xref: /freebsd/contrib/netbsd-tests/lib/libm/t_fenv.c (revision 1ec3feb6)
11ec3feb6SAlex Richardson /* $NetBSD: t_fenv.c,v 1.6 2019/04/25 20:48:54 kamil Exp $ */
2640235e2SEnji Cooper 
3640235e2SEnji Cooper /*-
4640235e2SEnji Cooper  * Copyright (c) 2014 The NetBSD Foundation, Inc.
5640235e2SEnji Cooper  * All rights reserved.
6640235e2SEnji Cooper  *
7640235e2SEnji Cooper  * This code is derived from software contributed to The NetBSD Foundation
8640235e2SEnji Cooper  * by Martin Husemann.
9640235e2SEnji Cooper  *
10640235e2SEnji Cooper  * Redistribution and use in source and binary forms, with or without
11640235e2SEnji Cooper  * modification, are permitted provided that the following conditions
12640235e2SEnji Cooper  * are met:
13640235e2SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
14640235e2SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
15640235e2SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
16640235e2SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
17640235e2SEnji Cooper  *    documentation and/or other materials provided with the distribution.
18640235e2SEnji Cooper  *
19640235e2SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20640235e2SEnji Cooper  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21640235e2SEnji Cooper  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22640235e2SEnji Cooper  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23640235e2SEnji Cooper  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24640235e2SEnji Cooper  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25640235e2SEnji Cooper  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26640235e2SEnji Cooper  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27640235e2SEnji Cooper  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28640235e2SEnji Cooper  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29640235e2SEnji Cooper  * POSSIBILITY OF SUCH DAMAGE.
30640235e2SEnji Cooper  */
31640235e2SEnji Cooper #include <sys/cdefs.h>
321ec3feb6SAlex Richardson __RCSID("$NetBSD: t_fenv.c,v 1.6 2019/04/25 20:48:54 kamil Exp $");
33640235e2SEnji Cooper 
34640235e2SEnji Cooper #include <atf-c.h>
35640235e2SEnji Cooper 
36640235e2SEnji Cooper #include <fenv.h>
37640235e2SEnji Cooper #ifdef __HAVE_FENV
38640235e2SEnji Cooper 
39640235e2SEnji Cooper #include <ieeefp.h>
40640235e2SEnji Cooper #include <stdlib.h>
41640235e2SEnji Cooper 
42640235e2SEnji Cooper 
431ec3feb6SAlex Richardson #if (__arm__ && !__SOFTFP__) || __aarch64__
44640235e2SEnji Cooper 	/*
451ec3feb6SAlex Richardson 	 * Some NEON fpus  do not trap on IEEE 754 FP exceptions.
461ec3feb6SAlex Richardson 	 * Skip these tests if running on them and compiled for
47640235e2SEnji Cooper 	 * hard float.
48640235e2SEnji Cooper 	 */
49640235e2SEnji Cooper #define	FPU_EXC_PREREQ()						\
50640235e2SEnji Cooper 	if (0 == fpsetmask(fpsetmask(FP_X_INV)))			\
511ec3feb6SAlex Richardson 		atf_tc_skip("FPU does not implement traps on FP exceptions");
52640235e2SEnji Cooper 
53640235e2SEnji Cooper 	/*
54640235e2SEnji Cooper 	 * Same as above: some don't allow configuring the rounding mode.
55640235e2SEnji Cooper 	 */
56640235e2SEnji Cooper #define	FPU_RND_PREREQ()						\
57640235e2SEnji Cooper 	if (0 == fpsetround(fpsetround(FP_RZ)))				\
58640235e2SEnji Cooper 		atf_tc_skip("FPU does not implement configurable "	\
59640235e2SEnji Cooper 		    "rounding modes");
60640235e2SEnji Cooper #endif
61640235e2SEnji Cooper 
62640235e2SEnji Cooper #ifndef FPU_EXC_PREREQ
63640235e2SEnji Cooper #define	FPU_EXC_PREREQ()	/* nothing */
64640235e2SEnji Cooper #endif
65640235e2SEnji Cooper #ifndef FPU_RND_PREREQ
66640235e2SEnji Cooper #define	FPU_RND_PREREQ()	/* nothing */
67640235e2SEnji Cooper #endif
68640235e2SEnji Cooper 
69640235e2SEnji Cooper 
70640235e2SEnji Cooper ATF_TC(fegetround);
71640235e2SEnji Cooper 
ATF_TC_HEAD(fegetround,tc)72640235e2SEnji Cooper ATF_TC_HEAD(fegetround, tc)
73640235e2SEnji Cooper {
74640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
75640235e2SEnji Cooper 	    "verify the fegetround() function agrees with the legacy "
76640235e2SEnji Cooper 	    "fpsetround");
77640235e2SEnji Cooper }
78640235e2SEnji Cooper 
ATF_TC_BODY(fegetround,tc)79640235e2SEnji Cooper ATF_TC_BODY(fegetround, tc)
80640235e2SEnji Cooper {
81640235e2SEnji Cooper 	FPU_RND_PREREQ();
82640235e2SEnji Cooper 
83640235e2SEnji Cooper 	fpsetround(FP_RZ);
84640235e2SEnji Cooper 	ATF_CHECK(fegetround() == FE_TOWARDZERO);
85640235e2SEnji Cooper 	fpsetround(FP_RM);
86640235e2SEnji Cooper 	ATF_CHECK(fegetround() == FE_DOWNWARD);
87640235e2SEnji Cooper 	fpsetround(FP_RN);
88640235e2SEnji Cooper 	ATF_CHECK(fegetround() == FE_TONEAREST);
89640235e2SEnji Cooper 	fpsetround(FP_RP);
90640235e2SEnji Cooper 	ATF_CHECK(fegetround() == FE_UPWARD);
91640235e2SEnji Cooper }
92640235e2SEnji Cooper 
93640235e2SEnji Cooper ATF_TC(fesetround);
94640235e2SEnji Cooper 
ATF_TC_HEAD(fesetround,tc)95640235e2SEnji Cooper ATF_TC_HEAD(fesetround, tc)
96640235e2SEnji Cooper {
97640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
98640235e2SEnji Cooper 	    "verify the fesetround() function agrees with the legacy "
99640235e2SEnji Cooper 	    "fpgetround");
100640235e2SEnji Cooper }
101640235e2SEnji Cooper 
ATF_TC_BODY(fesetround,tc)102640235e2SEnji Cooper ATF_TC_BODY(fesetround, tc)
103640235e2SEnji Cooper {
104640235e2SEnji Cooper 	FPU_RND_PREREQ();
105640235e2SEnji Cooper 
106640235e2SEnji Cooper 	fesetround(FE_TOWARDZERO);
107640235e2SEnji Cooper 	ATF_CHECK(fpgetround() == FP_RZ);
108640235e2SEnji Cooper 	fesetround(FE_DOWNWARD);
109640235e2SEnji Cooper 	ATF_CHECK(fpgetround() == FP_RM);
110640235e2SEnji Cooper 	fesetround(FE_TONEAREST);
111640235e2SEnji Cooper 	ATF_CHECK(fpgetround() == FP_RN);
112640235e2SEnji Cooper 	fesetround(FE_UPWARD);
113640235e2SEnji Cooper 	ATF_CHECK(fpgetround() == FP_RP);
114640235e2SEnji Cooper }
115640235e2SEnji Cooper 
116640235e2SEnji Cooper ATF_TC(fegetexcept);
117640235e2SEnji Cooper 
ATF_TC_HEAD(fegetexcept,tc)118640235e2SEnji Cooper ATF_TC_HEAD(fegetexcept, tc)
119640235e2SEnji Cooper {
120640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
121640235e2SEnji Cooper 	    "verify the fegetexcept() function agrees with the legacy "
122640235e2SEnji Cooper 	    "fpsetmask()");
123640235e2SEnji Cooper }
124640235e2SEnji Cooper 
ATF_TC_BODY(fegetexcept,tc)125640235e2SEnji Cooper ATF_TC_BODY(fegetexcept, tc)
126640235e2SEnji Cooper {
127640235e2SEnji Cooper 	FPU_EXC_PREREQ();
128640235e2SEnji Cooper 
129640235e2SEnji Cooper 	fpsetmask(0);
130640235e2SEnji Cooper 	ATF_CHECK(fegetexcept() == 0);
131640235e2SEnji Cooper 
132640235e2SEnji Cooper 	fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
133640235e2SEnji Cooper 	ATF_CHECK(fegetexcept() == (FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW
134640235e2SEnji Cooper 	    |FE_UNDERFLOW|FE_INEXACT));
135640235e2SEnji Cooper 
136640235e2SEnji Cooper 	fpsetmask(FP_X_INV);
137640235e2SEnji Cooper 	ATF_CHECK(fegetexcept() == FE_INVALID);
138640235e2SEnji Cooper 
139640235e2SEnji Cooper 	fpsetmask(FP_X_DZ);
140640235e2SEnji Cooper 	ATF_CHECK(fegetexcept() == FE_DIVBYZERO);
141640235e2SEnji Cooper 
142640235e2SEnji Cooper 	fpsetmask(FP_X_OFL);
143640235e2SEnji Cooper 	ATF_CHECK(fegetexcept() == FE_OVERFLOW);
144640235e2SEnji Cooper 
145640235e2SEnji Cooper 	fpsetmask(FP_X_UFL);
146640235e2SEnji Cooper 	ATF_CHECK(fegetexcept() == FE_UNDERFLOW);
147640235e2SEnji Cooper 
148640235e2SEnji Cooper 	fpsetmask(FP_X_IMP);
149640235e2SEnji Cooper 	ATF_CHECK(fegetexcept() == FE_INEXACT);
150640235e2SEnji Cooper }
151640235e2SEnji Cooper 
152640235e2SEnji Cooper ATF_TC(feenableexcept);
153640235e2SEnji Cooper 
ATF_TC_HEAD(feenableexcept,tc)154640235e2SEnji Cooper ATF_TC_HEAD(feenableexcept, tc)
155640235e2SEnji Cooper {
156640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
157640235e2SEnji Cooper 	    "verify the feenableexcept() function agrees with the legacy "
158640235e2SEnji Cooper 	    "fpgetmask()");
159640235e2SEnji Cooper }
160640235e2SEnji Cooper 
ATF_TC_BODY(feenableexcept,tc)161640235e2SEnji Cooper ATF_TC_BODY(feenableexcept, tc)
162640235e2SEnji Cooper {
163640235e2SEnji Cooper 	FPU_EXC_PREREQ();
164640235e2SEnji Cooper 
165640235e2SEnji Cooper 	fedisableexcept(FE_ALL_EXCEPT);
166640235e2SEnji Cooper 	ATF_CHECK(fpgetmask() == 0);
167640235e2SEnji Cooper 
168640235e2SEnji Cooper 	feenableexcept(FE_UNDERFLOW);
169640235e2SEnji Cooper 	ATF_CHECK(fpgetmask() == FP_X_UFL);
170640235e2SEnji Cooper 
171640235e2SEnji Cooper 	fedisableexcept(FE_ALL_EXCEPT);
172640235e2SEnji Cooper 	feenableexcept(FE_OVERFLOW);
173640235e2SEnji Cooper 	ATF_CHECK(fpgetmask() == FP_X_OFL);
174640235e2SEnji Cooper 
175640235e2SEnji Cooper 	fedisableexcept(FE_ALL_EXCEPT);
176640235e2SEnji Cooper 	feenableexcept(FE_DIVBYZERO);
177640235e2SEnji Cooper 	ATF_CHECK(fpgetmask() == FP_X_DZ);
178640235e2SEnji Cooper 
179640235e2SEnji Cooper 	fedisableexcept(FE_ALL_EXCEPT);
180640235e2SEnji Cooper 	feenableexcept(FE_INEXACT);
181640235e2SEnji Cooper 	ATF_CHECK(fpgetmask() == FP_X_IMP);
182640235e2SEnji Cooper 
183640235e2SEnji Cooper 	fedisableexcept(FE_ALL_EXCEPT);
184640235e2SEnji Cooper 	feenableexcept(FE_INVALID);
185640235e2SEnji Cooper 	ATF_CHECK(fpgetmask() == FP_X_INV);
186640235e2SEnji Cooper }
187640235e2SEnji Cooper 
ATF_TP_ADD_TCS(tp)188640235e2SEnji Cooper ATF_TP_ADD_TCS(tp)
189640235e2SEnji Cooper {
190640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, fegetround);
191640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, fesetround);
192640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, fegetexcept);
193640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, feenableexcept);
194640235e2SEnji Cooper 
195640235e2SEnji Cooper 	return atf_no_error();
196640235e2SEnji Cooper }
197640235e2SEnji Cooper 
198640235e2SEnji Cooper #else	/* no fenv.h support */
199640235e2SEnji Cooper 
200640235e2SEnji Cooper ATF_TC(t_nofenv);
201640235e2SEnji Cooper 
ATF_TC_HEAD(t_nofenv,tc)202640235e2SEnji Cooper ATF_TC_HEAD(t_nofenv, tc)
203640235e2SEnji Cooper {
204640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
205640235e2SEnji Cooper 	    "dummy test case - no fenv.h support");
206640235e2SEnji Cooper }
207640235e2SEnji Cooper 
208640235e2SEnji Cooper 
ATF_TC_BODY(t_nofenv,tc)209640235e2SEnji Cooper ATF_TC_BODY(t_nofenv, tc)
210640235e2SEnji Cooper {
211640235e2SEnji Cooper 	atf_tc_skip("no fenv.h support on this architecture");
212640235e2SEnji Cooper }
213640235e2SEnji Cooper 
ATF_TP_ADD_TCS(tp)214640235e2SEnji Cooper ATF_TP_ADD_TCS(tp)
215640235e2SEnji Cooper {
216640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, t_nofenv);
217640235e2SEnji Cooper 	return atf_no_error();
218640235e2SEnji Cooper }
219640235e2SEnji Cooper 
220640235e2SEnji Cooper #endif
221