[fpc-devel] Broken frac function in FPC3.1.1 / Windows x86_64

Thorsten Engler thorsten.engler at gmx.net
Sat Apr 28 13:01:24 CEST 2018


> -----Original Message-----
> From: fpc-devel <fpc-devel-bounces at lists.freepascal.org> On Behalf
> Of Sven Barth via fpc-devel

> Thorsten, do you have tests that could go with the new
> Frac() implementation? Something simply that checks the results and
> does a Halt() if something is wrong would be sufficent.

I was using the following to verify my implementation while writing it (and if I had remembered to actually run it again instead of making the rol to shl change only when posting the source here, I would have noticed my little oops sooner :/ ):

    Assert(Frac1(1) = 0);
    Assert(Frac1(1e15+0.5) = 0.5);
    Assert(Frac1(1e16+0.5) = 0);
    Assert(Frac1(0.5) = 0.5);
    Assert(Frac1(-1) = 0);
    Assert(Frac1(-1e15-0.5) = -0.5);
    Assert(Frac1(-1e16-0.5) = 0);
    Assert(Frac1(-0.5) = -0.5);

Not sure what exact format you want, but I'm sure you can adapt that as needed.

> This way I
> can be sure that my conversion to FPC's syntax will be correct.

I also used this to verify that my implementation produces the same output as Delphi:

    Assert(Frac1(1) = Frac(1));
    Assert(Frac1(1e15+0.5) = Frac(1e15+0.5) );
    Assert(Frac1(1e16+0.5) = Frac(1e16+0.5) );
    Assert(Frac1(0.5) = Frac(0.5));
    Assert(Frac1(-1) = Frac(-1));
    Assert(Frac1(-1e15-0.5) = Frac(-1e15-0.5));
    Assert(Frac1(-1e16-0.5) = Frac(-1e16-0.5));
    Assert(Frac1(-0.5) = Frac(-0.5));

> Oh, and before I forget it: would you *please* stop top posting?
Oh, sure. No worries. Standards about that vary from community to community...


The effects of code alignment beyond a granularity of 16 on such short code is interesting:

Code address:
Frac1: 0000000000536430 (48)
Frac2: 0000000000536480 (0)
Frac3: 00000000005364D0 (80)
Frac4: 0000000000536520 (32)
Frac5: 0000000000536570 (112)
Frac6: 00000000005365C0 (64)
Frac7: 0000000000536610 (16)
Frac8: 0000000000536660 (96)

1st run:
In range (1e15+0.5):
Frac 1872424
Frac1 1292064
Frac2 1302669
Frac3 1315819
Frac4 1301370
Frac5 1305682
Frac6 1288991
Frac7 1312695
Frac8 1294104

Out of range (1e16+0.5):
Frac 1605912
Frac1 1081226
Frac2 892385
Frac3 1078618
Frac4 888650
Frac5 1077251
Frac6 1096165
Frac7 1072769
Frac8 882501

Only fraction (0.5):
Frac 1638980
Frac1 990573
Frac2 893984
Frac3 989789
Frac4 884970
Frac5 975254
Frac6 986453
Frac7 983450
Frac8 877745

The number in () after the address is address mod 128.

It's interesting to see that for this particular code (and CPU) the "good" ones are 0, 32, and 96, but NOT 64. I'm sure the results are highly dependent on the CPU.

Also, you can see that no matter what the alignment, it beats Delphi's 64bit Frac implementation by a good margin.







More information about the fpc-devel mailing list