t_cos.c revision 1.11
1/* $NetBSD: t_cos.c,v 1.11 2024/05/06 15:45:20 riastradh Exp $ */ 2 3/*- 4 * Copyright (c) 2011 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. 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 37static const struct { 38 int angle; 39 double x; 40 double y; 41 float fy; 42} angles[] = { 43 { -180, -3.141592653589793, -1.0000000000000000, 999 }, 44 { -135, -2.356194490192345, -0.7071067811865476, 999 }, 45 { -90, -1.5707963267948966, 6.123233995736766e-17, -4.3711388e-08 }, 46 { -90, -1.5707963267948968, -1.6081226496766366e-16, -4.3711388e-08 }, 47 { -45, -0.785398163397448, 0.7071067811865478, 999 }, 48 { 0, 0.000000000000000, 1.0000000000000000, 999 }, 49 { 30, 0.523598775598299, 0.8660254037844386, 999 }, 50 { 45, 0.785398163397448, 0.7071067811865478, 999 }, 51 { 60, 1.0471975511965976, 0.5000000000000001, 999 }, 52 { 60, 1.0471975511965979, 0.4999999999999999, 999 }, 53 { 90, 1.570796326794897, -3.8285686989269494e-16, -4.3711388e-08 }, 54 { 120, 2.0943951023931953, -0.4999999999999998, 999 }, 55 { 120, 2.0943951023931957, -0.5000000000000002, 999 }, 56 { 135, 2.356194490192345, -0.7071067811865476, 999 }, 57 { 150, 2.617993877991494, -0.8660254037844386, 999 }, 58 { 180, 3.141592653589793, -1.0000000000000000, 999 }, 59 { 270, 4.712388980384690, -1.8369701987210297e-16, 1.1924881e-08 }, 60 { 360, 6.283185307179586, 1.0000000000000000, 999 }, 61}; 62 63/* 64 * cosl(3) 65 */ 66ATF_TC(cosl_angles); 67ATF_TC_HEAD(cosl_angles, tc) 68{ 69 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 70} 71 72ATF_TC_BODY(cosl_angles, tc) 73{ 74 /* 75 * XXX The given data is for double, so take that 76 * into account and expect less precise results.. 77 */ 78 const long double eps = DBL_EPSILON; 79 size_t i; 80 81 for (i = 0; i < __arraycount(angles); i++) { 82 int deg = angles[i].angle; 83 long double theta = angles[i].x; 84 long double cos_theta = angles[i].y; 85 86 assert(cos_theta != 0); 87 if (!(fabsl((cosl(theta) - cos_theta)/cos_theta) <= eps)) { 88 atf_tc_fail_nonfatal("cos(%d deg = %.17Lg) = %.17Lg" 89 " != %.17Lg", 90 deg, theta, cosl(theta), cos_theta); 91 } 92 } 93} 94 95ATF_TC(cosl_nan); 96ATF_TC_HEAD(cosl_nan, tc) 97{ 98 atf_tc_set_md_var(tc, "descr", "Test cosl(NaN) == NaN"); 99} 100 101ATF_TC_BODY(cosl_nan, tc) 102{ 103 const long double x = 0.0L / 0.0L; 104 105 ATF_CHECK(isnan(x) != 0); 106 ATF_CHECK(isnan(cosl(x)) != 0); 107} 108 109ATF_TC(cosl_inf_neg); 110ATF_TC_HEAD(cosl_inf_neg, tc) 111{ 112 atf_tc_set_md_var(tc, "descr", "Test cosl(-Inf) == NaN"); 113} 114 115ATF_TC_BODY(cosl_inf_neg, tc) 116{ 117 const long double x = -1.0L / 0.0L; 118 119 ATF_CHECK(isnan(cosl(x)) != 0); 120} 121 122ATF_TC(cosl_inf_pos); 123ATF_TC_HEAD(cosl_inf_pos, tc) 124{ 125 atf_tc_set_md_var(tc, "descr", "Test cosl(+Inf) == NaN"); 126} 127 128ATF_TC_BODY(cosl_inf_pos, tc) 129{ 130 const long double x = 1.0L / 0.0L; 131 132 ATF_CHECK(isnan(cosl(x)) != 0); 133} 134 135ATF_TC(cosl_zero_neg); 136ATF_TC_HEAD(cosl_zero_neg, tc) 137{ 138 atf_tc_set_md_var(tc, "descr", "Test cosl(-0.0) == 1.0"); 139} 140 141ATF_TC_BODY(cosl_zero_neg, tc) 142{ 143 const long double x = -0.0L; 144 145 ATF_CHECK(cosl(x) == 1.0); 146} 147 148ATF_TC(cosl_zero_pos); 149ATF_TC_HEAD(cosl_zero_pos, tc) 150{ 151 atf_tc_set_md_var(tc, "descr", "Test cosl(+0.0) == 1.0"); 152} 153 154ATF_TC_BODY(cosl_zero_pos, tc) 155{ 156 const long double x = 0.0L; 157 158 ATF_CHECK(cosl(x) == 1.0); 159} 160 161/* 162 * cos(3) 163 */ 164ATF_TC(cos_angles); 165ATF_TC_HEAD(cos_angles, tc) 166{ 167 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 168} 169 170ATF_TC_BODY(cos_angles, tc) 171{ 172 const double eps = DBL_EPSILON; 173 size_t i; 174 175 for (i = 0; i < __arraycount(angles); i++) { 176 int deg = angles[i].angle; 177 double theta = angles[i].x; 178 double cos_theta = angles[i].y; 179 180 assert(cos_theta != 0); 181 if (!(fabs((cos(theta) - cos_theta)/cos_theta) <= eps)) { 182 atf_tc_fail_nonfatal("cos(%d deg = %.17g) = %.17g" 183 " != %.17g", 184 deg, theta, cos(theta), cos_theta); 185 } 186 } 187} 188 189ATF_TC(cos_nan); 190ATF_TC_HEAD(cos_nan, tc) 191{ 192 atf_tc_set_md_var(tc, "descr", "Test cos(NaN) == NaN"); 193} 194 195ATF_TC_BODY(cos_nan, tc) 196{ 197 const double x = 0.0L / 0.0L; 198 199 ATF_CHECK(isnan(x) != 0); 200 ATF_CHECK(isnan(cos(x)) != 0); 201} 202 203ATF_TC(cos_inf_neg); 204ATF_TC_HEAD(cos_inf_neg, tc) 205{ 206 atf_tc_set_md_var(tc, "descr", "Test cos(-Inf) == NaN"); 207} 208 209ATF_TC_BODY(cos_inf_neg, tc) 210{ 211 const double x = -1.0L / 0.0L; 212 213 ATF_CHECK(isnan(cos(x)) != 0); 214} 215 216ATF_TC(cos_inf_pos); 217ATF_TC_HEAD(cos_inf_pos, tc) 218{ 219 atf_tc_set_md_var(tc, "descr", "Test cos(+Inf) == NaN"); 220} 221 222ATF_TC_BODY(cos_inf_pos, tc) 223{ 224 const double x = 1.0L / 0.0L; 225 226 ATF_CHECK(isnan(cos(x)) != 0); 227} 228 229ATF_TC(cos_zero_neg); 230ATF_TC_HEAD(cos_zero_neg, tc) 231{ 232 atf_tc_set_md_var(tc, "descr", "Test cos(-0.0) == 1.0"); 233} 234 235ATF_TC_BODY(cos_zero_neg, tc) 236{ 237 const double x = -0.0L; 238 239 ATF_CHECK(cos(x) == 1.0); 240} 241 242ATF_TC(cos_zero_pos); 243ATF_TC_HEAD(cos_zero_pos, tc) 244{ 245 atf_tc_set_md_var(tc, "descr", "Test cos(+0.0) == 1.0"); 246} 247 248ATF_TC_BODY(cos_zero_pos, tc) 249{ 250 const double x = 0.0L; 251 252 ATF_CHECK(cos(x) == 1.0); 253} 254 255/* 256 * cosf(3) 257 */ 258ATF_TC(cosf_angles); 259ATF_TC_HEAD(cosf_angles, tc) 260{ 261 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 262} 263 264ATF_TC_BODY(cosf_angles, tc) 265{ 266 const float eps = FLT_EPSILON; 267 size_t i; 268 269 for (i = 0; i < __arraycount(angles); i++) { 270 int deg = angles[i].angle; 271 float theta = angles[i].x; 272 float cos_theta = angles[i].fy; 273 274 /* 275 * Force rounding to float even if FLT_EVAL_METHOD=2, 276 * as is the case on i386. 277 * 278 * The volatile should not be necessary, by C99 Sec. 279 * 5.2.4.2.2. para. 8 on p. 24 which specifies that 280 * assignment and cast remove all extra range and 281 * precision, but is needed when we compile with 282 * -std=gnu99 which doesn't implement this semantics. 283 */ 284 volatile float result = cosf(theta); 285 286 if (cos_theta == 999) 287 cos_theta = angles[i].y; 288 289 assert(cos_theta != 0); 290 if (!(fabsf((result - cos_theta)/cos_theta) <= eps)) { 291 atf_tc_fail_nonfatal("cosf(%d deg = %.8g) = %.8g" 292 " != %.8g", deg, theta, result, cos_theta); 293 } 294 } 295} 296 297ATF_TC(cosf_nan); 298ATF_TC_HEAD(cosf_nan, tc) 299{ 300 atf_tc_set_md_var(tc, "descr", "Test cosf(NaN) == NaN"); 301} 302 303ATF_TC_BODY(cosf_nan, tc) 304{ 305 const float x = 0.0L / 0.0L; 306 307 ATF_CHECK(isnan(x) != 0); 308 ATF_CHECK(isnan(cosf(x)) != 0); 309} 310 311ATF_TC(cosf_inf_neg); 312ATF_TC_HEAD(cosf_inf_neg, tc) 313{ 314 atf_tc_set_md_var(tc, "descr", "Test cosf(-Inf) == NaN"); 315} 316 317ATF_TC_BODY(cosf_inf_neg, tc) 318{ 319 const float x = -1.0L / 0.0L; 320 321 if (isnan(cosf(x)) == 0) { 322 atf_tc_expect_fail("PR lib/45362"); 323 atf_tc_fail("cosf(-Inf) != NaN"); 324 } 325} 326 327ATF_TC(cosf_inf_pos); 328ATF_TC_HEAD(cosf_inf_pos, tc) 329{ 330 atf_tc_set_md_var(tc, "descr", "Test cosf(+Inf) == NaN"); 331} 332 333ATF_TC_BODY(cosf_inf_pos, tc) 334{ 335 const float x = 1.0L / 0.0L; 336 337 if (isnan(cosf(x)) == 0) { 338 atf_tc_expect_fail("PR lib/45362"); 339 atf_tc_fail("cosf(+Inf) != NaN"); 340 } 341} 342 343 344ATF_TC(cosf_zero_neg); 345ATF_TC_HEAD(cosf_zero_neg, tc) 346{ 347 atf_tc_set_md_var(tc, "descr", "Test cosf(-0.0) == 1.0"); 348} 349 350ATF_TC_BODY(cosf_zero_neg, tc) 351{ 352 const float x = -0.0L; 353 354 ATF_CHECK(cosf(x) == 1.0); 355} 356 357ATF_TC(cosf_zero_pos); 358ATF_TC_HEAD(cosf_zero_pos, tc) 359{ 360 atf_tc_set_md_var(tc, "descr", "Test cosf(+0.0) == 1.0"); 361} 362 363ATF_TC_BODY(cosf_zero_pos, tc) 364{ 365 const float x = 0.0L; 366 367 ATF_CHECK(cosf(x) == 1.0); 368} 369 370ATF_TP_ADD_TCS(tp) 371{ 372 373 ATF_TP_ADD_TC(tp, cosl_angles); 374 ATF_TP_ADD_TC(tp, cosl_nan); 375 ATF_TP_ADD_TC(tp, cosl_inf_neg); 376 ATF_TP_ADD_TC(tp, cosl_inf_pos); 377 ATF_TP_ADD_TC(tp, cosl_zero_neg); 378 ATF_TP_ADD_TC(tp, cosl_zero_pos); 379 380 ATF_TP_ADD_TC(tp, cos_angles); 381 ATF_TP_ADD_TC(tp, cos_nan); 382 ATF_TP_ADD_TC(tp, cos_inf_neg); 383 ATF_TP_ADD_TC(tp, cos_inf_pos); 384 ATF_TP_ADD_TC(tp, cos_zero_neg); 385 ATF_TP_ADD_TC(tp, cos_zero_pos); 386 387 ATF_TP_ADD_TC(tp, cosf_angles); 388 ATF_TP_ADD_TC(tp, cosf_nan); 389 ATF_TP_ADD_TC(tp, cosf_inf_neg); 390 ATF_TP_ADD_TC(tp, cosf_inf_pos); 391 ATF_TP_ADD_TC(tp, cosf_zero_neg); 392 ATF_TP_ADD_TC(tp, cosf_zero_pos); 393 394 return atf_no_error(); 395} 396