2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / gcc / testsuite / ada / acats / tests / cxg / cxg2004.a
blob2df296d3d42e5b0498a9803bdace1da87e5a7c80
1 -- CXG2004.A
2 --
3 -- Grant of Unlimited Rights
4 --
5 -- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
6 -- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
7 -- unlimited rights in the software and documentation contained herein.
8 -- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
9 -- this public release, the Government intends to confer upon all
10 -- recipients unlimited rights equal to those held by the Government.
11 -- These rights include rights to use, duplicate, release or disclose the
12 -- released technical data and computer software in whole or in part, in
13 -- any manner and for any purpose whatsoever, and to have or permit others
14 -- to do so.
16 -- DISCLAIMER
18 -- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
19 -- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
20 -- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
21 -- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
22 -- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
23 -- PARTICULAR PURPOSE OF SAID MATERIAL.
24 --*
26 -- OBJECTIVE:
27 -- Check that the sin and cos functions return
28 -- results that are within the error bound allowed.
30 -- TEST DESCRIPTION:
31 -- This test consists of a generic package that is
32 -- instantiated to check both float and a long float type.
33 -- The test for each floating point type is divided into
34 -- the following parts:
35 -- Special value checks where the result is a known constant.
36 -- Checks using an identity relationship.
38 -- SPECIAL REQUIREMENTS
39 -- The Strict Mode for the numerical accuracy must be
40 -- selected. The method by which this mode is selected
41 -- is implementation dependent.
43 -- APPLICABILITY CRITERIA:
44 -- This test applies only to implementations supporting the
45 -- Numerics Annex.
46 -- This test only applies to the Strict Mode for numerical
47 -- accuracy.
50 -- CHANGE HISTORY:
51 -- 13 FEB 96 SAIC Initial release for 2.1
52 -- 22 APR 96 SAIC Changed to generic implementation.
53 -- 18 AUG 96 SAIC Improvements to commentary.
54 -- 23 OCT 96 SAIC Exact results are not required unless the
55 -- cycle is specified.
56 -- 28 FEB 97 PWB.CTA Removed checks where cycle 2.0*Pi is specified
57 -- 02 JUN 98 EDS Revised calculations to ensure that X is exactly
58 -- three times Y per advice of numerics experts.
60 -- CHANGE NOTE:
61 -- According to Ken Dritz, author of the Numerics Annex of the RM,
62 -- one should never specify the cycle 2.0*Pi for the trigonometric
63 -- functions. In particular, if the machine number for the first
64 -- argument is not an exact multiple of the machine number for the
65 -- explicit cycle, then the specified exact results cannot be
66 -- reasonably expected. The affected checks in this test have been
67 -- marked as comments, with the additional notation "pwb-math".
68 -- Phil Brashear
69 --!
72 -- References:
74 -- Software Manual for the Elementary Functions
75 -- William J. Cody, Jr. and William Waite
76 -- Prentice-Hall, 1980
78 -- CRC Standard Mathematical Tables
79 -- 23rd Edition
81 -- Implementation and Testing of Function Software
82 -- W. J. Cody
83 -- Problems and Methodologies in Mathematical Software Production
84 -- editors P. C. Messina and A. Murli
85 -- Lecture Notes in Computer Science Volume 142
86 -- Springer Verlag, 1982
88 -- The sin and cos checks are translated directly from
89 -- the netlib FORTRAN code that was written by W. Cody.
92 with System;
93 with Report;
94 with Ada.Numerics.Generic_Elementary_Functions;
95 with Ada.Numerics.Elementary_Functions;
96 procedure CXG2004 is
97 Verbose : constant Boolean := False;
98 Number_Samples : constant := 1000;
100 -- CRC Standard Mathematical Tables; 23rd Edition; pg 738
101 Sqrt2 : constant :=
102 1.41421_35623_73095_04880_16887_24209_69807_85696_71875_37695;
103 Sqrt3 : constant :=
104 1.73205_08075_68877_29352_74463_41505_87236_69428_05253_81039;
106 Pi : constant := Ada.Numerics.Pi;
108 generic
109 type Real is digits <>;
110 package Generic_Check is
111 procedure Do_Test;
112 end Generic_Check;
114 package body Generic_Check is
115 package Elementary_Functions is new
116 Ada.Numerics.Generic_Elementary_Functions (Real);
118 function Sin (X : Real) return Real renames
119 Elementary_Functions.Sin;
120 function Cos (X : Real) return Real renames
121 Elementary_Functions.Cos;
122 function Sin (X, Cycle : Real) return Real renames
123 Elementary_Functions.Sin;
124 function Cos (X, Cycle : Real) return Real renames
125 Elementary_Functions.Cos;
127 Accuracy_Error_Reported : Boolean := False;
129 procedure Check (Actual, Expected : Real;
130 Test_Name : String;
131 MRE : Real) is
132 Rel_Error,
133 Abs_Error,
134 Max_Error : Real;
135 begin
137 -- In the case where the expected result is very small or 0
138 -- we compute the maximum error as a multiple of Model_Epsilon instead
139 -- of Model_Epsilon and Expected.
140 Rel_Error := MRE * abs Expected * Real'Model_Epsilon;
141 Abs_Error := MRE * Real'Model_Epsilon;
142 if Rel_Error > Abs_Error then
143 Max_Error := Rel_Error;
144 else
145 Max_Error := Abs_Error;
146 end if;
149 -- in addition to the relative error checks we apply the
150 -- criteria of G.2.4(16)
151 if abs (Actual) > 1.0 then
152 Accuracy_Error_Reported := True;
153 Report.Failed (Test_Name & " result > 1.0");
154 elsif abs (Actual - Expected) > Max_Error then
155 Accuracy_Error_Reported := True;
156 Report.Failed (Test_Name &
157 " actual: " & Real'Image (Actual) &
158 " expected: " & Real'Image (Expected) &
159 " difference: " &
160 Real'Image (Actual - Expected) &
161 " mre:" &
162 Real'Image (Max_Error) );
163 elsif Verbose then
164 if Actual = Expected then
165 Report.Comment (Test_Name & " exact result");
166 else
167 Report.Comment (Test_Name & " passed");
168 end if;
169 end if;
170 end Check;
173 procedure Sin_Check (A, B : Real;
174 Arg_Range : String) is
175 -- test a selection of
176 -- arguments selected from the range A to B.
178 -- This test uses the identity
179 -- sin(x) = sin(x/3)*(3 - 4 * sin(x/3)**2)
181 -- Note that in this test we must take into account the
182 -- error in the calculation of the expected result so
183 -- the maximum relative error is larger than the
184 -- accuracy required by the ARM.
186 X, Y, ZZ : Real;
187 Actual, Expected : Real;
188 MRE : Real;
189 Ran : Real;
190 begin
191 Accuracy_Error_Reported := False; -- reset
192 for I in 1 .. Number_Samples loop
193 -- Evenly distributed selection of arguments
194 Ran := Real (I) / Real (Number_Samples);
196 -- make sure x and x/3 are both exactly representable
197 -- on the machine. See "Implementation and Testing of
198 -- Function Software" page 44.
199 X := (B - A) * Ran + A;
200 Y := Real'Leading_Part
201 ( X/3.0,
202 Real'Machine_Mantissa - Real'Exponent (3.0) );
203 X := Y * 3.0;
205 Actual := Sin (X);
207 ZZ := Sin(Y);
208 Expected := ZZ * (3.0 - 4.0 * ZZ * ZZ);
210 -- note that since the expected value is computed, we
211 -- must take the error in that computation into account.
212 -- See Cody pp 139-141.
213 MRE := 4.0;
215 Check (Actual, Expected,
216 "sin test of range" & Arg_Range &
217 Integer'Image (I),
218 MRE);
219 exit when Accuracy_Error_Reported;
220 end loop;
221 exception
222 when Constraint_Error =>
223 Report.Failed
224 ("Constraint_Error raised in sin check");
225 when others =>
226 Report.Failed ("exception in sin check");
227 end Sin_Check;
231 procedure Cos_Check (A, B : Real;
232 Arg_Range : String) is
233 -- test a selection of
234 -- arguments selected from the range A to B.
236 -- This test uses the identity
237 -- cos(x) = cos(x/3)*(4 * cos(x/3)**2 - 3)
239 -- Note that in this test we must take into account the
240 -- error in the calculation of the expected result so
241 -- the maximum relative error is larger than the
242 -- accuracy required by the ARM.
244 X, Y, ZZ : Real;
245 Actual, Expected : Real;
246 MRE : Real;
247 Ran : Real;
248 begin
249 Accuracy_Error_Reported := False; -- reset
250 for I in 1 .. Number_Samples loop
251 -- Evenly distributed selection of arguments
252 Ran := Real (I) / Real (Number_Samples);
254 -- make sure x and x/3 are both exactly representable
255 -- on the machine. See "Implementation and Testing of
256 -- Function Software" page 44.
257 X := (B - A) * Ran + A;
258 Y := Real'Leading_Part
259 ( X/3.0,
260 Real'Machine_Mantissa - Real'Exponent (3.0) );
261 X := Y * 3.0;
263 Actual := Cos (X);
265 ZZ := Cos(Y);
266 Expected := ZZ * (4.0 * ZZ * ZZ - 3.0);
268 -- note that since the expected value is computed, we
269 -- must take the error in that computation into account.
270 -- See Cody pp 141-143.
271 MRE := 6.0;
273 Check (Actual, Expected,
274 "cos test of range" & Arg_Range &
275 Integer'Image (I),
276 MRE);
277 exit when Accuracy_Error_Reported;
278 end loop;
279 exception
280 when Constraint_Error =>
281 Report.Failed
282 ("Constraint_Error raised in cos check");
283 when others =>
284 Report.Failed ("exception in cos check");
285 end Cos_Check;
288 procedure Special_Angle_Checks is
289 type Data_Point is
290 record
291 Degrees,
292 Radians,
293 Sine,
294 Cosine : Real;
295 Sin_Result_Error,
296 Cos_Result_Error : Boolean;
297 end record;
299 type Test_Data_Type is array (Positive range <>) of Data_Point;
301 -- the values in the following table only involve static
302 -- expressions to minimize any loss of precision. However,
303 -- there are two sources of error that must be accounted for
304 -- in the following tests.
305 -- First, when a cycle is not specified there can be a roundoff
306 -- error in the value of Pi used. This error does not apply
307 -- when a cycle of 2.0 * Pi is explicitly provided.
308 -- Second, the expected results that involve sqrt values also
309 -- have a potential roundoff error.
310 -- The amount of error due to error in the argument is computed
311 -- as follows:
312 -- sin(x+err) = sin(x)*cos(err) + cos(x)*sin(err)
313 -- ~= sin(x) + err * cos(x)
314 -- similarly for cos the error due to error in the argument is
315 -- computed as follows:
316 -- cos(x+err) = cos(x)*cos(err) - sin(x)*sin(err)
317 -- ~= cos(x) - err * sin(x)
318 -- In both cases the term "err" is bounded by 0.5 * argument.
320 Test_Data : constant Test_Data_Type := (
321 -- degrees radians sine cosine sin_er cos_er test #
322 ( 0.0, 0.0, 0.0, 1.0, False, False ), -- 1
323 ( 30.0, Pi/6.0, 0.5, Sqrt3/2.0, False, True ), -- 2
324 ( 60.0, Pi/3.0, Sqrt3/2.0, 0.5, True, False ), -- 3
325 ( 90.0, Pi/2.0, 1.0, 0.0, False, False ), -- 4
326 (120.0, 2.0*Pi/3.0, Sqrt3/2.0, -0.5, True, False ), -- 5
327 (150.0, 5.0*Pi/6.0, 0.5, -Sqrt3/2.0, False, True ), -- 6
328 (180.0, Pi, 0.0, -1.0, False, False ), -- 7
329 (210.0, 7.0*Pi/6.0, -0.5, -Sqrt3/2.0, False, True ), -- 8
330 (240.0, 8.0*Pi/6.0, -Sqrt3/2.0, -0.5, True, False ), -- 9
331 (270.0, 9.0*Pi/6.0, -1.0, 0.0, False, False ), -- 10
332 (300.0, 10.0*Pi/6.0, -Sqrt3/2.0, 0.5, True, False ), -- 11
333 (330.0, 11.0*Pi/6.0, -0.5, Sqrt3/2.0, False, True ), -- 12
334 (360.0, 2.0*Pi, 0.0, 1.0, False, False ), -- 13
335 ( 45.0, Pi/4.0, Sqrt2/2.0, Sqrt2/2.0, True, True ), -- 14
336 (135.0, 3.0*Pi/4.0, Sqrt2/2.0, -Sqrt2/2.0, True, True ), -- 15
337 (225.0, 5.0*Pi/4.0, -Sqrt2/2.0, -Sqrt2/2.0, True, True ), -- 16
338 (315.0, 7.0*Pi/4.0, -Sqrt2/2.0, Sqrt2/2.0, True, True ), -- 17
339 (405.0, 9.0*Pi/4.0, Sqrt2/2.0, Sqrt2/2.0, True, True ) ); -- 18
342 Y : Real;
343 Sin_Arg_Err,
344 Cos_Arg_Err,
345 Sin_Result_Err,
346 Cos_Result_Err : Real;
347 begin
348 for I in Test_Data'Range loop
349 -- compute error components
350 Sin_Arg_Err := abs Test_Data (I).Cosine *
351 abs Test_Data (I).Radians / 2.0;
352 Cos_Arg_Err := abs Test_Data (I).Sine *
353 abs Test_Data (I).Radians / 2.0;
355 if Test_Data (I).Sin_Result_Error then
356 Sin_Result_Err := 0.5;
357 else
358 Sin_Result_Err := 0.0;
359 end if;
361 if Test_Data (I).Cos_Result_Error then
362 Cos_Result_Err := 1.0;
363 else
364 Cos_Result_Err := 0.0;
365 end if;
369 Y := Sin (Test_Data (I).Radians);
370 Check (Y, Test_Data (I).Sine,
371 "test" & Integer'Image (I) & " sin(r)",
372 2.0 + Sin_Arg_Err + Sin_Result_Err);
373 Y := Cos (Test_Data (I).Radians);
374 Check (Y, Test_Data (I).Cosine,
375 "test" & Integer'Image (I) & " cos(r)",
376 2.0 + Cos_Arg_Err + Cos_Result_Err);
377 Y := Sin (Test_Data (I).Degrees, 360.0);
378 Check (Y, Test_Data (I).Sine,
379 "test" & Integer'Image (I) & " sin(d,360)",
380 2.0 + Sin_Result_Err);
381 Y := Cos (Test_Data (I).Degrees, 360.0);
382 Check (Y, Test_Data (I).Cosine,
383 "test" & Integer'Image (I) & " cos(d,360)",
384 2.0 + Cos_Result_Err);
385 --pwb-math Y := Sin (Test_Data (I).Radians, 2.0*Pi);
386 --pwb-math Check (Y, Test_Data (I).Sine,
387 --pwb-math "test" & Integer'Image (I) & " sin(r,2pi)",
388 --pwb-math 2.0 + Sin_Result_Err);
389 --pwb-math Y := Cos (Test_Data (I).Radians, 2.0*Pi);
390 --pwb-math Check (Y, Test_Data (I).Cosine,
391 --pwb-math "test" & Integer'Image (I) & " cos(r,2pi)",
392 --pwb-math 2.0 + Cos_Result_Err);
393 end loop;
394 exception
395 when Constraint_Error =>
396 Report.Failed ("Constraint_Error raised in special angle test");
397 when others =>
398 Report.Failed ("exception in special angle test");
399 end Special_Angle_Checks;
402 -- check the rule of A.5.1(41);6.0 which requires that the
403 -- result be exact if the mathematical result is 0.0, 1.0,
404 -- or -1.0
405 procedure Exact_Result_Checks is
406 type Data_Point is
407 record
408 Degrees,
409 Sine,
410 Cosine : Real;
411 end record;
413 type Test_Data_Type is array (Positive range <>) of Data_Point;
414 Test_Data : constant Test_Data_Type := (
415 -- degrees sine cosine test #
416 ( 0.0, 0.0, 1.0 ), -- 1
417 ( 90.0, 1.0, 0.0 ), -- 2
418 (180.0, 0.0, -1.0 ), -- 3
419 (270.0, -1.0, 0.0 ), -- 4
420 (360.0, 0.0, 1.0 ), -- 5
421 ( 90.0 + 360.0, 1.0, 0.0 ), -- 6
422 (180.0 + 360.0, 0.0, -1.0 ), -- 7
423 (270.0 + 360.0,-1.0, 0.0 ), -- 8
424 (360.0 + 360.0, 0.0, 1.0 ) ); -- 9
426 Y : Real;
427 begin
428 for I in Test_Data'Range loop
429 Y := Sin (Test_Data(I).Degrees, 360.0);
430 if Y /= Test_Data(I).Sine then
431 Report.Failed ("exact result for sin(" &
432 Real'Image (Test_Data(I).Degrees) &
433 ", 360.0) is not" &
434 Real'Image (Test_Data(I).Sine) &
435 " Difference is " &
436 Real'Image (Y - Test_Data(I).Sine) );
437 end if;
439 Y := Cos (Test_Data(I).Degrees, 360.0);
440 if Y /= Test_Data(I).Cosine then
441 Report.Failed ("exact result for cos(" &
442 Real'Image (Test_Data(I).Degrees) &
443 ", 360.0) is not" &
444 Real'Image (Test_Data(I).Cosine) &
445 " Difference is " &
446 Real'Image (Y - Test_Data(I).Cosine) );
447 end if;
448 end loop;
449 exception
450 when Constraint_Error =>
451 Report.Failed ("Constraint_Error raised in exact result check");
452 when others =>
453 Report.Failed ("exception in exact result check");
454 end Exact_Result_Checks;
457 procedure Do_Test is
458 begin
459 Special_Angle_Checks;
460 Sin_Check (0.0, Pi/2.0, "0..pi/2");
461 Sin_Check (6.0*Pi, 6.5*Pi, "6pi..6.5pi");
462 Cos_Check (7.0*Pi, 7.5*Pi, "7pi..7.5pi");
463 Exact_Result_Checks;
464 end Do_Test;
465 end Generic_Check;
467 -----------------------------------------------------------------------
468 -----------------------------------------------------------------------
470 package Float_Check is new Generic_Check (Float);
472 -- check the floating point type with the most digits
473 type A_Long_Float is digits System.Max_Digits;
474 package A_Long_Float_Check is new Generic_Check (A_Long_Float);
476 -----------------------------------------------------------------------
477 -----------------------------------------------------------------------
480 begin
481 Report.Test ("CXG2004",
482 "Check the accuracy of the sin and cos functions");
484 if Verbose then
485 Report.Comment ("checking Standard.Float");
486 end if;
488 Float_Check.Do_Test;
490 if Verbose then
491 Report.Comment ("checking a digits" &
492 Integer'Image (System.Max_Digits) &
493 " floating point type");
494 end if;
496 A_Long_Float_Check.Do_Test;
498 Report.Result;
499 end CXG2004;