On 26/04/2020 18:41, Segher Boessenkool wrote:
> On Sun, Apr 26, 2020 at 10:38:57AM +0200, Iain Buclaw wrote:
>> On 25/04/2020 22:50, Segher Boessenkool wrote:
>>> On Sat, Apr 25, 2020 at 02:20:19AM +0200, Iain Buclaw via Gcc-patches wrote:
>>>> +            // Parse DoubleDoubles as a pair of doubles.
>>>> +            // The layout of the type is:
>>>> +            //
>>>> +            //   [1|  7  |       56      ][   8    |       56       ]
>>>> +            //   [S| Exp | Fraction (hi) ][ Unused | Fraction (low) ]
>>>> +            //
>>>> +            // We can get the least significant bits by subtracting the 
>>>> IEEE
>>>> +            // double precision portion from the real value.
>>>
>>> That's not correct.  There is no "Unused" field, and the lower fraction
>>> is not always an immediate extension of the higher fraction.
>>>
>>> (It's not 1,7,56 -- it is 1,11,52).
>>
>> Thanks, I did a quick look-up of where the original might have came
>> from, and I've found another extended floating point format of IBM.
>> I'll send the correction upstream.
>>
>>> A "double double" is really a pair of double precision numbers, both
>>> with sign and exponent fields.  If the first number has maximum
>>> exponent (so, it is infinity or a NaN), the second number is not
>>> significant; otherwise, the sum of the two numbers (taken as exact
>>> numbers, no rounding, no truncation, etc.) is the represented number.
>>> The first number should be that, rounded to double precision.
>>>
>>> So the second double does "add fraction bits" somewhat like this, but
>>> there is an implicit leading 1, for normal numbers, and there can be a
>>> gap between the two halves, too (like in 0x1p0 + 0x1p-100).
>>
>> The job of this routine is to pry out the byte representation of real
>> (long double) values at compile-time for hashing-related purposes.
>>
>> As zero, infinity and NaN are already handled, unless a mismatch between
>> compile and run-time computed hashes is found (I haven't seen any
>> unit-tests trigger failures in the testsuite), I don't think that there
>> is any immediate problem with the current implementation.
>>
>> Thanks for the information though.
> 
> All bits are significant to the value, there are no unused bits, for
> most values.  The sign and exponent of the second number are very much
> relevant, in general.
> 
> I didn't look at your actual implementation, just this comment, but it
> sounds like your tests miss a lot of cases, if no problems were found?
> 

All these tests pass.  That is, the computed compile-time byte layout
(the result of this function) is the same as the layout at run-time.

Don't mind that these are all strings, they are all passed to mixin().

/**Test special values*/
testNumberConvert!("-real.infinity");
testNumberConvert!("real.infinity");
testNumberConvert!("-0.0L");
testNumberConvert!("0.0L");
testNumberConvert!("real.nan");

/**Test min and max values values*/
testNumberConvert!("real.min_normal");
testNumberConvert!("real.max");

/**Test common values*/
testNumberConvert!("-0.17L");
testNumberConvert!("3.14L");

/**Test immutable and const*/
testNumberConvert!("cast(const)3.14L");
testNumberConvert!("cast(immutable)3.14L");

/**Test denormalized values*/
testNumberConvert!("real.min_normal/2");
testNumberConvert!("real.min_normal/2UL^^63");

// check subnormal storage edge case for Quadruple
testNumberConvert!("real.min_normal/2UL^^56");
testNumberConvert!("real.min_normal/19");
testNumberConvert!("real.min_normal/17");

/**Test imaginary values: convert algorithm is same with real values*/
testNumberConvert!("0.0Li");

/**True random values*/
testNumberConvert!("-0x9.0f7ee55df77618fp-13829L");
testNumberConvert!("0x7.36e6e2640120d28p+8797L");
testNumberConvert!("-0x1.05df6ce4702ccf8p+15835L");
testNumberConvert!("0x9.54bb0d88806f714p-7088L");

/**Big overflow or underflow*/
testNumberConvert!("cast(double)-0x9.0f7ee55df77618fp-13829L");
testNumberConvert!("cast(double)0x7.36e6e2640120d28p+8797L");
testNumberConvert!("cast(double)-0x1.05df6ce4702ccf8p+15835L");
testNumberConvert!("cast(double)0x9.54bb0d88806f714p-7088L");
testNumberConvert!("cast(float)-0x9.0f7ee55df77618fp-13829L");
testNumberConvert!("cast(float)0x7.36e6e2640120d28p+8797L");

Iain.

Reply via email to