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