1 /* $NetBSD: t_fpclassify.c,v 1.3 2011/10/01 21:47:08 christos Exp $ */
2 
3 /*-
4  * Copyright (c) 2011 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <atf-c.h>
30 
31 #include <float.h>
32 #include <math.h>
33 #include <stdio.h>
34 #include <string.h>
35 
36 #ifndef _FLOAT_IEEE754
37 
38 ATF_TC(no_test);
39 ATF_TC_HEAD(no_test, tc)
40 {
41 	atf_tc_set_md_var(tc, "descr", "Dummy test");
42 }
43 
44 ATF_TC_BODY(no_test,tc)
45 {
46 	atf_tc_skip("Test not available on this architecture");
47 }
48 
49 #else /* defined(_FLOAT_IEEE754) */
50 
51 ATF_TC(fpclassify_float);
52 ATF_TC_HEAD(fpclassify_float, tc)
53 {
54 
55 	atf_tc_set_md_var(tc, "descr", "Test float operations");
56 }
57 
58 ATF_TC_BODY(fpclassify_float, tc)
59 {
60 	float d0, d1, d2, f, ip;
61 	int e, i;
62 
63 	d0 = FLT_MIN;
64 	ATF_REQUIRE_EQ(fpclassify(d0), FP_NORMAL);
65 	f = frexpf(d0, &e);
66 	ATF_REQUIRE_EQ(e, FLT_MIN_EXP);
67 	ATF_REQUIRE_EQ(f, 0.5);
68 	d1 = d0;
69 
70 	/* shift a "1" bit through the mantissa (skip the implicit bit) */
71 	for (i = 1; i < FLT_MANT_DIG; i++) {
72 		d1 /= 2;
73 		ATF_REQUIRE_EQ(fpclassify(d1), FP_SUBNORMAL);
74 		ATF_REQUIRE(d1 > 0 && d1 < d0);
75 
76 		d2 = ldexpf(d0, -i);
77 		ATF_REQUIRE_EQ(d2, d1);
78 
79 		d2 = modff(d1, &ip);
80 		ATF_REQUIRE_EQ(d2, d1);
81 		ATF_REQUIRE_EQ(ip, 0);
82 
83 		f = frexpf(d1, &e);
84 		ATF_REQUIRE_EQ(e, FLT_MIN_EXP - i);
85 		ATF_REQUIRE_EQ(f, 0.5);
86 	}
87 
88 	d1 /= 2;
89 	ATF_REQUIRE_EQ(fpclassify(d1), FP_ZERO);
90 	f = frexpf(d1, &e);
91 	ATF_REQUIRE_EQ(e, 0);
92 	ATF_REQUIRE_EQ(f, 0);
93 }
94 
95 ATF_TC(fpclassify_double);
96 ATF_TC_HEAD(fpclassify_double, tc)
97 {
98 
99 	atf_tc_set_md_var(tc, "descr", "Test double operations");
100 }
101 
102 ATF_TC_BODY(fpclassify_double, tc)
103 {
104 	double d0, d1, d2, f, ip;
105 	int e, i;
106 
107 	d0 = DBL_MIN;
108 	ATF_REQUIRE_EQ(fpclassify(d0), FP_NORMAL);
109 	f = frexp(d0, &e);
110 	ATF_REQUIRE_EQ(e, DBL_MIN_EXP);
111 	ATF_REQUIRE_EQ(f, 0.5);
112 	d1 = d0;
113 
114 	/* shift a "1" bit through the mantissa (skip the implicit bit) */
115 	for (i = 1; i < DBL_MANT_DIG; i++) {
116 		d1 /= 2;
117 		ATF_REQUIRE_EQ(fpclassify(d1), FP_SUBNORMAL);
118 		ATF_REQUIRE(d1 > 0 && d1 < d0);
119 
120 		d2 = ldexp(d0, -i);
121 		ATF_REQUIRE_EQ(d2, d1);
122 
123 		d2 = modf(d1, &ip);
124 		ATF_REQUIRE_EQ(d2, d1);
125 		ATF_REQUIRE_EQ(ip, 0);
126 
127 		f = frexp(d1, &e);
128 		ATF_REQUIRE_EQ(e, DBL_MIN_EXP - i);
129 		ATF_REQUIRE_EQ(f, 0.5);
130 	}
131 
132 	d1 /= 2;
133 	ATF_REQUIRE_EQ(fpclassify(d1), FP_ZERO);
134 	f = frexp(d1, &e);
135 	ATF_REQUIRE_EQ(e, 0);
136 	ATF_REQUIRE_EQ(f, 0);
137 }
138 
139 /*
140  * XXX NetBSD doesn't have long-double flavors of frexp, ldexp, and modf,
141  * XXX so this test is disabled.
142  */
143 
144 #ifdef TEST_LONG_DOUBLE
145 
146 ATF_TC(fpclassify_long_double);
147 ATF_TC_HEAD(fpclassify_long_double, tc)
148 {
149 
150 	atf_tc_set_md_var(tc, "descr", "Test long double operations");
151 }
152 
153 ATF_TC_BODY(fpclassify_long_double, tc)
154 {
155 	long double d0, d1, d2, f, ip;
156 	int e, i;
157 
158 	d0 = LDBL_MIN;
159 	ATF_REQUIRE_EQ(fpclassify(d0), FP_NORMAL);
160 	f = frexpl(d0, &e);
161 	ATF_REQUIRE_EQ(e, LDBL_MIN_EXP);
162 	ATF_REQUIRE_EQ(f, 0.5);
163 	d1 = d0;
164 
165 	/* shift a "1" bit through the mantissa (skip the implicit bit) */
166 	for (i = 1; i < LDBL_MANT_DIG; i++) {
167 		d1 /= 2;
168 		ATF_REQUIRE_EQ(fpclassify(d1), FP_SUBNORMAL);
169 		ATF_REQUIRE(d1 > 0 && d1 < d0);
170 
171 		d2 = ldexpl(d0, -i);
172 		ATF_REQUIRE_EQ(d2, d1);
173 
174 		d2 = modfl(d1, &ip);
175 		ATF_REQUIRE_EQ(d2, d1);
176 		ATF_REQUIRE_EQ(ip, 0);
177 
178 		f = frexpl(d1, &e);
179 		ATF_REQUIRE_EQ(e, LDBL_MIN_EXP - i);
180 		ATF_REQUIRE_EQ(f, 0.5);
181 	}
182 
183 	d1 /= 2;
184 	ATF_REQUIRE_EQ(fpclassify(d1), FP_ZERO);
185 	f = frexpl(d1, &e);
186 	ATF_REQUIRE_EQ(e, 0);
187 	ATF_REQUIRE_EQ(f, 0);
188 }
189 #endif /* TEST_LONG_DOUBLE */
190 #endif /* _FLOAT_IEEE754 */
191 
192 ATF_TP_ADD_TCS(tp)
193 {
194 
195 #ifndef _FLOAT_IEEE754
196 	ATF_TP_ADD_TC(tp, no_test);
197 #else
198 	ATF_TP_ADD_TC(tp, fpclassify_float);
199 	ATF_TP_ADD_TC(tp, fpclassify_double);
200 #ifdef TEST_LONG_DOUBLE
201 	ATF_TP_ADD_TC(tp, fpclassify_long_double);
202 #endif /* TEST_LONG_DOUBLE */
203 #endif /* _FLOAT_IEEE754 */
204 
205 	return atf_no_error();
206 }
207