Thread overview
[D-runtime] FPU in core.time
Jan 16, 2012
Martin Nowak
Jan 16, 2012
Brad Roberts
Jan 16, 2012
Jonathan M Davis
Jan 16, 2012
Jonathan M Davis
Jan 16, 2012
Jonathan M Davis
Jan 16, 2012
Martin Nowak
January 16, 2012
There are some failing unittests in core.time.

core.time(1754):
     unittest
     {
         immutable curr = TickDuration.currSystemTick;
         TickDuration t1 = curr;
         immutable t2 = curr + curr;
         t1 *= 2;
         assert(t1 == t2);

         t1 = curr;
         t1 *= 2.0; //<- This relies on 80-bit arithmetic and might fail
since it is done on SSE
         assert(t1 == t2);
     }


core.time(1523):
     {
         enum unitsPerSec = convert!("seconds", units)(1);

         if(ticksPerSec >= unitsPerSec)
             return TickDuration(cast(long)(length * (ticksPerSec /
cast(real)unitsPerSec)));
         else
             return TickDuration(cast(long)(length / (unitsPerSec /
cast(real)ticksPerSec)));
     }

This fails it's unittest on my Windows machine due to limited precision
 from the double division.
The separate branches were originally used with integer arithmetic but it
seems to me that they
are no longer needed since the calculation is done in floating point now.
January 15, 2012
One of the checkins today made this a real problem.  Looking at the pull tester, many many of the failures are due to this.  The most recent linux 32/64 trunk build also failed with a time related failure.


On 1/15/2012 9:00 PM, Martin Nowak wrote:
> There are some failing unittests in core.time.
> 
> core.time(1754):
>     unittest
>     {
>         immutable curr = TickDuration.currSystemTick;
>         TickDuration t1 = curr;
>         immutable t2 = curr + curr;
>         t1 *= 2;
>         assert(t1 == t2);
> 
>         t1 = curr;
>         t1 *= 2.0; //<- This relies on 80-bit arithmetic and might fail since it is done on SSE
>         assert(t1 == t2);
>     }
> 
> 
> core.time(1523):
>     {
>         enum unitsPerSec = convert!("seconds", units)(1);
> 
>         if(ticksPerSec >= unitsPerSec)
>             return TickDuration(cast(long)(length * (ticksPerSec / cast(real)unitsPerSec)));
>         else
>             return TickDuration(cast(long)(length / (unitsPerSec / cast(real)ticksPerSec)));
>     }
> 
> This fails it's unittest on my Windows machine due to limited precision from the double division.
> The separate branches were originally used with integer arithmetic but it seems to me that they
> are no longer needed since the calculation is done in floating point now.
> _______________________________________________
> D-runtime mailing list
> D-runtime at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/d-runtime

January 15, 2012
On Monday, January 16, 2012 06:00:24 Martin Nowak wrote:
> There are some failing unittests in core.time.
> 
> core.time(1754):
>      unittest
>      {
>          immutable curr = TickDuration.currSystemTick;
>          TickDuration t1 = curr;
>          immutable t2 = curr + curr;
>          t1 *= 2;
>          assert(t1 == t2);
> 
>          t1 = curr;
>          t1 *= 2.0; //<- This relies on 80-bit arithmetic and might fail
> since it is done on SSE
>          assert(t1 == t2);
>      }

So, you can't rely on 2.0 * i being twice i anymore? I hate floating point values...

- Jonathan M Davis
January 15, 2012
On Monday, January 16, 2012 06:00:24 Martin Nowak wrote:
> There are some failing unittests in core.time.
> 
> core.time(1754):
>      unittest
>      {
>          immutable curr = TickDuration.currSystemTick;
>          TickDuration t1 = curr;
>          immutable t2 = curr + curr;
>          t1 *= 2;
>          assert(t1 == t2);
> 
>          t1 = curr;
>          t1 *= 2.0; //<- This relies on 80-bit arithmetic and might fail
> since it is done on SSE
>          assert(t1 == t2);
>      }

So, how far off can they be? Only by 1? Or can it be more? I'd think that it would just be 1 at the most, but given that it's a multiple of 2, I really would have thought that it would have been fine in the first place. So I don't know. But the normal trick of checking against something like 1e-5 doesn't make sense here, since TickDuration holds a long, not a floating point value.

- Jonath
January 16, 2012
On Sunday, January 15, 2012 22:56:30 Brad Roberts wrote:
> One of the checkins today made this a real problem.  Looking at the pull tester, many many of the failures are due to this.  The most recent linux 32/64 trunk build also failed with a time related failure.

I've made a commit which will hopefully fix the problem.

- Jonathan M Davis
January 16, 2012
On Mon, 16 Jan 2012 08:52:06 +0100, Jonathan M Davis <jmdavisProg at gmx.com> wrote:

> On Monday, January 16, 2012 06:00:24 Martin Nowak wrote:
>> There are some failing unittests in core.time.
>>
>> core.time(1754):
>>      unittest
>>      {
>>          immutable curr = TickDuration.currSystemTick;
>>          TickDuration t1 = curr;
>>          immutable t2 = curr + curr;
>>          t1 *= 2;
>>          assert(t1 == t2);
>>
>>          t1 = curr;
>>          t1 *= 2.0; //<- This relies on 80-bit arithmetic and might fail
>> since it is done on SSE
>>          assert(t1 == t2);
>>      }
>
> So, how far off can they be? Only by 1? Or can it be more? I'd think
> that it
> would just be 1 at the most, but given that it's a multiple of 2, I
> really
> would have thought that it would have been fine in the first place. So I
> don't
> know. But the normal trick of checking against something like 1e-5
> doesn't
> make sense here, since TickDuration holds a long, not a floating point
> value.
>
The intermediate calculation is done with 64-bit wide floats.
The mantissa has 53-bits so your integral gets rounded to that precision.
How much off your value is depends on how big you value is.
At maximum for long it is (2 ^^ (63 - 53)) / 2 = 512.

> - Jonath
> _______________________________________________
> D-runtime mailing list
> D-runtime at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/d-runtime