From: Robert Eachus <rieachus@comcast.net>
Subject: Re: Ada.Numerics, Accuracy of trigonometric functions
Date: Sat, 22 Oct 2016 15:38:58 -0700 (PDT)
Date: 2016-10-22T15:38:58-07:00 [thread overview]
Message-ID: <92d24324-3faa-4960-b138-1dd981fb9c0b@googlegroups.com> (raw)
In-Reply-To: <nt7sgs$1a06$1@gioia.aioe.org>
On Friday, October 7, 2016 at 6:13:50 AM UTC-4, Markus Schöpflin wrote:
> 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):
> 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?
Yes, you should report this as an error to AdaCore. The correct fix is to raise Constraint_Error, and mention why in the documentation. I'd like to raise Argument_Error, but even mentioning that possibility may result in lots more posts than the issue is worth.
I tried your program both with Short and Long_Float, and values of X up to 2**32 with and without scaling. The unscaled numbers worked up perfectly until 2**32 (see below). There seems to be some rounding somewhere in the scaled version. It's fine up to about 2**20. The unscaled numbers are accurate to 14 digits up until 2**32:
Size of Long_FLOAT = 64
Maximum relative error of COS = 4.44089209850063E-16
Angle threshold = 26
X**I = 1.00; COS(X**I) = 0.54030230586814; Scaled Cos = 0.54030230586814
X**I = 2.00; COS(X**I) = -0.41614683654714; Scaled Cos =-0.41614683654714
X**I = 4.00; COS(X**I) = -0.65364362086361; Scaled Cos =-0.65364362086361
X**I = 8.00; COS(X**I) = -0.14550003380861; Scaled Cos =-0.14550003380861
X**I = 16.00; COS(X**I) = -0.95765948032338; Scaled Cos =-0.95765948032338
X**I = 32.00; COS(X**I) = 0.83422336050651; Scaled Cos = 0.83422336050651
X**I = 64.00; COS(X**I) = 0.39185723042955; Scaled Cos = 0.39185723042955
X**I = 128.00; COS(X**I) = -0.69289582192017; Scaled Cos =-0.69289582192017
X**I = 256.00; COS(X**I) = -0.03979075993116; Scaled Cos =-0.03979075993116
X**I = 512.00; COS(X**I) = -0.99683339084820; Scaled Cos =-0.99683339084820
X**I = 1024.00; COS(X**I) = 0.98735361821985; Scaled Cos = 0.98735361821985
X**I = 2048.00; COS(X**I) = 0.94973433482365; Scaled Cos = 0.94973433482365
X**I = 4096.00; COS(X**I) = 0.80399061348585; Scaled Cos = 0.80399061348585
X**I = 8192.00; COS(X**I) = 0.29280181314670; Scaled Cos = 0.29280181314670
X**I = 16384.00; COS(X**I) = -0.82853419643601; Scaled Cos =-0.82853419643601
X**I = 32768.00; COS(X**I) = 0.37293782932771; Scaled Cos = 0.37293782932771
X**I = 65536.00; COS(X**I) = -0.72183475091266; Scaled Cos =-0.72183475091266
X**I = 131072.00; COS(X**I) = 0.04209081525030; Scaled Cos = 0.04209081525030
X**I = 262144.00; COS(X**I) = -0.99645672654313; Scaled Cos =-0.99645672654313
X**I = 524288.00; COS(X**I) = 0.98585201574610; Scaled Cos = 0.98585201574611
X**I = 1048576.00; COS(X**I) = 0.94380839390131; Scaled Cos = 0.94380839390132
X**I = 2097152.00; COS(X**I) = 0.78154856879715; Scaled Cos = 0.78154856879720
X**I = 4194304.00; COS(X**I) = 0.22163633077774; Scaled Cos = 0.22163633077789
X**I = 8388608.00; COS(X**I) = -0.90175467375876; Scaled Cos =-0.90175467375863
X**I = 16777216.00; COS(X**I) = 0.62632298329153; Scaled Cos = 0.62632298329196
X**I = 33554432.00; COS(X**I) = -0.21543904120159; Scaled Cos =-0.21543904120051
X**I = 67108864.00; COS(X**I) = -0.90717203905228; Scaled Cos =-0.90717203905196
X**I = 134217728.00; COS(X**I) = 0.64592221687655; Scaled Cos = 0.64592221687210
X**I = 268435456.00; COS(X**I) = -0.16556897949058; Scaled Cos =-0.16556897950206
X**I = 536870912.00; COS(X**I) = -0.94517382606090; Scaled Cos =-0.94517382605945
X**I = 1073741824.00; COS(X**I) = 0.78670712294119; Scaled Cos = 0.78670712290611
X**I = 2147483648.00; COS(X**I) = 0.23781619457280; Scaled Cos = 0.23781619446243
X**I = 4294967296.00; COS(X**I) = 1.00000000000000; Scaled Cos =-0.88688691530282
[2016-10-22 18:28:01] process terminated successfully, elapsed time: 00.34s
with ADA.NUMERICS.GENERIC_ELEMENTARY_FUNCTIONS;
with ADA.TEXT_IO; use ADA.TEXT_IO;
with ADA.Long_FLOAT_TEXT_IO; use ADA.Long_FLOAT_TEXT_IO;
procedure TEST_TRIG is
MRE_COS : constant := 2.0 * Long_FLOAT'MODEL_EPSILON;
THRESHOLD : constant := Long_FLOAT'MACHINE_MANTISSA / 2;
Pi : constant := Ada.Numerics.Pi;
Two_Pi : constant := Pi + Pi;
package EF is new ADA.NUMERICS.GENERIC_ELEMENTARY_FUNCTIONS (Long_FLOAT);
X : constant Long_FLOAT := 2.0;
Temp: Integer;
Y : constant Long_FLOAT := EF.COS (X);
begin
PUT_LINE ("Size of Long_FLOAT = " & POSITIVE'IMAGE (Long_FLOAT'SIZE));
PUT_LINE ("Maximum relative error of COS = " & Long_FLOAT'IMAGE (MRE_COS));
PUT_LINE ("Angle threshold = " & POSITIVE'IMAGE (THRESHOLD));
for I in 0..32 loop
PUT ("X**I = "); PUT (X**I, Fore => 10, Aft => 2, EXP => 0);
PUT ("; COS(X**I) = "); PUT (EF.Cos(X**I), EXP => 0);
Temp := Integer(X**I/(2.0*Pi));
Put ("; Scaled Cos =");
PUT (EF.Cos(Long_Float(Long_Long_Float(X**I)
- Long_Long_Float'(Long_Long_Float(Temp)*Two_Pi))), EXP => 0);
NEW_LINE;
end loop;
end TEST_TRIG;
prev parent reply other threads:[~2016-10-22 22:38 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
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 message]
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox