t_sincos.c revision 1.1 1 /* $NetBSD: t_sincos.c,v 1.1 2022/08/27 08:31:58 christos Exp $ */
2
3 /*-
4 * Copyright (c) 2011, 2022 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jukka Ruohonen and Christos Zoulas
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <assert.h>
33 #include <atf-c.h>
34 #include <float.h>
35 #include <math.h>
36 #include <stdio.h>
37
38 static const struct {
39 int angle;
40 double x;
41 double y;
42 float fy;
43 } sin_angles[] = {
44 // { -360, -6.283185307179586, 2.4492935982947064e-16, -1.7484555e-07 },
45 { -180, -3.141592653589793, -1.2246467991473532e-16, 8.7422777e-08 },
46 { -135, -2.356194490192345, -0.7071067811865476, 999 },
47 // { -90, -1.570796326794897, -1.0000000000000000, 999 },
48 { -45, -0.785398163397448, -0.7071067811865472, 999 },
49 { 0, 0.000000000000000, 0.0000000000000000, 999 },
50 { 30, 0.5235987755982989, 0.5000000000000000, 999 },
51 { 45, 0.785398163397448, 0.7071067811865472, 999 },
52 // { 60, 1.047197551196598, 0.8660254037844388, 999 },
53 { 90, 1.570796326794897, 1.0000000000000000, 999 },
54 // { 120, 2.094395102393195, 0.8660254037844389, 999 },
55 { 135, 2.356194490192345, 0.7071067811865476, 999 },
56 { 150, 2.617993877991494, 0.5000000000000003, 999 },
57 { 180, 3.141592653589793, 1.2246467991473532e-16, -8.7422777e-08 },
58 { 270, 4.712388980384690, -1.0000000000000000, 999 },
59 { 360, 6.283185307179586, -2.4492935982947064e-16, 1.7484555e-07 },
60 };
61
62 static const struct {
63 int angle;
64 double x;
65 double y;
66 float fy;
67 } cos_angles[] = {
68 { -180, -3.141592653589793, -1.0000000000000000, 999 },
69 { -135, -2.356194490192345, -0.7071067811865476, 999 },
70 // { -90, -1.5707963267948966, 6.123233995736766e-17, -4.3711388e-08 },
71 // { -90, -1.5707963267948968, -1.6081226496766366e-16, -4.3711388e-08 },
72 { -45, -0.785398163397448, 0.7071067811865478, 999 },
73 { 0, 0.000000000000000, 1.0000000000000000, 999 },
74 { 30, 0.5235987755982989, 0.8660254037844386, 999 },
75 { 45, 0.785398163397448, 0.7071067811865478, 999 },
76 // { 60, 1.0471975511965976, 0.5000000000000001, 999 },
77 // { 60, 1.0471975511965979, 0.4999999999999999, 999 },
78 { 90, 1.570796326794897, -3.8285686989269494e-16, -4.3711388e-08 },
79 // { 120, 2.0943951023931953, -0.4999999999999998, 999 },
80 // { 120, 2.0943951023931957, -0.5000000000000002, 999 },
81 { 135, 2.356194490192345, -0.7071067811865476, 999 },
82 { 150, 2.617993877991494, -0.8660254037844386, 999 },
83 { 180, 3.141592653589793, -1.0000000000000000, 999 },
84 { 270, 4.712388980384690, -1.8369701987210297e-16, 1.1924881e-08 },
85 { 360, 6.283185307179586, 1.0000000000000000, 999 },
86 };
87
88 #ifdef __HAVE_LONG_DOUBLE
89 /*
90 * sincosl(3)
91 */
92 ATF_TC(sincosl_angles);
93 ATF_TC_HEAD(sincosl_angles, tc)
94 {
95 atf_tc_set_md_var(tc, "descr", "Test some selected angles");
96 }
97
98 ATF_TC_BODY(sincosl_angles, tc)
99 {
100 /*
101 * XXX The given data is for double, so take that
102 * into account and expect less precise results..
103 */
104 const long double eps = DBL_EPSILON;
105 size_t i;
106
107 ATF_CHECK(__arraycount(sin_angles) == __arraycount(cos_angles));
108
109 for (i = 0; i < __arraycount(sin_angles); i++) {
110 ATF_CHECK_MSG(sin_angles[i].angle == cos_angles[i].angle,
111 "%zu %d %d", i, sin_angles[i].angle, cos_angles[i].angle);
112 int deg = sin_angles[i].angle;
113 ATF_CHECK_MSG(sin_angles[i].x == cos_angles[i].x,
114 "%zu %g %g", i, sin_angles[i].x, cos_angles[i].x);
115 long double theta = sin_angles[i].x;
116 long double sin_theta = sin_angles[i].y;
117 long double cos_theta = cos_angles[i].y;
118 long double s, c;
119
120 sincosl(theta, &s, &c);
121
122 if (fabsl((s - sin_theta)/sin_theta) > eps) {
123 atf_tc_fail_nonfatal("sin(%d deg = %.17Lg) = %.17Lg"
124 " != %.17Lg",
125 deg, theta, s, sin_theta);
126 }
127 if (fabsl((c - cos_theta)/cos_theta) > eps) {
128 atf_tc_fail_nonfatal("cos(%d deg = %.17Lg) = %.17Lg"
129 " != %.17Lg",
130 deg, theta, c, cos_theta);
131 }
132 }
133 }
134
135 ATF_TC(sincosl_nan);
136 ATF_TC_HEAD(sincosl_nan, tc)
137 {
138 atf_tc_set_md_var(tc, "descr", "Test sincosl(NaN) == (NaN, NaN)");
139 }
140
141 ATF_TC_BODY(sincosl_nan, tc)
142 {
143 const long double x = 0.0L / 0.0L;
144 long double s, c;
145
146 sincosl(x, &s, &c);
147 ATF_CHECK(isnan(x) && isnan(s) && isnan(c));
148 }
149
150 ATF_TC(sincosl_inf_neg);
151 ATF_TC_HEAD(sincosl_inf_neg, tc)
152 {
153 atf_tc_set_md_var(tc, "descr", "Test sincosl(-Inf) == (NaN, NaN)");
154 }
155
156 ATF_TC_BODY(sincosl_inf_neg, tc)
157 {
158 const long double x = -1.0L / 0.0L;
159 long double s, c;
160
161 sincosl(x, &s, &c);
162 ATF_CHECK(isnan(s) && isnan(c));
163 }
164
165 ATF_TC(sincosl_inf_pos);
166 ATF_TC_HEAD(sincosl_inf_pos, tc)
167 {
168 atf_tc_set_md_var(tc, "descr", "Test sincosl(+Inf) == (NaN, NaN)");
169 }
170
171 ATF_TC_BODY(sincosl_inf_pos, tc)
172 {
173 const long double x = 1.0L / 0.0L;
174 long double s, c;
175
176 sincosl(x, &s, &c);
177 ATF_CHECK(isnan(s) && isnan(c));
178 }
179
180
181 ATF_TC(sincosl_zero_neg);
182 ATF_TC_HEAD(sincosl_zero_neg, tc)
183 {
184 atf_tc_set_md_var(tc, "descr", "Test sincosl(-0.0) == (0.0, 1.0)");
185 }
186
187 ATF_TC_BODY(sincosl_zero_neg, tc)
188 {
189 const long double x = -0.0L;
190 long double s, c;
191
192 sincosl(x, &s, &c);
193 ATF_CHECK(s == 0.0 && c == 1.0);
194 }
195
196 ATF_TC(sincosl_zero_pos);
197 ATF_TC_HEAD(sincosl_zero_pos, tc)
198 {
199 atf_tc_set_md_var(tc, "descr", "Test sincosl(+0.0) == (0.0, 1.0)");
200 }
201
202 ATF_TC_BODY(sincosl_zero_pos, tc)
203 {
204 const long double x = 0.0L;
205 long double s, c;
206
207 sincosl(x, &s, &c);
208 ATF_CHECK(s == 0.0 && c == 1.0);
209 }
210 #endif
211
212 /*
213 * sincos(3)
214 */
215 ATF_TC(sincos_angles);
216 ATF_TC_HEAD(sincos_angles, tc)
217 {
218 atf_tc_set_md_var(tc, "descr", "Test some selected angles");
219 }
220
221 ATF_TC_BODY(sincos_angles, tc)
222 {
223 const double eps = DBL_EPSILON;
224 size_t i;
225
226 for (i = 0; i < __arraycount(sin_angles); i++) {
227 ATF_CHECK_MSG(sin_angles[i].angle == cos_angles[i].angle,
228 "%zu %d %d", i, sin_angles[i].angle, cos_angles[i].angle);
229 int deg = sin_angles[i].angle;
230 ATF_CHECK_MSG(sin_angles[i].x == cos_angles[i].x,
231 "%zu %g %g", i, sin_angles[i].x, cos_angles[i].x);
232 double theta = sin_angles[i].x;
233 double sin_theta = sin_angles[i].y;
234 double cos_theta = cos_angles[i].y;
235 double s, c;
236
237 sincos(theta, &s, &c);
238
239 if (fabs((s - sin_theta)/sin_theta) > eps) {
240 atf_tc_fail_nonfatal("sin(%d deg = %.17g) = %.17g"
241 " != %.17g",
242 deg, theta, s, sin_theta);
243 }
244 if (fabs((c - cos_theta)/cos_theta) > eps) {
245 atf_tc_fail_nonfatal("cos(%d deg = %.17g) = %.17g"
246 " != %.17g",
247 deg, theta, c, cos_theta);
248 }
249 }
250 }
251
252 ATF_TC(sincos_nan);
253 ATF_TC_HEAD(sincos_nan, tc)
254 {
255 atf_tc_set_md_var(tc, "descr", "Test sincos(NaN) == (NaN, NaN)");
256 }
257
258 ATF_TC_BODY(sincos_nan, tc)
259 {
260 const double x = 0.0L / 0.0L;
261 double s, c;
262
263 sincos(x, &s, &c);
264 ATF_CHECK(isnan(x) && isnan(s) && isnan(c));
265 }
266
267 ATF_TC(sincos_inf_neg);
268 ATF_TC_HEAD(sincos_inf_neg, tc)
269 {
270 atf_tc_set_md_var(tc, "descr", "Test sincos(-Inf) == (NaN, NaN)");
271 }
272
273 ATF_TC_BODY(sincos_inf_neg, tc)
274 {
275 const double x = -1.0L / 0.0L;
276 double s, c;
277
278 sincos(x, &s, &c);
279 ATF_CHECK(isnan(s) && isnan(c));
280 }
281
282 ATF_TC(sincos_inf_pos);
283 ATF_TC_HEAD(sincos_inf_pos, tc)
284 {
285 atf_tc_set_md_var(tc, "descr", "Test sincos(+Inf) == (NaN, NaN)");
286 }
287
288 ATF_TC_BODY(sincos_inf_pos, tc)
289 {
290 const double x = 1.0L / 0.0L;
291 double s, c;
292
293 sincos(x, &s, &c);
294 ATF_CHECK(isnan(s) && isnan(c));
295 }
296
297
298 ATF_TC(sincos_zero_neg);
299 ATF_TC_HEAD(sincos_zero_neg, tc)
300 {
301 atf_tc_set_md_var(tc, "descr", "Test sincos(-0.0) == (0.0, 1.0)");
302 }
303
304 ATF_TC_BODY(sincos_zero_neg, tc)
305 {
306 const double x = -0.0L;
307 double s, c;
308
309 sincos(x, &s, &c);
310 ATF_CHECK(s == 0 && c == 1.0);
311 }
312
313 ATF_TC(sincos_zero_pos);
314 ATF_TC_HEAD(sincos_zero_pos, tc)
315 {
316 atf_tc_set_md_var(tc, "descr", "Test cos(+0.0) == (0.0, 1.0)");
317 }
318
319 ATF_TC_BODY(sincos_zero_pos, tc)
320 {
321 const double x = 0.0L;
322 double s, c;
323
324 sincos(x, &s, &c);
325 ATF_CHECK(s == 0 && c == 1.0);
326 }
327
328 /*
329 * sincosf(3)
330 */
331 ATF_TC(sincosf_angles);
332 ATF_TC_HEAD(sincosf_angles, tc)
333 {
334 atf_tc_set_md_var(tc, "descr", "Test some selected angles");
335 }
336
337 ATF_TC_BODY(sincosf_angles, tc)
338 {
339 const float eps = FLT_EPSILON;
340 size_t i;
341
342 for (i = 0; i < __arraycount(sin_angles); i++) {
343 ATF_CHECK_MSG(sin_angles[i].angle == cos_angles[i].angle,
344 "%zu %d %d", i, sin_angles[i].angle, cos_angles[i].angle);
345 int deg = sin_angles[i].angle;
346 ATF_CHECK_MSG(sin_angles[i].x == cos_angles[i].x,
347 "%zu %g %g", i, sin_angles[i].x, cos_angles[i].x);
348 float theta = sin_angles[i].x;
349 float sin_theta = sin_angles[i].fy;
350 float cos_theta = cos_angles[i].fy;
351 float s, c;
352
353 sincosf(theta, &s, &c);
354 if (cos_theta == 999)
355 cos_theta = cos_angles[i].y;
356 if (sin_theta == 999)
357 sin_theta = sin_angles[i].y;
358
359 if (fabs((s - sin_theta)/sin_theta) > eps) {
360 atf_tc_fail_nonfatal("sin(%d deg = %.8g) = %.8g"
361 " != %.8g",
362 deg, theta, s, sin_theta);
363 }
364 if (fabs((c - cos_theta)/cos_theta) > eps) {
365 atf_tc_fail_nonfatal("cos(%d deg = %.8g) = %.8g"
366 " != %.8g",
367 deg, theta, c, cos_theta);
368 }
369 }
370 }
371
372 ATF_TC(sincosf_nan);
373 ATF_TC_HEAD(sincosf_nan, tc)
374 {
375 atf_tc_set_md_var(tc, "descr", "Test cosf(NaN) == (NaN, NaN)");
376 }
377
378 ATF_TC_BODY(sincosf_nan, tc)
379 {
380 const float x = 0.0L / 0.0L;
381 float s, c;
382
383 sincosf(x, &s, &c);
384 ATF_CHECK(isnan(x) && isnan(s) && isnan(c));
385 }
386
387 ATF_TC(sincosf_inf_neg);
388 ATF_TC_HEAD(sincosf_inf_neg, tc)
389 {
390 atf_tc_set_md_var(tc, "descr", "Test cosf(-Inf) == (NaN, NaN)");
391 }
392
393 ATF_TC_BODY(sincosf_inf_neg, tc)
394 {
395 const float x = -1.0L / 0.0L;
396 float s, c;
397
398 sincosf(x, &s, &c);
399 ATF_CHECK(isnan(s) && isnan(c));
400
401 }
402
403 ATF_TC(sincosf_inf_pos);
404 ATF_TC_HEAD(sincosf_inf_pos, tc)
405 {
406 atf_tc_set_md_var(tc, "descr", "Test sincosf(+Inf) == (NaN, NaN)");
407 }
408
409 ATF_TC_BODY(sincosf_inf_pos, tc)
410 {
411 const float x = 1.0L / 0.0L;
412 float s, c;
413
414 sincosf(x, &s, &c);
415 ATF_CHECK(isnan(s) && isnan(c));
416 }
417
418
419 ATF_TC(sincosf_zero_neg);
420 ATF_TC_HEAD(sincosf_zero_neg, tc)
421 {
422 atf_tc_set_md_var(tc, "descr", "Test sincosf(-0.0) == (0.0, 1.0)");
423 }
424
425 ATF_TC_BODY(sincosf_zero_neg, tc)
426 {
427 const float x = -0.0L;
428 float s, c;
429
430 sincosf(x, &s, &c);
431
432 ATF_CHECK(s == 0.0 && c == 1.0);
433 }
434
435 ATF_TC(sincosf_zero_pos);
436 ATF_TC_HEAD(sincosf_zero_pos, tc)
437 {
438 atf_tc_set_md_var(tc, "descr", "Test sincosf(+0.0) == (0.0, 1.0)");
439 }
440
441 ATF_TC_BODY(sincosf_zero_pos, tc)
442 {
443 const float x = 0.0L;
444
445 float s, c;
446
447 sincosf(x, &s, &c);
448
449 ATF_CHECK(s == 0 && c == 1.0);
450 }
451
452 ATF_TP_ADD_TCS(tp)
453 {
454 #ifdef __HAVE_LONG_DOUBLE
455 ATF_TP_ADD_TC(tp, sincosl_angles);
456 ATF_TP_ADD_TC(tp, sincosl_nan);
457 ATF_TP_ADD_TC(tp, sincosl_inf_neg);
458 ATF_TP_ADD_TC(tp, sincosl_inf_pos);
459 ATF_TP_ADD_TC(tp, sincosl_zero_neg);
460 ATF_TP_ADD_TC(tp, sincosl_zero_pos);
461 #endif
462
463 ATF_TP_ADD_TC(tp, sincos_angles);
464 ATF_TP_ADD_TC(tp, sincos_nan);
465 ATF_TP_ADD_TC(tp, sincos_inf_neg);
466 ATF_TP_ADD_TC(tp, sincos_inf_pos);
467 ATF_TP_ADD_TC(tp, sincos_zero_neg);
468 ATF_TP_ADD_TC(tp, sincos_zero_pos);
469
470 ATF_TP_ADD_TC(tp, sincosf_angles);
471 ATF_TP_ADD_TC(tp, sincosf_nan);
472 ATF_TP_ADD_TC(tp, sincosf_inf_neg);
473 ATF_TP_ADD_TC(tp, sincosf_inf_pos);
474 ATF_TP_ADD_TC(tp, sincosf_zero_neg);
475 ATF_TP_ADD_TC(tp, sincosf_zero_pos);
476
477 return atf_no_error();
478 }
479