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