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