1/* $NetBSD: t_fpclassify.c,v 1.6 2024/05/09 14:44:39 riastradh 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 36ATF_TC(fpclassify_float); 37ATF_TC_HEAD(fpclassify_float, tc) 38{ 39 40 atf_tc_set_md_var(tc, "descr", "Test float operations"); 41} 42 43ATF_TC_BODY(fpclassify_float, tc) 44{ 45 float d0, d1, d2, f, ip; 46 int e, i; 47 48 d0 = FLT_MIN; 49 ATF_CHECK_EQ_MSG(fpclassify(d0), FP_NORMAL, 50 "fpclassify(%a)=%d FP_NORMAL=%d", 51 d0, fpclassify(d0), FP_NORMAL); 52 f = frexpf(d0, &e); 53 ATF_CHECK_EQ_MSG(e, FLT_MIN_EXP, 54 "frexpf(%a) returned normalized %a, exponent %d;" 55 " expected normalized %a, exponent %d", 56 d0, f, e, 0.5, FLT_MIN_EXP); 57 ATF_CHECK_EQ_MSG(f, 0.5, 58 "frexpf(%a) returned normalized %a, exponent %d;" 59 " expected normalized %a, exponent %d", 60 d0, f, e, 0.5, FLT_MIN_EXP); 61 d1 = d0; 62 63#ifdef __FLT_HAS_DENORM__ 64 /* shift a "1" bit through the mantissa (skip the implicit bit) */ 65 for (i = 1; i < FLT_MANT_DIG; i++) { 66 d1 /= 2; 67 ATF_CHECK_EQ_MSG(fpclassify(d1), FP_SUBNORMAL, 68 "[%d] fpclassify(%a)=%d FP_SUBNORMAL=%d", 69 i, d1, fpclassify(d1), FP_SUBNORMAL); 70 ATF_CHECK_MSG(d1 > 0 && d1 < d0, 71 "[%d] d1=%a d0=%a", i, d1, d0); 72 73 d2 = ldexpf(d0, -i); 74 ATF_CHECK_EQ_MSG(d2, d1, "[%d] ldexpf(%a, -%d)=%a != %a", 75 i, d0, i, d2, d1); 76 77 d2 = modff(d1, &ip); 78 ATF_CHECK_EQ_MSG(d2, d1, 79 "[%d] modff(%a) returned int %a, frac %a;" 80 " expected int %a, frac %a", 81 i, d1, ip, d2, 0., d1); 82 ATF_CHECK_EQ_MSG(ip, 0, 83 "[%d] modff(%a) returned int %a, frac %a;" 84 " expected int %a, frac %a", 85 i, d1, ip, d2, 0., d1); 86 87 f = frexpf(d1, &e); 88 ATF_CHECK_EQ_MSG(e, FLT_MIN_EXP - i, 89 "[%d] frexpf(%a) returned normalized %a, exponent %d;" 90 " expected normalized %a, exponent %d", 91 i, d1, f, e, 0.5, FLT_MIN_EXP - i); 92 ATF_CHECK_EQ_MSG(f, 0.5, 93 "[%d] frexpf(%a) returned normalized %a, exponent %d;" 94 " expected normalized %a, exponent %d", 95 i, d1, f, e, 0.5, FLT_MIN_EXP - i); 96 } 97#endif 98 99 d1 /= 2; 100 ATF_CHECK_EQ_MSG(fpclassify(d1), FP_ZERO, 101 "fpclassify(%a)=%d FP_ZERO=%d", 102 d1, fpclassify(d1), FP_ZERO); 103 f = frexpf(d1, &e); 104 ATF_CHECK_EQ_MSG(e, 0, 105 "frexpf(%a) returned normalized %a, exponent %d;" 106 " expected normalized %a, exponent %d", 107 d1, f, e, 0., 0); 108 ATF_CHECK_EQ_MSG(f, 0, 109 "frexpf(%a) returned normalized %a, exponent %d;" 110 " expected normalized %a, exponent %d", 111 d1, f, e, 0., 0); 112} 113 114ATF_TC(fpclassify_double); 115ATF_TC_HEAD(fpclassify_double, tc) 116{ 117 118 atf_tc_set_md_var(tc, "descr", "Test double operations"); 119} 120 121ATF_TC_BODY(fpclassify_double, tc) 122{ 123 double d0, d1, d2, f, ip; 124 int e, i; 125 126 d0 = DBL_MIN; 127 ATF_CHECK_EQ_MSG(fpclassify(d0), FP_NORMAL, 128 "fpclassify(%a)=%d FP_NORMAL=%d", 129 d0, fpclassify(d0), FP_NORMAL); 130 f = frexp(d0, &e); 131 ATF_CHECK_EQ_MSG(e, DBL_MIN_EXP, 132 "frexp(%a) returned normalized %a, exponent %d;" 133 " expected normalized %a, exponent %d", 134 d0, f, e, 0.5, DBL_MIN_EXP); 135 ATF_CHECK_EQ_MSG(f, 0.5, 136 "frexp(%a) returned normalized %a, exponent %d;" 137 " expected normalized %a, exponent %d", 138 d0, f, e, 0.5, DBL_MIN_EXP); 139 d1 = d0; 140 141#ifdef __DBL_HAS_DENORM__ 142 /* shift a "1" bit through the mantissa (skip the implicit bit) */ 143 for (i = 1; i < DBL_MANT_DIG; i++) { 144 d1 /= 2; 145 ATF_CHECK_EQ_MSG(fpclassify(d1), FP_SUBNORMAL, 146 "[%d] fpclassify(%a)=%d FP_SUBNORMAL=%d", 147 i, d1, fpclassify(d1), FP_SUBNORMAL); 148 ATF_CHECK_MSG(d1 > 0 && d1 < d0, 149 "[%d] d1=%a d0=%a", i, d1, d0); 150 151 d2 = ldexp(d0, -i); 152 ATF_CHECK_EQ_MSG(d2, d1, "[%d] ldexp(%a, -%d)=%a != %a", 153 i, d0, i, d2, d1); 154 155 d2 = modf(d1, &ip); 156 ATF_CHECK_EQ_MSG(d2, d1, 157 "[%d] modf(%a) returned int %a, frac %a;" 158 " expected int %a, frac %a", 159 i, d1, ip, d2, 0., d1); 160 ATF_CHECK_EQ_MSG(ip, 0, 161 "[%d] modf(%a) returned int %a, frac %a;" 162 " expected int %a, frac %a", 163 i, d1, ip, d2, 0., d1); 164 165 f = frexp(d1, &e); 166 ATF_CHECK_EQ_MSG(e, DBL_MIN_EXP - i, 167 "[%d] frexp(%a) returned normalized %a, exponent %d;" 168 " expected normalized %a, exponent %d", 169 i, d1, f, e, 0.5, DBL_MIN_EXP - i); 170 ATF_CHECK_EQ_MSG(f, 0.5, 171 "[%d] frexp(%a) returned normalized %a, exponent %d;" 172 " expected normalized %a, exponent %d", 173 i, d1, f, e, 0.5, DBL_MIN_EXP - i); 174 } 175#endif 176 177 d1 /= 2; 178 ATF_CHECK_EQ_MSG(fpclassify(d1), FP_ZERO, 179 "fpclassify(%a)=%d FP_ZERO=%d", 180 d1, fpclassify(d1), FP_ZERO); 181 f = frexp(d1, &e); 182 ATF_CHECK_EQ_MSG(e, 0, 183 "frexp(%a) returned normalized %a, exponent %d;" 184 " expected normalized %a, exponent %d", 185 d1, f, e, 0., 0); 186 ATF_CHECK_EQ_MSG(f, 0, 187 "frexp(%a) returned normalized %a, exponent %d;" 188 " expected normalized %a, exponent %d", 189 d1, f, e, 0., 0); 190} 191 192ATF_TC(fpclassify_long_double); 193ATF_TC_HEAD(fpclassify_long_double, tc) 194{ 195 196 atf_tc_set_md_var(tc, "descr", "Test long double operations"); 197} 198 199ATF_TC_BODY(fpclassify_long_double, tc) 200{ 201 long double d0, d1, d2, f, ip; 202 int e, i; 203 204 d0 = LDBL_MIN; 205 ATF_CHECK_EQ_MSG(fpclassify(d0), FP_NORMAL, 206 "fpclassify(%La)=%d FP_NORMAL=%d", 207 d0, fpclassify(d0), FP_NORMAL); 208 f = frexpl(d0, &e); 209 ATF_CHECK_EQ_MSG(e, LDBL_MIN_EXP, 210 "frexpl(%La) returned normalized %La, exponent %d;" 211 " expected normalized %La, exponent %d", 212 d0, f, e, 0.5L, LDBL_MIN_EXP); 213 ATF_CHECK_EQ_MSG(f, 0.5, 214 "frexpl(%La) returned normalized %La, exponent %d;" 215 " expected normalized %La, exponent %d", 216 d0, f, e, 0.5L, LDBL_MIN_EXP); 217 d1 = d0; 218 219#ifdef __LDBL_HAS_DENORM__ 220 /* shift a "1" bit through the mantissa (skip the implicit bit) */ 221 for (i = 1; i < LDBL_MANT_DIG; i++) { 222 d1 /= 2; 223 ATF_CHECK_EQ_MSG(fpclassify(d1), FP_SUBNORMAL, 224 "[%d] fpclassify(%La)=%d FP_SUBNORMAL=%d", 225 i, d1, fpclassify(d1), FP_SUBNORMAL); 226 ATF_CHECK_MSG(d1 > 0 && d1 < d0, 227 "[%d] d1=%La d0=%La", i, d1, d0); 228 229 d2 = ldexpl(d0, -i); 230 ATF_CHECK_EQ_MSG(d2, d1, "[%d] ldexpl(%La, -%d)=%La != %La", 231 i, d0, i, d2, d1); 232 233 d2 = modfl(d1, &ip); 234 ATF_CHECK_EQ_MSG(d2, d1, 235 "[%d] modfl(%La) returned int %La, frac %La;" 236 " expected int %La, frac %La", 237 i, d1, ip, d2, 0.L, d1); 238 ATF_CHECK_EQ_MSG(ip, 0, 239 "[%d] modfl(%La) returned int %La, frac %La;" 240 " expected int %La, frac %La", 241 i, d1, ip, d2, 0.L, d1); 242 243 f = frexpl(d1, &e); 244 ATF_CHECK_EQ_MSG(e, LDBL_MIN_EXP - i, 245 "[%d] frexpl(%La) returned normalized %La, exponent %d;" 246 " expected normalized %La, exponent %d", 247 i, d1, f, e, 0.5L, LDBL_MIN_EXP - i); 248 ATF_CHECK_EQ_MSG(f, 0.5, 249 "[%d] frexpl(%La) returned normalized %La, exponent %d;" 250 " expected normalized %La, exponent %d", 251 i, d1, f, e, 0.5L, LDBL_MIN_EXP - i); 252 } 253#endif 254 255 d1 /= 2; 256 ATF_CHECK_EQ_MSG(fpclassify(d1), FP_ZERO, 257 "fpclassify(%La)=%d FP_ZERO=%d", 258 d1, fpclassify(d1), FP_ZERO); 259 f = frexpl(d1, &e); 260 ATF_CHECK_EQ_MSG(e, 0, 261 "frexpl(%La) returned normalized %La, exponent %d;" 262 " expected normalized %La, exponent %d", 263 d1, f, e, 0.L, 0); 264 ATF_CHECK_EQ_MSG(f, 0, 265 "frexpl(%La) returned normalized %La, exponent %d;" 266 " expected normalized %La, exponent %d", 267 d1, f, e, 0.L, 0); 268} 269 270ATF_TP_ADD_TCS(tp) 271{ 272 273 ATF_TP_ADD_TC(tp, fpclassify_float); 274 ATF_TP_ADD_TC(tp, fpclassify_double); 275 ATF_TP_ADD_TC(tp, fpclassify_long_double); 276 277 return atf_no_error(); 278} 279