t_fenv.c revision 313498
1/* $NetBSD: t_fenv.c,v 1.3 2015/12/22 14:20:59 christos 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.3 2015/12/22 14:20:59 christos 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__
44	/*
45	 * Some NEON fpus do not implement IEEE exception handling,
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 exception handling");
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
70ATF_TC(fegetround);
71
72ATF_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
79ATF_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
93ATF_TC(fesetround);
94
95ATF_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
102ATF_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
116ATF_TC(fegetexcept);
117
118ATF_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
125ATF_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
152ATF_TC(feenableexcept);
153
154ATF_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
161ATF_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
188ATF_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
200ATF_TC(t_nofenv);
201
202ATF_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
209ATF_TC_BODY(t_nofenv, tc)
210{
211	atf_tc_skip("no fenv.h support on this architecture");
212}
213
214ATF_TP_ADD_TCS(tp)
215{
216	ATF_TP_ADD_TC(tp, t_nofenv);
217	return atf_no_error();
218}
219
220#endif
221