Jump to page: 1 2
Thread overview
Force usage of double (instead of higher precision)
Jun 28, 2017
Simon Bürger
Jun 28, 2017
Stefan Koch
Jun 29, 2017
Stefan Koch
Jun 29, 2017
Simon Bürger
Jun 30, 2017
Luis
Jun 30, 2017
kinke
Jun 30, 2017
kinke
Jun 30, 2017
Stefan Koch
Jun 30, 2017
kinke
Jun 29, 2017
kinke
Jun 29, 2017
Simon Bürger
Jun 29, 2017
Stefan Koch
June 28, 2017
According to the standard (http://dlang.org/spec/float.html), the compiler is allowed to compute any floating-point statement in a higher precision than specified. Is there a way to deactivate this behaviour?

Context (reason why I need this): I am building a "double double" type, which essentially takes two 64-bit double-precision numbers to emulate a (nearly) quadruple-precision number. A simplified version looks something like this:

struct ddouble
{
    double high;
    double low;

    invariant
    {
        assert(high + low == high);
    }

    // ...implemententations of arithmetic operations...
}

Everything works fine at run-time, but if I declare a compile-time constant like

enum pi = ddouble(3.141592653589793116e+00, 1.224646799147353207e-16);

the invariant fails because it is evaluated using 80-bit "extended precision" during CTFE. All arithmetic operations rely on IEEE-conform double-precision, so everything breaks down if the compiler decides to replace them with higher precision. I am currently using LDC on 64-bit-Linux if that is relevant.

(If you are interested in the "double double" type, take a look here:
https://github.com/BrianSwift/MetalQD
which includes a double-double and even quad-double implementation in C/C++/Fortran)
June 28, 2017
On Wednesday, 28 June 2017 at 22:16:48 UTC, Simon Bürger wrote:

> (If you are interested in the "double double" type, take a look here:
> https://github.com/BrianSwift/MetalQD
> which includes a double-double and even quad-double implementation in C/C++/Fortran)

Nice work can you re or dual license under the boost license ?
I'd like to incorporate the qd type into newCTFE.

As for your problems they can be worked around.
by assigning every temporary to a variable.
Which will enforce the discarding of precision.
June 29, 2017
On Wednesday, 28 June 2017 at 23:56:42 UTC, Stefan Koch wrote:
>
> As for your problems they can be worked around.
> by assigning every temporary to a variable.
> Which will enforce the discarding of precision.

Sorry for the misinformation!
I was using the newCTFE fork which fixes this.
Indeed you'll have no way to get rid of the excess precision except for creating a function per sub-expression.

June 29, 2017
On Wednesday, 28 June 2017 at 22:16:48 UTC, Simon Bürger wrote:
> I am currently using LDC on 64-bit-Linux if that is relevant.

It is, as LDC on Windows/MSVC would use 64-bit compile-time reals. ;)

Changing it to double on other platforms is trivial if you compile LDC yourself. You'll want to use this alias: https://github.com/ldc-developers/ldc/blob/master/ddmd/root/ctfloat.d#L19, https://github.com/ldc-developers/ldc/blob/master/ddmd/root/ctfloat.h#L19
June 29, 2017
Thanks a lot for your comments.

On Wednesday, 28 June 2017 at 23:56:42 UTC, Stefan Koch wrote:
> [...]
>
> Nice work can you re or dual license under the boost license ?
> I'd like to incorporate the qd type into newCTFE.

The original work is not mine but traces back to http://crd-legacy.lbl.gov/~dhbailey/mpdist/ which is under a (modified) BSD license. I just posted the link for context, sorry for the confusion. Doing a port to D does not allow me to change the license even though I not a single line from the original would remain (I think?).

I might do a completely new D implementation (still based on the original authors research paper, not on the details of their code). But
1. I probably would only do a subset of functions I need for my work (i.e. double-double only, no quad-double, and only a limited set of trancendental functions).
2. Given that I have seen the original code, this might still be considered a "derivative work". I'm not sure, copyright-law is kinda confusing to me in these cases.

> Indeed you'll have no way to get rid of the excess precision except for creating a function per sub-expression.

No, doesn't seem to work. Here is a minimal breaking example:

double sum(double x, double y) { return x + y; }
bool equals(double x, double y) { return x == y; }

enum pi = ddouble(3.141592653589793116e+00, 1.224646799147353207e-16);

struct ddouble
{
	double hi, lo;

	invariant
	{
		if(!isNaN(hi) && !isNaN(lo))
			assert(equals(sum(hi, lo),  hi));
	}

	this(double hi, double lo)
	{
		this.hi = hi;
		this.lo = lo;
	}
}

But there are workarounds that seem to work:
1. remove the constructor (I think this means the invariant is not checked anymore?)
2. disable the invariant in ctfe (using "if(__ctfe) return;")
3. Don't use any ctfe (by replacing enum with immutable globals, initialized in "static this").

> I was using the newCTFE fork which fixes this.

Does this mean your new CTFE code (which is quite impressive work as far as I can tell), floating point no longer gets promoted to higher precision? That would be really good news for hackish floating-point code.

Honestly, this whole "compiler gets to decide which type to actually use" thing really bugs me. Kinda reminiscent of C/C++ integer types which could in principle be anything at all. I thought D had fixed this by specifying "int = 32-bit, long = 64-bit, float = IEEE-single-precision, double = IEEE-double-precision". Apparently not.

If I write "double", I would like to get IEEE-conform double-precision operations. If I wanted something depending on target-platform and compiler-optimization-level I would have used "real". Also this 80-bit-extended type is just a bad idea in general and should never be used (IMHO). Even on x86 processors, it only exists for backward-compatibility. No current instruction set (like SEE/AVX) supports it. Sorry for the long rant. But I am puzzled that the spec (https://dlang.org/spec/float.html) actually encourages double<->real convertions while at the same time it (rightfully) disallows "unsafe math optimizations" such as "x-x=0".
June 29, 2017
On Thursday, 29 June 2017 at 00:07:35 UTC, kinke wrote:
> On Wednesday, 28 June 2017 at 22:16:48 UTC, Simon Bürger wrote:
>> I am currently using LDC on 64-bit-Linux if that is relevant.
>
> It is, as LDC on Windows/MSVC would use 64-bit compile-time reals. ;)
>
> Changing it to double on other platforms is trivial if you compile LDC yourself. You'll want to use this alias: https://github.com/ldc-developers/ldc/blob/master/ddmd/root/ctfloat.d#L19, https://github.com/ldc-developers/ldc/blob/master/ddmd/root/ctfloat.h#L19

Huh, I will definitely look into this. This might be the most elegant solution. Thanks for the suggestion.
June 29, 2017
On Thursday, 29 June 2017 at 12:02:48 UTC, Simon Bürger wrote:
> On Thursday, 29 June 2017 at 00:07:35 UTC, kinke wrote:
>> On Wednesday, 28 June 2017 at 22:16:48 UTC, Simon Bürger wrote:
>>> I am currently using LDC on 64-bit-Linux if that is relevant.
>>
>> It is, as LDC on Windows/MSVC would use 64-bit compile-time reals. ;)
>>
>> Changing it to double on other platforms is trivial if you compile LDC yourself. You'll want to use this alias: https://github.com/ldc-developers/ldc/blob/master/ddmd/root/ctfloat.d#L19, https://github.com/ldc-developers/ldc/blob/master/ddmd/root/ctfloat.h#L19
>
> Huh, I will definitely look into this. This might be the most elegant solution. Thanks for the suggestion.

Required a custom build of the compiler for the library to work is rather inelegant imo.
However It might allow you to make progress the quickest.
Note that this only changes the type all ct-float-math is done at to double.
which means that know float and real will be double.
(Which is probably better then having float and double transform into 80bit reals)


June 30, 2017
On Thursday, 29 June 2017 at 12:00:53 UTC, Simon Bürger wrote:
> Thanks a lot for your comments.
>
> On Wednesday, 28 June 2017 at 23:56:42 UTC, Stefan Koch wrote:
>> [...]
>>

This is only happening on CTFE ? Enforcing to use the old 8086 FPU for any float/double operation would give a lot performance penalty on any modern CPU.


June 30, 2017
On Friday, 30 June 2017 at 11:42:39 UTC, Luis wrote:
> On Thursday, 29 June 2017 at 12:00:53 UTC, Simon Bürger wrote:
>> Thanks a lot for your comments.
>>
>> On Wednesday, 28 June 2017 at 23:56:42 UTC, Stefan Koch wrote:
>>> [...]
>>>
>
> This is only happening on CTFE ? Enforcing to use the old 8086 FPU for any float/double operation would give a lot performance penalty on any modern CPU.

CTFE only (incl. parsing of literals). Just make sure you don't happen to call a std.math function only accepting reals; I don't know how many of those are still around.
June 30, 2017
On Friday, 30 June 2017 at 16:21:18 UTC, kinke wrote:
> CTFE only (incl. parsing of literals). Just make sure you don't happen to call a std.math function only accepting reals; I don't know how many of those are still around.

Oh, apparently most still are. There are even some mean overloads for double/float only casting and forwarding to the `real` implementation.
« First   ‹ Prev
1 2