1 /* $NetBSD: t_sincos.c,v 1.2 2024/05/06 15:53:46 riastradh 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 /* 89 * sincosl(3) 90 */ 91 ATF_TC(sincosl_angles); 92 ATF_TC_HEAD(sincosl_angles, tc) 93 { 94 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 95 } 96 97 ATF_TC_BODY(sincosl_angles, tc) 98 { 99 /* 100 * XXX The given data is for double, so take that 101 * into account and expect less precise results.. 102 */ 103 const long double eps = DBL_EPSILON; 104 size_t i; 105 106 ATF_CHECK(__arraycount(sin_angles) == __arraycount(cos_angles)); 107 108 for (i = 0; i < __arraycount(sin_angles); i++) { 109 ATF_CHECK_MSG(sin_angles[i].angle == cos_angles[i].angle, 110 "%zu %d %d", i, sin_angles[i].angle, cos_angles[i].angle); 111 int deg = sin_angles[i].angle; 112 ATF_CHECK_MSG(sin_angles[i].x == cos_angles[i].x, 113 "%zu %g %g", i, sin_angles[i].x, cos_angles[i].x); 114 long double theta = sin_angles[i].x; 115 long double sin_theta = sin_angles[i].y; 116 long double cos_theta = cos_angles[i].y; 117 long double s, c; 118 119 sincosl(theta, &s, &c); 120 121 if (fabsl((s - sin_theta)/sin_theta) > eps) { 122 atf_tc_fail_nonfatal("sin(%d deg = %.17Lg) = %.17Lg" 123 " != %.17Lg", 124 deg, theta, s, sin_theta); 125 } 126 if (fabsl((c - cos_theta)/cos_theta) > eps) { 127 atf_tc_fail_nonfatal("cos(%d deg = %.17Lg) = %.17Lg" 128 " != %.17Lg", 129 deg, theta, c, cos_theta); 130 } 131 } 132 } 133 134 ATF_TC(sincosl_nan); 135 ATF_TC_HEAD(sincosl_nan, tc) 136 { 137 atf_tc_set_md_var(tc, "descr", "Test sincosl(NaN) == (NaN, NaN)"); 138 } 139 140 ATF_TC_BODY(sincosl_nan, tc) 141 { 142 const long double x = 0.0L / 0.0L; 143 long double s, c; 144 145 sincosl(x, &s, &c); 146 ATF_CHECK(isnan(x) && isnan(s) && isnan(c)); 147 } 148 149 ATF_TC(sincosl_inf_neg); 150 ATF_TC_HEAD(sincosl_inf_neg, tc) 151 { 152 atf_tc_set_md_var(tc, "descr", "Test sincosl(-Inf) == (NaN, NaN)"); 153 } 154 155 ATF_TC_BODY(sincosl_inf_neg, tc) 156 { 157 const long double x = -1.0L / 0.0L; 158 long double s, c; 159 160 sincosl(x, &s, &c); 161 ATF_CHECK(isnan(s) && isnan(c)); 162 } 163 164 ATF_TC(sincosl_inf_pos); 165 ATF_TC_HEAD(sincosl_inf_pos, tc) 166 { 167 atf_tc_set_md_var(tc, "descr", "Test sincosl(+Inf) == (NaN, NaN)"); 168 } 169 170 ATF_TC_BODY(sincosl_inf_pos, tc) 171 { 172 const long double x = 1.0L / 0.0L; 173 long double s, c; 174 175 sincosl(x, &s, &c); 176 ATF_CHECK(isnan(s) && isnan(c)); 177 } 178 179 180 ATF_TC(sincosl_zero_neg); 181 ATF_TC_HEAD(sincosl_zero_neg, tc) 182 { 183 atf_tc_set_md_var(tc, "descr", "Test sincosl(-0.0) == (0.0, 1.0)"); 184 } 185 186 ATF_TC_BODY(sincosl_zero_neg, tc) 187 { 188 const long double x = -0.0L; 189 long double s, c; 190 191 sincosl(x, &s, &c); 192 ATF_CHECK(s == 0.0 && c == 1.0); 193 } 194 195 ATF_TC(sincosl_zero_pos); 196 ATF_TC_HEAD(sincosl_zero_pos, tc) 197 { 198 atf_tc_set_md_var(tc, "descr", "Test sincosl(+0.0) == (0.0, 1.0)"); 199 } 200 201 ATF_TC_BODY(sincosl_zero_pos, tc) 202 { 203 const long double x = 0.0L; 204 long double s, c; 205 206 sincosl(x, &s, &c); 207 ATF_CHECK(s == 0.0 && c == 1.0); 208 } 209 210 /* 211 * sincos(3) 212 */ 213 ATF_TC(sincos_angles); 214 ATF_TC_HEAD(sincos_angles, tc) 215 { 216 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 217 } 218 219 ATF_TC_BODY(sincos_angles, tc) 220 { 221 const double eps = DBL_EPSILON; 222 size_t i; 223 224 for (i = 0; i < __arraycount(sin_angles); i++) { 225 ATF_CHECK_MSG(sin_angles[i].angle == cos_angles[i].angle, 226 "%zu %d %d", i, sin_angles[i].angle, cos_angles[i].angle); 227 int deg = sin_angles[i].angle; 228 ATF_CHECK_MSG(sin_angles[i].x == cos_angles[i].x, 229 "%zu %g %g", i, sin_angles[i].x, cos_angles[i].x); 230 double theta = sin_angles[i].x; 231 double sin_theta = sin_angles[i].y; 232 double cos_theta = cos_angles[i].y; 233 double s, c; 234 235 sincos(theta, &s, &c); 236 237 if (fabs((s - sin_theta)/sin_theta) > eps) { 238 atf_tc_fail_nonfatal("sin(%d deg = %.17g) = %.17g" 239 " != %.17g", 240 deg, theta, s, sin_theta); 241 } 242 if (fabs((c - cos_theta)/cos_theta) > eps) { 243 atf_tc_fail_nonfatal("cos(%d deg = %.17g) = %.17g" 244 " != %.17g", 245 deg, theta, c, cos_theta); 246 } 247 } 248 } 249 250 ATF_TC(sincos_nan); 251 ATF_TC_HEAD(sincos_nan, tc) 252 { 253 atf_tc_set_md_var(tc, "descr", "Test sincos(NaN) == (NaN, NaN)"); 254 } 255 256 ATF_TC_BODY(sincos_nan, tc) 257 { 258 const double x = 0.0L / 0.0L; 259 double s, c; 260 261 sincos(x, &s, &c); 262 ATF_CHECK(isnan(x) && isnan(s) && isnan(c)); 263 } 264 265 ATF_TC(sincos_inf_neg); 266 ATF_TC_HEAD(sincos_inf_neg, tc) 267 { 268 atf_tc_set_md_var(tc, "descr", "Test sincos(-Inf) == (NaN, NaN)"); 269 } 270 271 ATF_TC_BODY(sincos_inf_neg, tc) 272 { 273 const double x = -1.0L / 0.0L; 274 double s, c; 275 276 sincos(x, &s, &c); 277 ATF_CHECK(isnan(s) && isnan(c)); 278 } 279 280 ATF_TC(sincos_inf_pos); 281 ATF_TC_HEAD(sincos_inf_pos, tc) 282 { 283 atf_tc_set_md_var(tc, "descr", "Test sincos(+Inf) == (NaN, NaN)"); 284 } 285 286 ATF_TC_BODY(sincos_inf_pos, tc) 287 { 288 const double x = 1.0L / 0.0L; 289 double s, c; 290 291 sincos(x, &s, &c); 292 ATF_CHECK(isnan(s) && isnan(c)); 293 } 294 295 296 ATF_TC(sincos_zero_neg); 297 ATF_TC_HEAD(sincos_zero_neg, tc) 298 { 299 atf_tc_set_md_var(tc, "descr", "Test sincos(-0.0) == (0.0, 1.0)"); 300 } 301 302 ATF_TC_BODY(sincos_zero_neg, tc) 303 { 304 const double x = -0.0L; 305 double s, c; 306 307 sincos(x, &s, &c); 308 ATF_CHECK(s == 0 && c == 1.0); 309 } 310 311 ATF_TC(sincos_zero_pos); 312 ATF_TC_HEAD(sincos_zero_pos, tc) 313 { 314 atf_tc_set_md_var(tc, "descr", "Test cos(+0.0) == (0.0, 1.0)"); 315 } 316 317 ATF_TC_BODY(sincos_zero_pos, tc) 318 { 319 const double x = 0.0L; 320 double s, c; 321 322 sincos(x, &s, &c); 323 ATF_CHECK(s == 0 && c == 1.0); 324 } 325 326 /* 327 * sincosf(3) 328 */ 329 ATF_TC(sincosf_angles); 330 ATF_TC_HEAD(sincosf_angles, tc) 331 { 332 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 333 } 334 335 ATF_TC_BODY(sincosf_angles, tc) 336 { 337 const float eps = FLT_EPSILON; 338 size_t i; 339 340 for (i = 0; i < __arraycount(sin_angles); i++) { 341 ATF_CHECK_MSG(sin_angles[i].angle == cos_angles[i].angle, 342 "%zu %d %d", i, sin_angles[i].angle, cos_angles[i].angle); 343 int deg = sin_angles[i].angle; 344 ATF_CHECK_MSG(sin_angles[i].x == cos_angles[i].x, 345 "%zu %g %g", i, sin_angles[i].x, cos_angles[i].x); 346 float theta = sin_angles[i].x; 347 float sin_theta = sin_angles[i].fy; 348 float cos_theta = cos_angles[i].fy; 349 float s, c; 350 351 sincosf(theta, &s, &c); 352 if (cos_theta == 999) 353 cos_theta = cos_angles[i].y; 354 if (sin_theta == 999) 355 sin_theta = sin_angles[i].y; 356 357 if (fabs((s - sin_theta)/sin_theta) > eps) { 358 atf_tc_fail_nonfatal("sin(%d deg = %.8g) = %.8g" 359 " != %.8g", 360 deg, theta, s, sin_theta); 361 } 362 if (fabs((c - cos_theta)/cos_theta) > eps) { 363 atf_tc_fail_nonfatal("cos(%d deg = %.8g) = %.8g" 364 " != %.8g", 365 deg, theta, c, cos_theta); 366 } 367 } 368 } 369 370 ATF_TC(sincosf_nan); 371 ATF_TC_HEAD(sincosf_nan, tc) 372 { 373 atf_tc_set_md_var(tc, "descr", "Test cosf(NaN) == (NaN, NaN)"); 374 } 375 376 ATF_TC_BODY(sincosf_nan, tc) 377 { 378 const float x = 0.0L / 0.0L; 379 float s, c; 380 381 sincosf(x, &s, &c); 382 ATF_CHECK(isnan(x) && isnan(s) && isnan(c)); 383 } 384 385 ATF_TC(sincosf_inf_neg); 386 ATF_TC_HEAD(sincosf_inf_neg, tc) 387 { 388 atf_tc_set_md_var(tc, "descr", "Test cosf(-Inf) == (NaN, NaN)"); 389 } 390 391 ATF_TC_BODY(sincosf_inf_neg, tc) 392 { 393 const float x = -1.0L / 0.0L; 394 float s, c; 395 396 sincosf(x, &s, &c); 397 ATF_CHECK(isnan(s) && isnan(c)); 398 399 } 400 401 ATF_TC(sincosf_inf_pos); 402 ATF_TC_HEAD(sincosf_inf_pos, tc) 403 { 404 atf_tc_set_md_var(tc, "descr", "Test sincosf(+Inf) == (NaN, NaN)"); 405 } 406 407 ATF_TC_BODY(sincosf_inf_pos, tc) 408 { 409 const float x = 1.0L / 0.0L; 410 float s, c; 411 412 sincosf(x, &s, &c); 413 ATF_CHECK(isnan(s) && isnan(c)); 414 } 415 416 417 ATF_TC(sincosf_zero_neg); 418 ATF_TC_HEAD(sincosf_zero_neg, tc) 419 { 420 atf_tc_set_md_var(tc, "descr", "Test sincosf(-0.0) == (0.0, 1.0)"); 421 } 422 423 ATF_TC_BODY(sincosf_zero_neg, tc) 424 { 425 const float x = -0.0L; 426 float s, c; 427 428 sincosf(x, &s, &c); 429 430 ATF_CHECK(s == 0.0 && c == 1.0); 431 } 432 433 ATF_TC(sincosf_zero_pos); 434 ATF_TC_HEAD(sincosf_zero_pos, tc) 435 { 436 atf_tc_set_md_var(tc, "descr", "Test sincosf(+0.0) == (0.0, 1.0)"); 437 } 438 439 ATF_TC_BODY(sincosf_zero_pos, tc) 440 { 441 const float x = 0.0L; 442 443 float s, c; 444 445 sincosf(x, &s, &c); 446 447 ATF_CHECK(s == 0 && c == 1.0); 448 } 449 450 ATF_TP_ADD_TCS(tp) 451 { 452 453 ATF_TP_ADD_TC(tp, sincosl_angles); 454 ATF_TP_ADD_TC(tp, sincosl_nan); 455 ATF_TP_ADD_TC(tp, sincosl_inf_neg); 456 ATF_TP_ADD_TC(tp, sincosl_inf_pos); 457 ATF_TP_ADD_TC(tp, sincosl_zero_neg); 458 ATF_TP_ADD_TC(tp, sincosl_zero_pos); 459 460 ATF_TP_ADD_TC(tp, sincos_angles); 461 ATF_TP_ADD_TC(tp, sincos_nan); 462 ATF_TP_ADD_TC(tp, sincos_inf_neg); 463 ATF_TP_ADD_TC(tp, sincos_inf_pos); 464 ATF_TP_ADD_TC(tp, sincos_zero_neg); 465 ATF_TP_ADD_TC(tp, sincos_zero_pos); 466 467 ATF_TP_ADD_TC(tp, sincosf_angles); 468 ATF_TP_ADD_TC(tp, sincosf_nan); 469 ATF_TP_ADD_TC(tp, sincosf_inf_neg); 470 ATF_TP_ADD_TC(tp, sincosf_inf_pos); 471 ATF_TP_ADD_TC(tp, sincosf_zero_neg); 472 ATF_TP_ADD_TC(tp, sincosf_zero_pos); 473 474 return atf_no_error(); 475 } 476