1 /* $NetBSD: t_fenv.c,v 1.6 2019/04/25 20:48:54 kamil Exp $ */
2
3 /*-
4 * Copyright (c) 2014 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Martin Husemann.
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 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: t_fenv.c,v 1.6 2019/04/25 20:48:54 kamil Exp $");
33
34 #include <atf-c.h>
35
36 #include <fenv.h>
37 #ifdef __HAVE_FENV
38
39 #include <ieeefp.h>
40 #include <stdlib.h>
41
42
43 #if (__arm__ && !__SOFTFP__) || __aarch64__
44 /*
45 * Some NEON fpus do not trap on IEEE 754 FP exceptions.
46 * Skip these tests if running on them and compiled for
47 * hard float.
48 */
49 #define FPU_EXC_PREREQ() \
50 if (0 == fpsetmask(fpsetmask(FP_X_INV))) \
51 atf_tc_skip("FPU does not implement traps on FP exceptions");
52
53 /*
54 * Same as above: some don't allow configuring the rounding mode.
55 */
56 #define FPU_RND_PREREQ() \
57 if (0 == fpsetround(fpsetround(FP_RZ))) \
58 atf_tc_skip("FPU does not implement configurable " \
59 "rounding modes");
60 #endif
61
62 #ifndef FPU_EXC_PREREQ
63 #define FPU_EXC_PREREQ() /* nothing */
64 #endif
65 #ifndef FPU_RND_PREREQ
66 #define FPU_RND_PREREQ() /* nothing */
67 #endif
68
69
70 ATF_TC(fegetround);
71
ATF_TC_HEAD(fegetround,tc)72 ATF_TC_HEAD(fegetround, tc)
73 {
74 atf_tc_set_md_var(tc, "descr",
75 "verify the fegetround() function agrees with the legacy "
76 "fpsetround");
77 }
78
ATF_TC_BODY(fegetround,tc)79 ATF_TC_BODY(fegetround, tc)
80 {
81 FPU_RND_PREREQ();
82
83 fpsetround(FP_RZ);
84 ATF_CHECK(fegetround() == FE_TOWARDZERO);
85 fpsetround(FP_RM);
86 ATF_CHECK(fegetround() == FE_DOWNWARD);
87 fpsetround(FP_RN);
88 ATF_CHECK(fegetround() == FE_TONEAREST);
89 fpsetround(FP_RP);
90 ATF_CHECK(fegetround() == FE_UPWARD);
91 }
92
93 ATF_TC(fesetround);
94
ATF_TC_HEAD(fesetround,tc)95 ATF_TC_HEAD(fesetround, tc)
96 {
97 atf_tc_set_md_var(tc, "descr",
98 "verify the fesetround() function agrees with the legacy "
99 "fpgetround");
100 }
101
ATF_TC_BODY(fesetround,tc)102 ATF_TC_BODY(fesetround, tc)
103 {
104 FPU_RND_PREREQ();
105
106 fesetround(FE_TOWARDZERO);
107 ATF_CHECK(fpgetround() == FP_RZ);
108 fesetround(FE_DOWNWARD);
109 ATF_CHECK(fpgetround() == FP_RM);
110 fesetround(FE_TONEAREST);
111 ATF_CHECK(fpgetround() == FP_RN);
112 fesetround(FE_UPWARD);
113 ATF_CHECK(fpgetround() == FP_RP);
114 }
115
116 ATF_TC(fegetexcept);
117
ATF_TC_HEAD(fegetexcept,tc)118 ATF_TC_HEAD(fegetexcept, tc)
119 {
120 atf_tc_set_md_var(tc, "descr",
121 "verify the fegetexcept() function agrees with the legacy "
122 "fpsetmask()");
123 }
124
ATF_TC_BODY(fegetexcept,tc)125 ATF_TC_BODY(fegetexcept, tc)
126 {
127 FPU_EXC_PREREQ();
128
129 fpsetmask(0);
130 ATF_CHECK(fegetexcept() == 0);
131
132 fpsetmask(FP_X_INV|FP_X_DZ|FP_X_OFL|FP_X_UFL|FP_X_IMP);
133 ATF_CHECK(fegetexcept() == (FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW
134 |FE_UNDERFLOW|FE_INEXACT));
135
136 fpsetmask(FP_X_INV);
137 ATF_CHECK(fegetexcept() == FE_INVALID);
138
139 fpsetmask(FP_X_DZ);
140 ATF_CHECK(fegetexcept() == FE_DIVBYZERO);
141
142 fpsetmask(FP_X_OFL);
143 ATF_CHECK(fegetexcept() == FE_OVERFLOW);
144
145 fpsetmask(FP_X_UFL);
146 ATF_CHECK(fegetexcept() == FE_UNDERFLOW);
147
148 fpsetmask(FP_X_IMP);
149 ATF_CHECK(fegetexcept() == FE_INEXACT);
150 }
151
152 ATF_TC(feenableexcept);
153
ATF_TC_HEAD(feenableexcept,tc)154 ATF_TC_HEAD(feenableexcept, tc)
155 {
156 atf_tc_set_md_var(tc, "descr",
157 "verify the feenableexcept() function agrees with the legacy "
158 "fpgetmask()");
159 }
160
ATF_TC_BODY(feenableexcept,tc)161 ATF_TC_BODY(feenableexcept, tc)
162 {
163 FPU_EXC_PREREQ();
164
165 fedisableexcept(FE_ALL_EXCEPT);
166 ATF_CHECK(fpgetmask() == 0);
167
168 feenableexcept(FE_UNDERFLOW);
169 ATF_CHECK(fpgetmask() == FP_X_UFL);
170
171 fedisableexcept(FE_ALL_EXCEPT);
172 feenableexcept(FE_OVERFLOW);
173 ATF_CHECK(fpgetmask() == FP_X_OFL);
174
175 fedisableexcept(FE_ALL_EXCEPT);
176 feenableexcept(FE_DIVBYZERO);
177 ATF_CHECK(fpgetmask() == FP_X_DZ);
178
179 fedisableexcept(FE_ALL_EXCEPT);
180 feenableexcept(FE_INEXACT);
181 ATF_CHECK(fpgetmask() == FP_X_IMP);
182
183 fedisableexcept(FE_ALL_EXCEPT);
184 feenableexcept(FE_INVALID);
185 ATF_CHECK(fpgetmask() == FP_X_INV);
186 }
187
ATF_TP_ADD_TCS(tp)188 ATF_TP_ADD_TCS(tp)
189 {
190 ATF_TP_ADD_TC(tp, fegetround);
191 ATF_TP_ADD_TC(tp, fesetround);
192 ATF_TP_ADD_TC(tp, fegetexcept);
193 ATF_TP_ADD_TC(tp, feenableexcept);
194
195 return atf_no_error();
196 }
197
198 #else /* no fenv.h support */
199
200 ATF_TC(t_nofenv);
201
ATF_TC_HEAD(t_nofenv,tc)202 ATF_TC_HEAD(t_nofenv, tc)
203 {
204 atf_tc_set_md_var(tc, "descr",
205 "dummy test case - no fenv.h support");
206 }
207
208
ATF_TC_BODY(t_nofenv,tc)209 ATF_TC_BODY(t_nofenv, tc)
210 {
211 atf_tc_skip("no fenv.h support on this architecture");
212 }
213
ATF_TP_ADD_TCS(tp)214 ATF_TP_ADD_TCS(tp)
215 {
216 ATF_TP_ADD_TC(tp, t_nofenv);
217 return atf_no_error();
218 }
219
220 #endif
221