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 38static 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 62static 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 */ 91ATF_TC(sincosl_angles); 92ATF_TC_HEAD(sincosl_angles, tc) 93{ 94 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 95} 96 97ATF_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 134ATF_TC(sincosl_nan); 135ATF_TC_HEAD(sincosl_nan, tc) 136{ 137 atf_tc_set_md_var(tc, "descr", "Test sincosl(NaN) == (NaN, NaN)"); 138} 139 140ATF_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 149ATF_TC(sincosl_inf_neg); 150ATF_TC_HEAD(sincosl_inf_neg, tc) 151{ 152 atf_tc_set_md_var(tc, "descr", "Test sincosl(-Inf) == (NaN, NaN)"); 153} 154 155ATF_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 164ATF_TC(sincosl_inf_pos); 165ATF_TC_HEAD(sincosl_inf_pos, tc) 166{ 167 atf_tc_set_md_var(tc, "descr", "Test sincosl(+Inf) == (NaN, NaN)"); 168} 169 170ATF_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 180ATF_TC(sincosl_zero_neg); 181ATF_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 186ATF_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 195ATF_TC(sincosl_zero_pos); 196ATF_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 201ATF_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 */ 213ATF_TC(sincos_angles); 214ATF_TC_HEAD(sincos_angles, tc) 215{ 216 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 217} 218 219ATF_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 250ATF_TC(sincos_nan); 251ATF_TC_HEAD(sincos_nan, tc) 252{ 253 atf_tc_set_md_var(tc, "descr", "Test sincos(NaN) == (NaN, NaN)"); 254} 255 256ATF_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 265ATF_TC(sincos_inf_neg); 266ATF_TC_HEAD(sincos_inf_neg, tc) 267{ 268 atf_tc_set_md_var(tc, "descr", "Test sincos(-Inf) == (NaN, NaN)"); 269} 270 271ATF_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 280ATF_TC(sincos_inf_pos); 281ATF_TC_HEAD(sincos_inf_pos, tc) 282{ 283 atf_tc_set_md_var(tc, "descr", "Test sincos(+Inf) == (NaN, NaN)"); 284} 285 286ATF_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 296ATF_TC(sincos_zero_neg); 297ATF_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 302ATF_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 311ATF_TC(sincos_zero_pos); 312ATF_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 317ATF_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 */ 329ATF_TC(sincosf_angles); 330ATF_TC_HEAD(sincosf_angles, tc) 331{ 332 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 333} 334 335ATF_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 370ATF_TC(sincosf_nan); 371ATF_TC_HEAD(sincosf_nan, tc) 372{ 373 atf_tc_set_md_var(tc, "descr", "Test cosf(NaN) == (NaN, NaN)"); 374} 375 376ATF_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 385ATF_TC(sincosf_inf_neg); 386ATF_TC_HEAD(sincosf_inf_neg, tc) 387{ 388 atf_tc_set_md_var(tc, "descr", "Test cosf(-Inf) == (NaN, NaN)"); 389} 390 391ATF_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 401ATF_TC(sincosf_inf_pos); 402ATF_TC_HEAD(sincosf_inf_pos, tc) 403{ 404 atf_tc_set_md_var(tc, "descr", "Test sincosf(+Inf) == (NaN, NaN)"); 405} 406 407ATF_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 417ATF_TC(sincosf_zero_neg); 418ATF_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 423ATF_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 433ATF_TC(sincosf_zero_pos); 434ATF_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 439ATF_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 450ATF_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