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 __i386__ 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(__i386__) */ 50 51 #undef LDBL_MANT_DIG 52 #define LDBL_MANT_DIG DBL_MANT_DIG 53 54 ATF_TC(fpclassify_float); 55 ATF_TC_HEAD(fpclassify_float, tc) 56 { 57 58 atf_tc_set_md_var(tc, "descr", "Test float operations"); 59 } 60 61 ATF_TC_BODY(fpclassify_float, tc) 62 { 63 float d0, d1, d2, f, ip; 64 int e, i; 65 66 d0 = FLT_MIN; 67 ATF_REQUIRE_EQ(fpclassify(d0), FP_NORMAL); 68 f = frexpf(d0, &e); 69 ATF_REQUIRE_EQ(e, FLT_MIN_EXP); 70 ATF_REQUIRE_EQ(f, 0.5); 71 d1 = d0; 72 73 /* shift a "1" bit through the mantissa (skip the implicit bit) */ 74 for (i = 1; i < FLT_MANT_DIG; i++) { 75 d1 /= 2; 76 ATF_REQUIRE_EQ(fpclassify(d1), FP_SUBNORMAL); 77 ATF_REQUIRE(d1 > 0 && d1 < d0); 78 79 d2 = ldexpf(d0, -i); 80 ATF_REQUIRE_EQ(d2, d1); 81 82 d2 = modff(d1, &ip); 83 ATF_REQUIRE_EQ(d2, d1); 84 ATF_REQUIRE_EQ(ip, 0); 85 86 f = frexpf(d1, &e); 87 ATF_REQUIRE_EQ(e, FLT_MIN_EXP - i); 88 ATF_REQUIRE_EQ(f, 0.5); 89 } 90 91 d1 /= 2; 92 ATF_REQUIRE_EQ(fpclassify(d1), FP_ZERO); 93 f = frexpf(d1, &e); 94 ATF_REQUIRE_EQ(e, 0); 95 ATF_REQUIRE_EQ(f, 0); 96 } 97 98 ATF_TC(fpclassify_double); 99 ATF_TC_HEAD(fpclassify_double, tc) 100 { 101 102 atf_tc_set_md_var(tc, "descr", "Test double operations"); 103 } 104 105 ATF_TC_BODY(fpclassify_double, tc) 106 { 107 double d0, d1, d2, f, ip; 108 int e, i; 109 110 d0 = DBL_MIN; 111 ATF_REQUIRE_EQ(fpclassify(d0), FP_NORMAL); 112 f = frexp(d0, &e); 113 ATF_REQUIRE_EQ(e, DBL_MIN_EXP); 114 ATF_REQUIRE_EQ(f, 0.5); 115 d1 = d0; 116 117 /* shift a "1" bit through the mantissa (skip the implicit bit) */ 118 for (i = 1; i < DBL_MANT_DIG; i++) { 119 d1 /= 2; 120 ATF_REQUIRE_EQ(fpclassify(d1), FP_SUBNORMAL); 121 ATF_REQUIRE(d1 > 0 && d1 < d0); 122 123 d2 = ldexp(d0, -i); 124 ATF_REQUIRE_EQ(d2, d1); 125 126 d2 = modf(d1, &ip); 127 ATF_REQUIRE_EQ(d2, d1); 128 ATF_REQUIRE_EQ(ip, 0); 129 130 f = frexp(d1, &e); 131 ATF_REQUIRE_EQ(e, DBL_MIN_EXP - i); 132 ATF_REQUIRE_EQ(f, 0.5); 133 } 134 135 d1 /= 2; 136 ATF_REQUIRE_EQ(fpclassify(d1), FP_ZERO); 137 f = frexp(d1, &e); 138 ATF_REQUIRE_EQ(e, 0); 139 ATF_REQUIRE_EQ(f, 0); 140 } 141 142 /* 143 * XXX NetBSD doesn't have long-double flavors of frexp, ldexp, and modf, 144 * XXX so this test is disabled. 145 */ 146 147 #ifdef TEST_LONG_DOUBLE 148 149 ATF_TC(fpclassify_long_double); 150 ATF_TC_HEAD(fpclassify_long_double, tc) 151 { 152 153 atf_tc_set_md_var(tc, "descr", "Test long double operations"); 154 } 155 156 ATF_TC_BODY(fpclassify_long_double, tc) 157 { 158 long double d0, d1, d2, f, ip; 159 int e, i; 160 161 d0 = LDBL_MIN; 162 ATF_REQUIRE_EQ(fpclassify(d0), FP_NORMAL); 163 f = frexpl(d0, &e); 164 ATF_REQUIRE_EQ(e, LDBL_MIN_EXP); 165 ATF_REQUIRE_EQ(f, 0.5); 166 d1 = d0; 167 168 /* shift a "1" bit through the mantissa (skip the implicit bit) */ 169 for (i = 1; i < LDBL_MANT_DIG; i++) { 170 d1 /= 2; 171 ATF_REQUIRE_EQ(fpclassify(d1), FP_SUBNORMAL); 172 ATF_REQUIRE(d1 > 0 && d1 < d0); 173 174 d2 = ldexpl(d0, -i); 175 ATF_REQUIRE_EQ(d2, d1); 176 177 d2 = modfl(d1, &ip); 178 ATF_REQUIRE_EQ(d2, d1); 179 ATF_REQUIRE_EQ(ip, 0); 180 181 f = frexpl(d1, &e); 182 ATF_REQUIRE_EQ(e, LDBL_MIN_EXP - i); 183 ATF_REQUIRE_EQ(f, 0.5); 184 } 185 186 d1 /= 2; 187 ATF_REQUIRE_EQ(fpclassify(d1), FP_ZERO); 188 f = frexpl(d1, &e); 189 ATF_REQUIRE_EQ(e, 0); 190 ATF_REQUIRE_EQ(f, 0); 191 } 192 #endif /* TEST_LONG_DOUBLE */ 193 #endif /* __i386__ */ 194 195 ATF_TP_ADD_TCS(tp) 196 { 197 198 #ifndef __i386__ 199 ATF_TP_ADD_TC(tp, no_test); 200 #else 201 ATF_TP_ADD_TC(tp, fpclassify_float); 202 ATF_TP_ADD_TC(tp, fpclassify_double); 203 #ifdef TEST_LONG_DOUBLE 204 ATF_TP_ADD_TC(tp, fpclassify_long_double); 205 #endif /* TEST_LONG_DOUBLE */ 206 #endif /* __i386__ */ 207 208 return atf_no_error(); 209 } 210