xref: /netbsd-src/tests/lib/libm/t_sin.c (revision 6442493f2ffd9de79989674a2201aa1c86eff8b6)
1*6442493fSriastradh /* $NetBSD: t_sin.c,v 1.8 2024/06/09 16:53:12 riastradh Exp $ */
28f667ecfSjruoho 
38f667ecfSjruoho /*-
48f667ecfSjruoho  * Copyright (c) 2011 The NetBSD Foundation, Inc.
58f667ecfSjruoho  * All rights reserved.
68f667ecfSjruoho  *
78f667ecfSjruoho  * This code is derived from software contributed to The NetBSD Foundation
88f667ecfSjruoho  * by Jukka Ruohonen.
98f667ecfSjruoho  *
108f667ecfSjruoho  * Redistribution and use in source and binary forms, with or without
118f667ecfSjruoho  * modification, are permitted provided that the following conditions
128f667ecfSjruoho  * are met:
138f667ecfSjruoho  * 1. Redistributions of source code must retain the above copyright
148f667ecfSjruoho  *    notice, this list of conditions and the following disclaimer.
158f667ecfSjruoho  * 2. Redistributions in binary form must reproduce the above copyright
168f667ecfSjruoho  *    notice, this list of conditions and the following disclaimer in the
178f667ecfSjruoho  *    documentation and/or other materials provided with the distribution.
188f667ecfSjruoho  *
198f667ecfSjruoho  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
208f667ecfSjruoho  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
218f667ecfSjruoho  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
228f667ecfSjruoho  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
238f667ecfSjruoho  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
248f667ecfSjruoho  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
258f667ecfSjruoho  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
268f667ecfSjruoho  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
278f667ecfSjruoho  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
288f667ecfSjruoho  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
298f667ecfSjruoho  * POSSIBILITY OF SUCH DAMAGE.
308f667ecfSjruoho  */
318f667ecfSjruoho 
32a8a8e5f5Sriastradh #include <assert.h>
338f667ecfSjruoho #include <atf-c.h>
34a8a8e5f5Sriastradh #include <float.h>
358f667ecfSjruoho #include <math.h>
368f667ecfSjruoho 
378f667ecfSjruoho static const struct {
388f667ecfSjruoho 	int		angle;
398f667ecfSjruoho 	double		x;
408f667ecfSjruoho 	double		y;
41a8a8e5f5Sriastradh 	float		fy;
428f667ecfSjruoho } angles[] = {
43a8a8e5f5Sriastradh 	{ -360, -6.283185307179586,  2.4492935982947064e-16, -1.7484555e-07 },
44a8a8e5f5Sriastradh 	{ -180, -3.141592653589793, -1.2246467991473532e-16, 8.7422777e-08 },
45a8a8e5f5Sriastradh 	{ -135, -2.356194490192345, -0.7071067811865476, 999 },
46a8a8e5f5Sriastradh 	{  -90, -1.570796326794897, -1.0000000000000000, 999 },
47a8a8e5f5Sriastradh 	{  -45, -0.785398163397448, -0.7071067811865472, 999 },
48a8a8e5f5Sriastradh 	{    0,  0.000000000000000,  0.0000000000000000, 999 },
49a8a8e5f5Sriastradh 	{   30,  0.5235987755982989, 0.5000000000000000, 999 },
50a8a8e5f5Sriastradh 	{   45,  0.785398163397448,  0.7071067811865472, 999 },
51a8a8e5f5Sriastradh 	{   60,  1.047197551196598,  0.8660254037844388, 999 },
52a8a8e5f5Sriastradh 	{   90,  1.570796326794897,  1.0000000000000000, 999 },
53a8a8e5f5Sriastradh 	{  120,  2.094395102393195,  0.8660254037844389, 999 },
54a8a8e5f5Sriastradh 	{  135,  2.356194490192345,  0.7071067811865476, 999 },
55a8a8e5f5Sriastradh 	{  150,  2.617993877991494,  0.5000000000000003, 999 },
56a8a8e5f5Sriastradh 	{  180,  3.141592653589793,  1.2246467991473532e-16, -8.7422777e-08 },
57a8a8e5f5Sriastradh 	{  270,  4.712388980384690, -1.0000000000000000, 999 },
58a8a8e5f5Sriastradh 	{  360,  6.283185307179586, -2.4492935982947064e-16, 1.7484555e-07 },
598f667ecfSjruoho };
608f667ecfSjruoho 
618f667ecfSjruoho /*
628f667ecfSjruoho  * sin(3)
638f667ecfSjruoho  */
648f667ecfSjruoho ATF_TC(sin_angles);
ATF_TC_HEAD(sin_angles,tc)658f667ecfSjruoho ATF_TC_HEAD(sin_angles, tc)
668f667ecfSjruoho {
678f667ecfSjruoho 	atf_tc_set_md_var(tc, "descr", "Test some selected angles");
688f667ecfSjruoho }
698f667ecfSjruoho 
ATF_TC_BODY(sin_angles,tc)708f667ecfSjruoho ATF_TC_BODY(sin_angles, tc)
718f667ecfSjruoho {
72a8a8e5f5Sriastradh 	const double eps = DBL_EPSILON;
738f667ecfSjruoho 	size_t i;
748f667ecfSjruoho 
758f667ecfSjruoho 	for (i = 0; i < __arraycount(angles); i++) {
76a8a8e5f5Sriastradh 		int deg = angles[i].angle;
77a8a8e5f5Sriastradh 		double theta = angles[i].x;
78a8a8e5f5Sriastradh 		double sin_theta = angles[i].y;
79a8a8e5f5Sriastradh 		bool ok;
808f667ecfSjruoho 
81a8a8e5f5Sriastradh 		if (sin_theta == 0) {
82a8a8e5f5Sriastradh 			/* Should be computed exactly.  */
83a8a8e5f5Sriastradh 			assert(sin_theta == 0);
84a8a8e5f5Sriastradh 			ok = (sin(theta) == 0);
85a8a8e5f5Sriastradh 		} else {
86a8a8e5f5Sriastradh 			assert(sin_theta != 0);
87a8a8e5f5Sriastradh 			ok = (fabs((sin(theta) - sin_theta)/sin_theta) <= eps);
88a8a8e5f5Sriastradh 		}
89a8a8e5f5Sriastradh 
90a8a8e5f5Sriastradh 		if (!ok) {
91a8a8e5f5Sriastradh 			atf_tc_fail_nonfatal("sin(%d deg = %.17g) = %.17g"
92a8a8e5f5Sriastradh 			    " != %.17g",
93a8a8e5f5Sriastradh 			    deg, theta, sin(theta), sin_theta);
94a8a8e5f5Sriastradh 		}
958f667ecfSjruoho 	}
968f667ecfSjruoho }
978f667ecfSjruoho 
988f667ecfSjruoho ATF_TC(sin_nan);
ATF_TC_HEAD(sin_nan,tc)998f667ecfSjruoho ATF_TC_HEAD(sin_nan, tc)
1008f667ecfSjruoho {
1018f667ecfSjruoho 	atf_tc_set_md_var(tc, "descr", "Test sin(NaN) == NaN");
1028f667ecfSjruoho }
1038f667ecfSjruoho 
ATF_TC_BODY(sin_nan,tc)1048f667ecfSjruoho ATF_TC_BODY(sin_nan, tc)
1058f667ecfSjruoho {
1068f667ecfSjruoho 	const double x = 0.0L / 0.0L;
1078f667ecfSjruoho 
1088f667ecfSjruoho 	ATF_CHECK(isnan(x) != 0);
1098f667ecfSjruoho 	ATF_CHECK(isnan(sin(x)) != 0);
1108f667ecfSjruoho }
1118f667ecfSjruoho 
1128f667ecfSjruoho ATF_TC(sin_inf_neg);
ATF_TC_HEAD(sin_inf_neg,tc)1138f667ecfSjruoho ATF_TC_HEAD(sin_inf_neg, tc)
1148f667ecfSjruoho {
1158f667ecfSjruoho 	atf_tc_set_md_var(tc, "descr", "Test sin(-Inf) == NaN");
1168f667ecfSjruoho }
1178f667ecfSjruoho 
ATF_TC_BODY(sin_inf_neg,tc)1188f667ecfSjruoho ATF_TC_BODY(sin_inf_neg, tc)
1198f667ecfSjruoho {
120*6442493fSriastradh 	const volatile double x = -1.0 / 0.0;
121*6442493fSriastradh 	const double y = sin(x);
1228f667ecfSjruoho 
123*6442493fSriastradh 	ATF_CHECK_MSG(isnan(y), "y=%a", y);
1248f667ecfSjruoho }
1258f667ecfSjruoho 
1268f667ecfSjruoho ATF_TC(sin_inf_pos);
ATF_TC_HEAD(sin_inf_pos,tc)1278f667ecfSjruoho ATF_TC_HEAD(sin_inf_pos, tc)
1288f667ecfSjruoho {
1298f667ecfSjruoho 	atf_tc_set_md_var(tc, "descr", "Test sin(+Inf) == NaN");
1308f667ecfSjruoho }
1318f667ecfSjruoho 
ATF_TC_BODY(sin_inf_pos,tc)1328f667ecfSjruoho ATF_TC_BODY(sin_inf_pos, tc)
1338f667ecfSjruoho {
134*6442493fSriastradh 	const volatile double x = 1.0 / 0.0;
135*6442493fSriastradh 	const double y = sin(x);
1368f667ecfSjruoho 
137*6442493fSriastradh 	ATF_CHECK_MSG(isnan(y), "y=%a", y);
1388f667ecfSjruoho }
1398f667ecfSjruoho 
1408f667ecfSjruoho 
1418f667ecfSjruoho ATF_TC(sin_zero_neg);
ATF_TC_HEAD(sin_zero_neg,tc)1428f667ecfSjruoho ATF_TC_HEAD(sin_zero_neg, tc)
1438f667ecfSjruoho {
1448f667ecfSjruoho 	atf_tc_set_md_var(tc, "descr", "Test sin(-0.0) == -0.0");
1458f667ecfSjruoho }
1468f667ecfSjruoho 
ATF_TC_BODY(sin_zero_neg,tc)1478f667ecfSjruoho ATF_TC_BODY(sin_zero_neg, tc)
1488f667ecfSjruoho {
1498f667ecfSjruoho 	const double x = -0.0L;
1508f667ecfSjruoho 
1518f667ecfSjruoho 	ATF_CHECK(sin(x) == x);
1528f667ecfSjruoho }
1538f667ecfSjruoho 
1548f667ecfSjruoho ATF_TC(sin_zero_pos);
ATF_TC_HEAD(sin_zero_pos,tc)1558f667ecfSjruoho ATF_TC_HEAD(sin_zero_pos, tc)
1568f667ecfSjruoho {
1578f667ecfSjruoho 	atf_tc_set_md_var(tc, "descr", "Test sin(+0.0) == +0.0");
1588f667ecfSjruoho }
1598f667ecfSjruoho 
ATF_TC_BODY(sin_zero_pos,tc)1608f667ecfSjruoho ATF_TC_BODY(sin_zero_pos, tc)
1618f667ecfSjruoho {
1628f667ecfSjruoho 	const double x = 0.0L;
1638f667ecfSjruoho 
1648f667ecfSjruoho 	ATF_CHECK(sin(x) == x);
1658f667ecfSjruoho }
1668f667ecfSjruoho 
1678f667ecfSjruoho /*
1688f667ecfSjruoho  * sinf(3)
1698f667ecfSjruoho  */
1708f667ecfSjruoho ATF_TC(sinf_angles);
ATF_TC_HEAD(sinf_angles,tc)1718f667ecfSjruoho ATF_TC_HEAD(sinf_angles, tc)
1728f667ecfSjruoho {
1738f667ecfSjruoho 	atf_tc_set_md_var(tc, "descr", "Test some selected angles");
1748f667ecfSjruoho }
1758f667ecfSjruoho 
ATF_TC_BODY(sinf_angles,tc)1768f667ecfSjruoho ATF_TC_BODY(sinf_angles, tc)
1778f667ecfSjruoho {
178a8a8e5f5Sriastradh 	const float eps = FLT_EPSILON;
1798f667ecfSjruoho 	size_t i;
1808f667ecfSjruoho 
1818f667ecfSjruoho 	for (i = 0; i < __arraycount(angles); i++) {
182a8a8e5f5Sriastradh 		int deg = angles[i].angle;
183a8a8e5f5Sriastradh 		float theta = angles[i].x;
184a8a8e5f5Sriastradh 		float sin_theta = angles[i].fy;
185a8a8e5f5Sriastradh 		bool ok;
1868f667ecfSjruoho 
187a8a8e5f5Sriastradh 		if (sin_theta == 999)
188a8a8e5f5Sriastradh 			sin_theta = angles[i].y;
1898f667ecfSjruoho 
190a8a8e5f5Sriastradh 		if (sin_theta == 0) {
191a8a8e5f5Sriastradh 			/* Should be computed exactly.  */
192a8a8e5f5Sriastradh 			ok = (sinf(theta) == 0);
193a8a8e5f5Sriastradh 		} else {
194a8a8e5f5Sriastradh 			ok = (fabsf((sinf(theta) - sin_theta)/sin_theta)
195a8a8e5f5Sriastradh 			    <= eps);
196a8a8e5f5Sriastradh 		}
197a8a8e5f5Sriastradh 
198a8a8e5f5Sriastradh 		if (!ok) {
1996eb8aac8Smaya 			atf_tc_fail_nonfatal("sinf(%d deg) = %.8g != %.8g",
2006eb8aac8Smaya 			    deg, sinf(theta), sin_theta);
201a8a8e5f5Sriastradh 		}
2028f667ecfSjruoho 	}
2038f667ecfSjruoho }
2048f667ecfSjruoho 
2058f667ecfSjruoho ATF_TC(sinf_nan);
ATF_TC_HEAD(sinf_nan,tc)2068f667ecfSjruoho ATF_TC_HEAD(sinf_nan, tc)
2078f667ecfSjruoho {
2088f667ecfSjruoho 	atf_tc_set_md_var(tc, "descr", "Test sinf(NaN) == NaN");
2098f667ecfSjruoho }
2108f667ecfSjruoho 
ATF_TC_BODY(sinf_nan,tc)2118f667ecfSjruoho ATF_TC_BODY(sinf_nan, tc)
2128f667ecfSjruoho {
2138f667ecfSjruoho 	const float x = 0.0L / 0.0L;
2148f667ecfSjruoho 
2158f667ecfSjruoho 	ATF_CHECK(isnan(x) != 0);
2168f667ecfSjruoho 	ATF_CHECK(isnan(sinf(x)) != 0);
2178f667ecfSjruoho }
2188f667ecfSjruoho 
2198f667ecfSjruoho ATF_TC(sinf_inf_neg);
ATF_TC_HEAD(sinf_inf_neg,tc)2208f667ecfSjruoho ATF_TC_HEAD(sinf_inf_neg, tc)
2218f667ecfSjruoho {
2228f667ecfSjruoho 	atf_tc_set_md_var(tc, "descr", "Test sinf(-Inf) == NaN");
2238f667ecfSjruoho }
2248f667ecfSjruoho 
ATF_TC_BODY(sinf_inf_neg,tc)2258f667ecfSjruoho ATF_TC_BODY(sinf_inf_neg, tc)
2268f667ecfSjruoho {
227*6442493fSriastradh 	const volatile float x = -1.0f / 0.0f;
228*6442493fSriastradh 	const float y = sinf(x);
2298f667ecfSjruoho 
230*6442493fSriastradh 	ATF_CHECK_MSG(isnan(y), "y=%a", y);
2318f667ecfSjruoho }
2328f667ecfSjruoho 
2338f667ecfSjruoho ATF_TC(sinf_inf_pos);
ATF_TC_HEAD(sinf_inf_pos,tc)2348f667ecfSjruoho ATF_TC_HEAD(sinf_inf_pos, tc)
2358f667ecfSjruoho {
2368f667ecfSjruoho 	atf_tc_set_md_var(tc, "descr", "Test sinf(+Inf) == NaN");
2378f667ecfSjruoho }
2388f667ecfSjruoho 
ATF_TC_BODY(sinf_inf_pos,tc)2398f667ecfSjruoho ATF_TC_BODY(sinf_inf_pos, tc)
2408f667ecfSjruoho {
241*6442493fSriastradh 	const volatile float x = -1.0f / 0.0f;
242*6442493fSriastradh 	const float y = sinf(x);
2438f667ecfSjruoho 
244*6442493fSriastradh 	ATF_CHECK_MSG(isnan(y), "y=%a", y);
2458f667ecfSjruoho }
2468f667ecfSjruoho 
2478f667ecfSjruoho 
2488f667ecfSjruoho ATF_TC(sinf_zero_neg);
ATF_TC_HEAD(sinf_zero_neg,tc)2498f667ecfSjruoho ATF_TC_HEAD(sinf_zero_neg, tc)
2508f667ecfSjruoho {
2518f667ecfSjruoho 	atf_tc_set_md_var(tc, "descr", "Test sinf(-0.0) == -0.0");
2528f667ecfSjruoho }
2538f667ecfSjruoho 
ATF_TC_BODY(sinf_zero_neg,tc)2548f667ecfSjruoho ATF_TC_BODY(sinf_zero_neg, tc)
2558f667ecfSjruoho {
2568f667ecfSjruoho 	const float x = -0.0L;
2578f667ecfSjruoho 
2588f667ecfSjruoho 	ATF_CHECK(sinf(x) == x);
2598f667ecfSjruoho }
2608f667ecfSjruoho 
2618f667ecfSjruoho ATF_TC(sinf_zero_pos);
ATF_TC_HEAD(sinf_zero_pos,tc)2628f667ecfSjruoho ATF_TC_HEAD(sinf_zero_pos, tc)
2638f667ecfSjruoho {
2648f667ecfSjruoho 	atf_tc_set_md_var(tc, "descr", "Test sinf(+0.0) == +0.0");
2658f667ecfSjruoho }
2668f667ecfSjruoho 
ATF_TC_BODY(sinf_zero_pos,tc)2678f667ecfSjruoho ATF_TC_BODY(sinf_zero_pos, tc)
2688f667ecfSjruoho {
2698f667ecfSjruoho 	const float x = 0.0L;
2708f667ecfSjruoho 
2718f667ecfSjruoho 	ATF_CHECK(sinf(x) == x);
2728f667ecfSjruoho }
2738f667ecfSjruoho 
ATF_TP_ADD_TCS(tp)2748f667ecfSjruoho ATF_TP_ADD_TCS(tp)
2758f667ecfSjruoho {
2768f667ecfSjruoho 
2778f667ecfSjruoho 	ATF_TP_ADD_TC(tp, sin_angles);
2788f667ecfSjruoho 	ATF_TP_ADD_TC(tp, sin_nan);
2798f667ecfSjruoho 	ATF_TP_ADD_TC(tp, sin_inf_neg);
2808f667ecfSjruoho 	ATF_TP_ADD_TC(tp, sin_inf_pos);
2818f667ecfSjruoho 	ATF_TP_ADD_TC(tp, sin_zero_neg);
2828f667ecfSjruoho 	ATF_TP_ADD_TC(tp, sin_zero_pos);
2838f667ecfSjruoho 
2848f667ecfSjruoho 	ATF_TP_ADD_TC(tp, sinf_angles);
2858f667ecfSjruoho 	ATF_TP_ADD_TC(tp, sinf_nan);
2868f667ecfSjruoho 	ATF_TP_ADD_TC(tp, sinf_inf_neg);
2878f667ecfSjruoho 	ATF_TP_ADD_TC(tp, sinf_inf_pos);
2888f667ecfSjruoho 	ATF_TP_ADD_TC(tp, sinf_zero_neg);
2898f667ecfSjruoho 	ATF_TP_ADD_TC(tp, sinf_zero_pos);
2908f667ecfSjruoho 
2918f667ecfSjruoho 	return atf_no_error();
2928f667ecfSjruoho }
293