1 /* $NetBSD: t_sin.c,v 1.8 2024/06/09 16:53:12 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 37 static const struct { 38 int angle; 39 double x; 40 double y; 41 float fy; 42 } angles[] = { 43 { -360, -6.283185307179586, 2.4492935982947064e-16, -1.7484555e-07 }, 44 { -180, -3.141592653589793, -1.2246467991473532e-16, 8.7422777e-08 }, 45 { -135, -2.356194490192345, -0.7071067811865476, 999 }, 46 { -90, -1.570796326794897, -1.0000000000000000, 999 }, 47 { -45, -0.785398163397448, -0.7071067811865472, 999 }, 48 { 0, 0.000000000000000, 0.0000000000000000, 999 }, 49 { 30, 0.5235987755982989, 0.5000000000000000, 999 }, 50 { 45, 0.785398163397448, 0.7071067811865472, 999 }, 51 { 60, 1.047197551196598, 0.8660254037844388, 999 }, 52 { 90, 1.570796326794897, 1.0000000000000000, 999 }, 53 { 120, 2.094395102393195, 0.8660254037844389, 999 }, 54 { 135, 2.356194490192345, 0.7071067811865476, 999 }, 55 { 150, 2.617993877991494, 0.5000000000000003, 999 }, 56 { 180, 3.141592653589793, 1.2246467991473532e-16, -8.7422777e-08 }, 57 { 270, 4.712388980384690, -1.0000000000000000, 999 }, 58 { 360, 6.283185307179586, -2.4492935982947064e-16, 1.7484555e-07 }, 59 }; 60 61 /* 62 * sin(3) 63 */ 64 ATF_TC(sin_angles); 65 ATF_TC_HEAD(sin_angles, tc) 66 { 67 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 68 } 69 70 ATF_TC_BODY(sin_angles, tc) 71 { 72 const double eps = DBL_EPSILON; 73 size_t i; 74 75 for (i = 0; i < __arraycount(angles); i++) { 76 int deg = angles[i].angle; 77 double theta = angles[i].x; 78 double sin_theta = angles[i].y; 79 bool ok; 80 81 if (sin_theta == 0) { 82 /* Should be computed exactly. */ 83 assert(sin_theta == 0); 84 ok = (sin(theta) == 0); 85 } else { 86 assert(sin_theta != 0); 87 ok = (fabs((sin(theta) - sin_theta)/sin_theta) <= eps); 88 } 89 90 if (!ok) { 91 atf_tc_fail_nonfatal("sin(%d deg = %.17g) = %.17g" 92 " != %.17g", 93 deg, theta, sin(theta), sin_theta); 94 } 95 } 96 } 97 98 ATF_TC(sin_nan); 99 ATF_TC_HEAD(sin_nan, tc) 100 { 101 atf_tc_set_md_var(tc, "descr", "Test sin(NaN) == NaN"); 102 } 103 104 ATF_TC_BODY(sin_nan, tc) 105 { 106 const double x = 0.0L / 0.0L; 107 108 ATF_CHECK(isnan(x) != 0); 109 ATF_CHECK(isnan(sin(x)) != 0); 110 } 111 112 ATF_TC(sin_inf_neg); 113 ATF_TC_HEAD(sin_inf_neg, tc) 114 { 115 atf_tc_set_md_var(tc, "descr", "Test sin(-Inf) == NaN"); 116 } 117 118 ATF_TC_BODY(sin_inf_neg, tc) 119 { 120 const volatile double x = -1.0 / 0.0; 121 const double y = sin(x); 122 123 ATF_CHECK_MSG(isnan(y), "y=%a", y); 124 } 125 126 ATF_TC(sin_inf_pos); 127 ATF_TC_HEAD(sin_inf_pos, tc) 128 { 129 atf_tc_set_md_var(tc, "descr", "Test sin(+Inf) == NaN"); 130 } 131 132 ATF_TC_BODY(sin_inf_pos, tc) 133 { 134 const volatile double x = 1.0 / 0.0; 135 const double y = sin(x); 136 137 ATF_CHECK_MSG(isnan(y), "y=%a", y); 138 } 139 140 141 ATF_TC(sin_zero_neg); 142 ATF_TC_HEAD(sin_zero_neg, tc) 143 { 144 atf_tc_set_md_var(tc, "descr", "Test sin(-0.0) == -0.0"); 145 } 146 147 ATF_TC_BODY(sin_zero_neg, tc) 148 { 149 const double x = -0.0L; 150 151 ATF_CHECK(sin(x) == x); 152 } 153 154 ATF_TC(sin_zero_pos); 155 ATF_TC_HEAD(sin_zero_pos, tc) 156 { 157 atf_tc_set_md_var(tc, "descr", "Test sin(+0.0) == +0.0"); 158 } 159 160 ATF_TC_BODY(sin_zero_pos, tc) 161 { 162 const double x = 0.0L; 163 164 ATF_CHECK(sin(x) == x); 165 } 166 167 /* 168 * sinf(3) 169 */ 170 ATF_TC(sinf_angles); 171 ATF_TC_HEAD(sinf_angles, tc) 172 { 173 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 174 } 175 176 ATF_TC_BODY(sinf_angles, tc) 177 { 178 const float eps = FLT_EPSILON; 179 size_t i; 180 181 for (i = 0; i < __arraycount(angles); i++) { 182 int deg = angles[i].angle; 183 float theta = angles[i].x; 184 float sin_theta = angles[i].fy; 185 bool ok; 186 187 if (sin_theta == 999) 188 sin_theta = angles[i].y; 189 190 if (sin_theta == 0) { 191 /* Should be computed exactly. */ 192 ok = (sinf(theta) == 0); 193 } else { 194 ok = (fabsf((sinf(theta) - sin_theta)/sin_theta) 195 <= eps); 196 } 197 198 if (!ok) { 199 atf_tc_fail_nonfatal("sinf(%d deg) = %.8g != %.8g", 200 deg, sinf(theta), sin_theta); 201 } 202 } 203 } 204 205 ATF_TC(sinf_nan); 206 ATF_TC_HEAD(sinf_nan, tc) 207 { 208 atf_tc_set_md_var(tc, "descr", "Test sinf(NaN) == NaN"); 209 } 210 211 ATF_TC_BODY(sinf_nan, tc) 212 { 213 const float x = 0.0L / 0.0L; 214 215 ATF_CHECK(isnan(x) != 0); 216 ATF_CHECK(isnan(sinf(x)) != 0); 217 } 218 219 ATF_TC(sinf_inf_neg); 220 ATF_TC_HEAD(sinf_inf_neg, tc) 221 { 222 atf_tc_set_md_var(tc, "descr", "Test sinf(-Inf) == NaN"); 223 } 224 225 ATF_TC_BODY(sinf_inf_neg, tc) 226 { 227 const volatile float x = -1.0f / 0.0f; 228 const float y = sinf(x); 229 230 ATF_CHECK_MSG(isnan(y), "y=%a", y); 231 } 232 233 ATF_TC(sinf_inf_pos); 234 ATF_TC_HEAD(sinf_inf_pos, tc) 235 { 236 atf_tc_set_md_var(tc, "descr", "Test sinf(+Inf) == NaN"); 237 } 238 239 ATF_TC_BODY(sinf_inf_pos, tc) 240 { 241 const volatile float x = -1.0f / 0.0f; 242 const float y = sinf(x); 243 244 ATF_CHECK_MSG(isnan(y), "y=%a", y); 245 } 246 247 248 ATF_TC(sinf_zero_neg); 249 ATF_TC_HEAD(sinf_zero_neg, tc) 250 { 251 atf_tc_set_md_var(tc, "descr", "Test sinf(-0.0) == -0.0"); 252 } 253 254 ATF_TC_BODY(sinf_zero_neg, tc) 255 { 256 const float x = -0.0L; 257 258 ATF_CHECK(sinf(x) == x); 259 } 260 261 ATF_TC(sinf_zero_pos); 262 ATF_TC_HEAD(sinf_zero_pos, tc) 263 { 264 atf_tc_set_md_var(tc, "descr", "Test sinf(+0.0) == +0.0"); 265 } 266 267 ATF_TC_BODY(sinf_zero_pos, tc) 268 { 269 const float x = 0.0L; 270 271 ATF_CHECK(sinf(x) == x); 272 } 273 274 ATF_TP_ADD_TCS(tp) 275 { 276 277 ATF_TP_ADD_TC(tp, sin_angles); 278 ATF_TP_ADD_TC(tp, sin_nan); 279 ATF_TP_ADD_TC(tp, sin_inf_neg); 280 ATF_TP_ADD_TC(tp, sin_inf_pos); 281 ATF_TP_ADD_TC(tp, sin_zero_neg); 282 ATF_TP_ADD_TC(tp, sin_zero_pos); 283 284 ATF_TP_ADD_TC(tp, sinf_angles); 285 ATF_TP_ADD_TC(tp, sinf_nan); 286 ATF_TP_ADD_TC(tp, sinf_inf_neg); 287 ATF_TP_ADD_TC(tp, sinf_inf_pos); 288 ATF_TP_ADD_TC(tp, sinf_zero_neg); 289 ATF_TP_ADD_TC(tp, sinf_zero_pos); 290 291 return atf_no_error(); 292 } 293