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 37static 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 */ 64ATF_TC(sin_angles); 65ATF_TC_HEAD(sin_angles, tc) 66{ 67 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 68} 69 70ATF_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 98ATF_TC(sin_nan); 99ATF_TC_HEAD(sin_nan, tc) 100{ 101 atf_tc_set_md_var(tc, "descr", "Test sin(NaN) == NaN"); 102} 103 104ATF_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 112ATF_TC(sin_inf_neg); 113ATF_TC_HEAD(sin_inf_neg, tc) 114{ 115 atf_tc_set_md_var(tc, "descr", "Test sin(-Inf) == NaN"); 116} 117 118ATF_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 125ATF_TC(sin_inf_pos); 126ATF_TC_HEAD(sin_inf_pos, tc) 127{ 128 atf_tc_set_md_var(tc, "descr", "Test sin(+Inf) == NaN"); 129} 130 131ATF_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 139ATF_TC(sin_zero_neg); 140ATF_TC_HEAD(sin_zero_neg, tc) 141{ 142 atf_tc_set_md_var(tc, "descr", "Test sin(-0.0) == -0.0"); 143} 144 145ATF_TC_BODY(sin_zero_neg, tc) 146{ 147 const double x = -0.0L; 148 149 ATF_CHECK(sin(x) == x); 150} 151 152ATF_TC(sin_zero_pos); 153ATF_TC_HEAD(sin_zero_pos, tc) 154{ 155 atf_tc_set_md_var(tc, "descr", "Test sin(+0.0) == +0.0"); 156} 157 158ATF_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 */ 168ATF_TC(sinf_angles); 169ATF_TC_HEAD(sinf_angles, tc) 170{ 171 atf_tc_set_md_var(tc, "descr", "Test some selected angles"); 172} 173 174ATF_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 203ATF_TC(sinf_nan); 204ATF_TC_HEAD(sinf_nan, tc) 205{ 206 atf_tc_set_md_var(tc, "descr", "Test sinf(NaN) == NaN"); 207} 208 209ATF_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 217ATF_TC(sinf_inf_neg); 218ATF_TC_HEAD(sinf_inf_neg, tc) 219{ 220 atf_tc_set_md_var(tc, "descr", "Test sinf(-Inf) == NaN"); 221} 222 223ATF_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 233ATF_TC(sinf_inf_pos); 234ATF_TC_HEAD(sinf_inf_pos, tc) 235{ 236 atf_tc_set_md_var(tc, "descr", "Test sinf(+Inf) == NaN"); 237} 238 239ATF_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 250ATF_TC(sinf_zero_neg); 251ATF_TC_HEAD(sinf_zero_neg, tc) 252{ 253 atf_tc_set_md_var(tc, "descr", "Test sinf(-0.0) == -0.0"); 254} 255 256ATF_TC_BODY(sinf_zero_neg, tc) 257{ 258 const float x = -0.0L; 259 260 ATF_CHECK(sinf(x) == x); 261} 262 263ATF_TC(sinf_zero_pos); 264ATF_TC_HEAD(sinf_zero_pos, tc) 265{ 266 atf_tc_set_md_var(tc, "descr", "Test sinf(+0.0) == +0.0"); 267} 268 269ATF_TC_BODY(sinf_zero_pos, tc) 270{ 271 const float x = 0.0L; 272 273 ATF_CHECK(sinf(x) == x); 274} 275 276ATF_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