Home | History | Annotate | Line # | Download | only in libm
t_sin.c revision 1.4.24.1
      1 /* $NetBSD: t_sin.c,v 1.4.24.1 2018/11/26 01:52:53 pgoyette 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) = %.17g != %.17g",
    198 			    deg, (double)sin(theta), (double)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