comp.lang.ada
 help / color / mirror / Atom feed
* Ada.Numerics, Accuracy of trigonometric functions
@ 2016-10-07 10:13 Markus Schöpflin
  2016-10-07 10:23 ` Markus Schöpflin
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Markus Schöpflin @ 2016-10-07 10:13 UTC (permalink / raw)


The following tests have been performed using GNAT 7.4 on a 64bit Linux system.

I'm puzzled by the seemingly bad accuracy of calling COS on a large value of 
type Short_Float.

Given the following procedure which calculates y1 = cos(2**32) and y2 = 
cos(2**32 mod 2*PI):

---%<---
with ADA.NUMERICS.GENERIC_ELEMENTARY_FUNCTIONS;

with ADA.TEXT_IO; use ADA.TEXT_IO;
with ADA.SHORT_FLOAT_TEXT_IO; use ADA.SHORT_FLOAT_TEXT_IO;

procedure TEST_TRIG is

    MRE_COS : constant := 2.0 * SHORT_FLOAT'MODEL_EPSILON;
    THRESHOLD : constant := SHORT_FLOAT'MACHINE_MANTISSA / 2;

    package EF is new ADA.NUMERICS.GENERIC_ELEMENTARY_FUNCTIONS (SHORT_FLOAT);

    X : constant SHORT_FLOAT := 2.0**32;
    Y : constant SHORT_FLOAT := EF.COS (X);

begin

    PUT_LINE ("Size of SHORT_FLOAT = " & POSITIVE'IMAGE (SHORT_FLOAT'SIZE));
    PUT_LINE ("Maximum relative error of COS = " & SHORT_FLOAT'IMAGE (MRE_COS));
    PUT_LINE ("Angle threshold = " & POSITIVE'IMAGE (THRESHOLD));

    PUT ("X = ");        PUT (X, EXP => 0);
    PUT ("; COS(X) = "); PUT (Y, EXP => 0);
    NEW_LINE;

end TEST_TRIG;
--->%---

The (for me surprising result is):

---%<---
Size of SHORT_FLOAT =  32
Maximum relative error of COS =  2.38419E-07
Angle threshold =  12
X = 4294967296.00000; COS(X) =  1.00000      <-- WHAT?
--->%---

The corresponding C program:

---%<---
#include <math.h>
#include <stdio.h>

int main() {

   float x = exp2f(32.0);

   printf("sizeof(float) = %lu\n", sizeof(float));
   printf("x = %f; cos(x) = %f\n", x, cosf(x));

   return 0;
}
--->%---

gives:

---%<---
sizeof(float) = 4
x = 4294967296.000000; cos(x) = -0.886887    <--- OK
--->%---

Now, why is the error on cos(2**32) so large in this case? I am aware that I'm 
way beyond the required angle threshold mentioned in G.2.4(12), so it's up to 
the compiler to decide on the accuracy.

Looking at the implementation defined characteristics for GNAT, I find that 
strict mode is on by default, so G.2.4 should apply. For G.2.4(10) the 
documentation states (for the value of the angle threshold and the accuracy 
beyond the threshold): "Information on this subject is not yet available.".

So in principle the compiler is free to give me any answer once I'm beyond the 
minimum required angle threshold, which is about 12 for short float.

But if I understand G.2.4(10) correctly, cos(x1, cycle=>2*PI) should give me 
an answer within the maximum relative error, but this is not the case either, 
as EF.COS (X, CYCLE => TWO_PI) gives 0.33575.

Now for the questions: Is my reasoning above correct? Why does using the cycle 
parameter not help? Do other Ada compilers give the same bad result in this 
case? Should I report this as an error to AdaCore?

TIA,
Markus

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2016-10-22 22:38 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-07 10:13 Ada.Numerics, Accuracy of trigonometric functions Markus Schöpflin
2016-10-07 10:23 ` Markus Schöpflin
2016-10-07 10:23 ` Brian Drummond
2016-10-07 10:40   ` Markus Schöpflin
2016-10-07 14:52 ` Dennis Lee Bieber
2016-10-07 15:19   ` Markus Schöpflin
2016-10-07 22:15     ` Dennis Lee Bieber
2016-10-07 16:38 ` Jeffrey R. Carter
2016-10-10  7:44   ` Markus Schöpflin
2016-10-22 22:38 ` Robert Eachus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox