1/* $NetBSD: t_asin.c,v 1.4 2018/11/07 03:59:36 riastradh 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 <atf-c.h>
33#include <float.h>
34#include <math.h>
35
36static const struct {
37	double x;
38	double y;
39} values[] = {
40	{ -1.0, -M_PI / 2, },
41	{ -0.9, -1.119769514998634, },
42	{ -0.5, -M_PI / 6, },
43	{ -0.1, -0.1001674211615598, },
44	{  0.1,  0.1001674211615598, },
45	{  0.5,  M_PI / 6, },
46	{  0.9,  1.119769514998634, },
47	{  1.0,  M_PI / 2, },
48};
49
50/*
51 * asin(3)
52 */
53ATF_TC(asin_nan);
54ATF_TC_HEAD(asin_nan, tc)
55{
56	atf_tc_set_md_var(tc, "descr", "Test asin(NaN) == NaN");
57}
58
59ATF_TC_BODY(asin_nan, tc)
60{
61	const double x = 0.0L / 0.0L;
62
63	if (isnan(asin(x)) == 0)
64		atf_tc_fail_nonfatal("asin(NaN) != NaN");
65}
66
67ATF_TC(asin_inf_neg);
68ATF_TC_HEAD(asin_inf_neg, tc)
69{
70	atf_tc_set_md_var(tc, "descr", "Test asin(-Inf) == NaN");
71}
72
73ATF_TC_BODY(asin_inf_neg, tc)
74{
75	const double x = -1.0L / 0.0L;
76
77	if (isnan(asin(x)) == 0)
78		atf_tc_fail_nonfatal("asin(-Inf) != NaN");
79}
80
81ATF_TC(asin_inf_pos);
82ATF_TC_HEAD(asin_inf_pos, tc)
83{
84	atf_tc_set_md_var(tc, "descr", "Test asin(+Inf) == NaN");
85}
86
87ATF_TC_BODY(asin_inf_pos, tc)
88{
89	const double x = 1.0L / 0.0L;
90
91	if (isnan(asin(x)) == 0)
92		atf_tc_fail_nonfatal("asin(+Inf) != NaN");
93}
94
95ATF_TC(asin_range);
96ATF_TC_HEAD(asin_range, tc)
97{
98	atf_tc_set_md_var(tc, "descr", "Test asin(x) == NaN, x < -1, x > 1");
99}
100
101ATF_TC_BODY(asin_range, tc)
102{
103	const double x[] = { -1.1, -1.000000001, 1.1, 1.000000001 };
104	size_t i;
105
106	for (i = 0; i < __arraycount(x); i++) {
107
108		if (isnan(asin(x[i])) == 0)
109			atf_tc_fail_nonfatal("asin(%f) != NaN", x[i]);
110	}
111}
112
113ATF_TC(asin_inrange);
114ATF_TC_HEAD(asin_inrange, tc)
115{
116	atf_tc_set_md_var(tc, "descr", "Test asin(x) for some values");
117}
118
119ATF_TC_BODY(asin_inrange, tc)
120{
121	const double eps = DBL_EPSILON;
122	size_t i;
123
124	for (i = 0; i < __arraycount(values); i++) {
125		double x = values[i].x;
126		double y = values[i].y;
127
128		if (!(fabs((asin(x) - y)/y) <= eps))
129			atf_tc_fail_nonfatal("asin(%g) != %g",
130				values[i].x, values[i].y);
131	}
132}
133
134ATF_TC(asin_zero_neg);
135ATF_TC_HEAD(asin_zero_neg, tc)
136{
137	atf_tc_set_md_var(tc, "descr", "Test asin(-0.0) == -0.0");
138}
139
140ATF_TC_BODY(asin_zero_neg, tc)
141{
142	const double x = -0.0L;
143	double y = asin(x);
144
145	if (fabs(y) > 0.0 || signbit(y) == 0)
146		atf_tc_fail_nonfatal("asin(-0.0) != -0.0");
147}
148
149ATF_TC(asin_zero_pos);
150ATF_TC_HEAD(asin_zero_pos, tc)
151{
152	atf_tc_set_md_var(tc, "descr", "Test asin(+0.0) == +0.0");
153}
154
155ATF_TC_BODY(asin_zero_pos, tc)
156{
157	const double x = 0.0L;
158	double y = asin(x);
159
160	if (fabs(y) > 0.0 || signbit(y) != 0)
161		atf_tc_fail_nonfatal("asin(+0.0) != +0.0");
162}
163
164/*
165 * asinf(3)
166 */
167ATF_TC(asinf_nan);
168ATF_TC_HEAD(asinf_nan, tc)
169{
170	atf_tc_set_md_var(tc, "descr", "Test asinf(NaN) == NaN");
171}
172
173ATF_TC_BODY(asinf_nan, tc)
174{
175	const float x = 0.0L / 0.0L;
176
177	if (isnan(asinf(x)) == 0)
178		atf_tc_fail_nonfatal("asinf(NaN) != NaN");
179}
180
181ATF_TC(asinf_inf_neg);
182ATF_TC_HEAD(asinf_inf_neg, tc)
183{
184	atf_tc_set_md_var(tc, "descr", "Test asinf(-Inf) == NaN");
185}
186
187ATF_TC_BODY(asinf_inf_neg, tc)
188{
189	const float x = -1.0L / 0.0L;
190
191	if (isnan(asinf(x)) == 0)
192		atf_tc_fail_nonfatal("asinf(-Inf) != NaN");
193}
194
195ATF_TC(asinf_inf_pos);
196ATF_TC_HEAD(asinf_inf_pos, tc)
197{
198	atf_tc_set_md_var(tc, "descr", "Test asinf(+Inf) == NaN");
199}
200
201ATF_TC_BODY(asinf_inf_pos, tc)
202{
203	const float x = 1.0L / 0.0L;
204
205	if (isnan(asinf(x)) == 0)
206		atf_tc_fail_nonfatal("asinf(+Inf) != NaN");
207}
208
209ATF_TC(asinf_range);
210ATF_TC_HEAD(asinf_range, tc)
211{
212	atf_tc_set_md_var(tc, "descr", "Test asinf(x) == NaN, x < -1, x > 1");
213}
214
215ATF_TC_BODY(asinf_range, tc)
216{
217	const float x[] = { -1.1, -1.0000001, 1.1, 1.0000001 };
218	size_t i;
219
220	for (i = 0; i < __arraycount(x); i++) {
221
222		if (isnan(asinf(x[i])) == 0)
223			atf_tc_fail_nonfatal("asinf(%f) != NaN", x[i]);
224	}
225}
226
227ATF_TC(asinf_inrange);
228ATF_TC_HEAD(asinf_inrange, tc)
229{
230	atf_tc_set_md_var(tc, "descr", "Test asinf(x) for some values");
231}
232
233ATF_TC_BODY(asinf_inrange, tc)
234{
235	const float eps = FLT_EPSILON;
236	size_t i;
237
238	for (i = 0; i < __arraycount(values); i++) {
239		float x = values[i].x;
240		float y = values[i].y;
241
242#ifdef __NetBSD__
243		if (fabs(x) == 0.5)
244			atf_tc_expect_fail("asinf is busted,"
245			    " gives ~2ulp error");
246#endif
247		if (!(fabsf((asinf(x) - y)/y) <= eps)) {
248			atf_tc_fail_nonfatal("asinf(%.8g) = %.8g != %.8g,"
249			    " error=~%.1fulp",
250			    x, asinf(x), y, fabsf(((asinf(x) - y)/y)/eps));
251		}
252		if (fabs(x) == 0.5)
253			atf_tc_expect_pass();
254	}
255}
256
257ATF_TC(asinf_zero_neg);
258ATF_TC_HEAD(asinf_zero_neg, tc)
259{
260	atf_tc_set_md_var(tc, "descr", "Test asinf(-0.0) == -0.0");
261}
262
263ATF_TC_BODY(asinf_zero_neg, tc)
264{
265	const float x = -0.0L;
266	float y = asinf(x);
267
268	if (fabsf(y) > 0.0 || signbit(y) == 0)
269		atf_tc_fail_nonfatal("asinf(-0.0) != -0.0");
270}
271
272ATF_TC(asinf_zero_pos);
273ATF_TC_HEAD(asinf_zero_pos, tc)
274{
275	atf_tc_set_md_var(tc, "descr", "Test asinf(+0.0) == +0.0");
276}
277
278ATF_TC_BODY(asinf_zero_pos, tc)
279{
280	const float x = 0.0L;
281	float y = asinf(x);
282
283	if (fabsf(y) > 0.0 || signbit(y) != 0)
284		atf_tc_fail_nonfatal("asinf(+0.0) != +0.0");
285}
286
287ATF_TP_ADD_TCS(tp)
288{
289
290	ATF_TP_ADD_TC(tp, asin_nan);
291	ATF_TP_ADD_TC(tp, asin_inf_neg);
292	ATF_TP_ADD_TC(tp, asin_inf_pos);
293	ATF_TP_ADD_TC(tp, asin_range);
294	ATF_TP_ADD_TC(tp, asin_inrange);
295	ATF_TP_ADD_TC(tp, asin_zero_neg);
296	ATF_TP_ADD_TC(tp, asin_zero_pos);
297
298	ATF_TP_ADD_TC(tp, asinf_nan);
299	ATF_TP_ADD_TC(tp, asinf_inf_neg);
300	ATF_TP_ADD_TC(tp, asinf_inf_pos);
301	ATF_TP_ADD_TC(tp, asinf_range);
302	ATF_TP_ADD_TC(tp, asinf_inrange);
303	ATF_TP_ADD_TC(tp, asinf_zero_neg);
304	ATF_TP_ADD_TC(tp, asinf_zero_pos);
305
306	return atf_no_error();
307}
308