1 /* $NetBSD: t_sin.c,v 1.7 2019/05/27 00:24:37 maya 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 double x = -1.0L / 0.0L; 121 122 ATF_CHECK(isnan(sin(x)) != 0); 123 } 124 125 ATF_TC(sin_inf_pos); 126 ATF_TC_HEAD(sin_inf_pos, tc) 127 { 128 atf_tc_set_md_var(tc, "descr", "Test sin(+Inf) == NaN"); 129 } 130 131 ATF_TC_BODY(sin_inf_pos, tc) 132 { 133 const double x = 1.0L / 0.0L; 134 135 ATF_CHECK(isnan(sin(x)) != 0); 136 } 137 138 139 ATF_TC(sin_zero_neg); 140 ATF_TC_HEAD(sin_zero_neg, tc) 141 { 142 atf_tc_set_md_var(tc, "descr", "Test sin(-0.0) == -0.0"); 143 } 144 145 ATF_TC_BODY(sin_zero_neg, tc) 146 { 147 const double x = -0.0L; 148 149 ATF_CHECK(sin(x) == x); 150 } 151 152 ATF_TC(sin_zero_pos); 153 ATF_TC_HEAD(sin_zero_pos, tc) 154 { 155 atf_tc_set_md_var(tc, "descr", "Test sin(+0.0) == +0.0"); 156 } 157 158 ATF_TC_BODY(sin_zero_pos, tc) 159 { 160 const double x = 0.0L; 161 162 ATF_CHECK(sin(x) == x); 163 } 164 165 /* 166 * sinf(3) 167 */ 168 ATF_TC(sinf_angles); 169 ATF_TC_HEAD(sinf_angles, tc) 170 { 171 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 172 } 173 174 ATF_TC_BODY(sinf_angles, tc) 175 { 176 const float eps = FLT_EPSILON; 177 size_t i; 178 179 for (i = 0; i < __arraycount(angles); i++) { 180 int deg = angles[i].angle; 181 float theta = angles[i].x; 182 float sin_theta = angles[i].fy; 183 bool ok; 184 185 if (sin_theta == 999) 186 sin_theta = angles[i].y; 187 188 if (sin_theta == 0) { 189 /* Should be computed exactly. */ 190 ok = (sinf(theta) == 0); 191 } else { 192 ok = (fabsf((sinf(theta) - sin_theta)/sin_theta) 193 <= eps); 194 } 195 196 if (!ok) { 197 atf_tc_fail_nonfatal("sinf(%d deg) = %.8g != %.8g", 198 deg, sinf(theta), sin_theta); 199 } 200 } 201 } 202 203 ATF_TC(sinf_nan); 204 ATF_TC_HEAD(sinf_nan, tc) 205 { 206 atf_tc_set_md_var(tc, "descr", "Test sinf(NaN) == NaN"); 207 } 208 209 ATF_TC_BODY(sinf_nan, tc) 210 { 211 const float x = 0.0L / 0.0L; 212 213 ATF_CHECK(isnan(x) != 0); 214 ATF_CHECK(isnan(sinf(x)) != 0); 215 } 216 217 ATF_TC(sinf_inf_neg); 218 ATF_TC_HEAD(sinf_inf_neg, tc) 219 { 220 atf_tc_set_md_var(tc, "descr", "Test sinf(-Inf) == NaN"); 221 } 222 223 ATF_TC_BODY(sinf_inf_neg, tc) 224 { 225 const float x = -1.0L / 0.0L; 226 227 if (isnan(sinf(x)) == 0) { 228 atf_tc_expect_fail("PR lib/45362"); 229 atf_tc_fail("sinf(-Inf) != NaN"); 230 } 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 float x = 1.0L / 0.0L; 242 243 if (isnan(sinf(x)) == 0) { 244 atf_tc_expect_fail("PR lib/45362"); 245 atf_tc_fail("sinf(+Inf) != NaN"); 246 } 247 } 248 249 250 ATF_TC(sinf_zero_neg); 251 ATF_TC_HEAD(sinf_zero_neg, tc) 252 { 253 atf_tc_set_md_var(tc, "descr", "Test sinf(-0.0) == -0.0"); 254 } 255 256 ATF_TC_BODY(sinf_zero_neg, tc) 257 { 258 const float x = -0.0L; 259 260 ATF_CHECK(sinf(x) == x); 261 } 262 263 ATF_TC(sinf_zero_pos); 264 ATF_TC_HEAD(sinf_zero_pos, tc) 265 { 266 atf_tc_set_md_var(tc, "descr", "Test sinf(+0.0) == +0.0"); 267 } 268 269 ATF_TC_BODY(sinf_zero_pos, tc) 270 { 271 const float x = 0.0L; 272 273 ATF_CHECK(sinf(x) == x); 274 } 275 276 ATF_TP_ADD_TCS(tp) 277 { 278 279 ATF_TP_ADD_TC(tp, sin_angles); 280 ATF_TP_ADD_TC(tp, sin_nan); 281 ATF_TP_ADD_TC(tp, sin_inf_neg); 282 ATF_TP_ADD_TC(tp, sin_inf_pos); 283 ATF_TP_ADD_TC(tp, sin_zero_neg); 284 ATF_TP_ADD_TC(tp, sin_zero_pos); 285 286 ATF_TP_ADD_TC(tp, sinf_angles); 287 ATF_TP_ADD_TC(tp, sinf_nan); 288 ATF_TP_ADD_TC(tp, sinf_inf_neg); 289 ATF_TP_ADD_TC(tp, sinf_inf_pos); 290 ATF_TP_ADD_TC(tp, sinf_zero_neg); 291 ATF_TP_ADD_TC(tp, sinf_zero_pos); 292 293 return atf_no_error(); 294 } 295