1/*- 2 * Copyright (C) 2003, 2005 David Schultz <das@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27/* 28 * Test for scanf() floating point formats. 29 */ 30 31#include <sys/cdefs.h> 32__FBSDID("$FreeBSD$"); 33 34#include <assert.h> 35#include <fenv.h> 36#include <float.h> 37#include <locale.h> 38#include <math.h> 39#include <stdio.h> 40#include <stdlib.h> 41#include <string.h> 42 43#define eq(type, a, b) _eq(type##_EPSILON, (a), (b)) 44static int _eq(long double epsilon, long double a, long double b); 45 46int 47main(int argc, char *argv[]) 48{ 49 char buf[128]; 50 long double ld = 0.0; 51 double d = 0.0; 52 float f = 0.0; 53 char *endp; 54 55 printf("1..4\n"); 56 57 buf[0] = '\0'; 58 assert(setlocale(LC_NUMERIC, "")); 59 60 /* 61 * Various tests for normalized numbers 62 */ 63 sscanf("3.141592", "%e", &f); 64 assert(eq(FLT, f, 3.141592)); 65 66 sscanf("3.141592653589793", "%lf", &d); 67 assert(eq(DBL, d, 3.141592653589793)); 68 69 sscanf("1.234568e+06", "%E", &f); 70 assert(eq(FLT, f, 1.234568e+06)); 71 72 sscanf("-1.234568e6", "%lF", &d); 73 assert(eq(DBL, d, -1.234568e6)); 74 75 sscanf("+1.234568e-52", "%LG", &ld); 76 assert(eq(LDBL, ld, 1.234568e-52L)); 77 78 sscanf("0.1", "%la", &d); 79 assert(eq(DBL, d, 0.1)); 80 81 sscanf("00.2", "%lA", &d); 82 assert(eq(DBL, d, 0.2)); 83 84 sscanf("123456", "%5le%s", &d, buf); 85 assert(eq(DBL, d, 12345.)); 86 assert(strcmp(buf, "6") == 0); 87 88 sscanf("1.0Q", "%*5le%s", buf); 89 assert(strcmp(buf, "Q") == 0); 90 91 sscanf("-1.23e", "%e%s", &f, buf); 92 assert(eq(FLT, f, -1.23)); 93 assert(strcmp(buf, "e") == 0); 94 95 sscanf("1.25e+", "%le%s", &d, buf); 96 assert(eq(DBL, d, 1.25)); 97 assert(strcmp(buf, "e+") == 0); 98 99 sscanf("1.23E4E5", "%le%s", &d, buf); 100 assert(eq(DBL, d, 1.23e4)); 101 assert(strcmp(buf, "E5") == 0); 102 103 sscanf("12e6", "%le", &d); 104 assert(eq(DBL, d, 12e6)); 105 106 sscanf("1.a", "%le%s", &d, buf); 107 assert(eq(DBL, d, 1.0)); 108 assert(strcmp(buf, "a") == 0); 109 110 sscanf(".0p4", "%le%s", &d, buf); 111 assert(eq(DBL, d, 0.0)); 112 assert(strcmp(buf, "p4") == 0); 113 114 d = 0.25; 115 assert(sscanf(".", "%le", &d) == 0); 116 assert(d == 0.25); 117 118 sscanf("0x08", "%le", &d); 119 assert(d == 0x8p0); 120 121 sscanf("0x90a.bcdefP+09a", "%le%s", &d, buf); 122 assert(d == 0x90a.bcdefp+09); 123 assert(strcmp(buf, "a") == 0); 124 125#if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__) 126 sscanf("3.14159265358979323846", "%Lg", &ld); 127 assert(eq(LDBL, ld, 3.14159265358979323846L)); 128 129 sscanf(" 0X.0123456789abcdefffp-3g", "%Le%s", &ld, buf); 130 assert(ld == 0x0.0123456789abcdefffp-3L); 131 assert(strcmp(buf, "g") == 0); 132#endif 133 134 sscanf("0xg", "%le%s", &d, buf); 135 assert(d == 0.0); 136 assert(strcmp(buf, "xg") == 0); 137 138 assert(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */ 139 140 sscanf("1.23", "%le%s", &d, buf); 141 assert(d == 1.0); 142 assert(strcmp(buf, ".23") == 0); 143 144 sscanf("1,23", "%le", &d); 145 assert(d == 1.23); 146 147 assert(setlocale(LC_NUMERIC, "")); 148 149 printf("ok 1 - scanfloat\n"); 150 151 /* 152 * Infinity and NaN tests 153 */ 154 sscanf("-Inf", "%le", &d); 155 assert(d < 0.0 && isinf(d)); 156 157 sscanf("iNfInItY and beyond", "%le%s", &d, buf); 158 assert(d > 0.0 && isinf(d)); 159 assert(strcmp(buf, " and beyond")); 160 161 sscanf("NaN", "%le", &d); 162 assert(isnan(d)); 163 164 sscanf("NAN(123Y", "%le%s", &d, buf); 165 assert(isnan(d)); 166 assert(strcmp(buf, "(123Y") == 0); 167 168 sscanf("nan(f00f)plugh", "%le%s", &d, buf); 169 assert(isnan(d)); 170 assert(strcmp(buf, "plugh") == 0); 171 172 sscanf("-nan", "%le", &d); 173 assert(isnan(d)); 174 175 /* Only quiet NaNs should be returned. */ 176 sscanf("NaN", "%e", &f); 177 sscanf("nan", "%le", &d); 178 sscanf("nan", "%Le", &ld); 179 feclearexcept(FE_ALL_EXCEPT); 180 assert(f != f); 181 assert(d != d); 182 assert(ld != ld); 183 assert(fetestexcept(FE_INVALID) == 0); 184 sscanf("nan(1234)", "%e", &f); 185 sscanf("nan(1234)", "%le", &d); 186 sscanf("nan(1234)", "%Le", &ld); 187 feclearexcept(FE_ALL_EXCEPT); 188 assert(f != f); 189 assert(d != d); 190 assert(ld != ld); 191 /* POSIX says we should only generate quiet NaNs. */ 192 assert(fetestexcept(FE_INVALID) == 0); 193 194 printf("ok 2 - scanfloat\n"); 195 196 /* 197 * Rounding tests 198 */ 199 200 fesetround(FE_DOWNWARD); 201 202 sscanf("1.999999999999999999999999999999999", "%le", &d); 203 assert(d < 2.0); 204 sscanf("0x1.ffffffffffffffp0", "%le", &d); 205 assert(d < 2.0); 206 sscanf("1.999999999999999999999999999999999", "%Le", &ld); 207 assert(ld < 2.0); 208 209 sscanf("1.0571892669084007", "%le", &d); 210 assert(d == 0x1.0ea3f4af0dc59p0); 211 sscanf("-1.0571892669084007", "%le", &d); 212 assert(d == -0x1.0ea3f4af0dc5ap0); 213 sscanf("1.0571892669084010", "%le", &d); 214 assert(d == 0x1.0ea3f4af0dc5ap0); 215 216 sscanf("0x1.23p-5000", "%le", &d); 217 assert(d == 0.0); 218 219 sscanf("0x1.2345678p-1050", "%le", &d); 220 assert(d == 0x1.234567p-1050); 221 222 fesetround(FE_UPWARD); 223 224 sscanf("1.0571892669084007", "%le", &d); 225 assert(d == 0x1.0ea3f4af0dc5ap0); 226 sscanf("-1.0571892669084007", "%le", &d); 227 assert(d == -0x1.0ea3f4af0dc59p0); 228 sscanf("1.0571892669084010", "%le", &d); 229 assert(d == 0x1.0ea3f4af0dc5bp0); 230 231 sscanf("0x1.23p-5000", "%le", &d); 232 assert(d == 0x1p-1074); 233 234 sscanf("0x1.2345678p-1050", "%le", &d); 235 assert(d == 0x1.234568p-1050); 236 237 fesetround(FE_TOWARDZERO); 238 239 sscanf("1.0571892669084007", "%le", &d); 240 assert(d == 0x1.0ea3f4af0dc59p0); 241 sscanf("-1.0571892669084007", "%le", &d); 242 assert(d == -0x1.0ea3f4af0dc59p0); 243 sscanf("1.0571892669084010", "%le", &d); 244 assert(d == 0x1.0ea3f4af0dc5ap0); 245 246 sscanf("0x1.23p-5000", "%le", &d); 247 assert(d == 0.0); 248 249 sscanf("0x1.2345678p-1050", "%le", &d); 250 assert(d == 0x1.234567p-1050); 251 252 fesetround(FE_TONEAREST); 253 254 /* 1.0571892669084007 is slightly closer to 0x1.0ea3f4af0dc59p0 */ 255 sscanf("1.0571892669084007", "%le", &d); 256 assert(d == 0x1.0ea3f4af0dc59p0); 257 sscanf("-1.0571892669084007", "%le", &d); 258 assert(d == -0x1.0ea3f4af0dc59p0); 259 sscanf("1.0571892669084010", "%le", &d); 260 assert(d == 0x1.0ea3f4af0dc5bp0); 261 262 /* strtod() should round small numbers to 0. */ 263 sscanf("0x1.23p-5000", "%le", &d); 264 assert(d == 0.0); 265 266 /* Extra digits in a denormal shouldn't break anything. */ 267 sscanf("0x1.2345678p-1050", "%le", &d); 268 assert(d == 0x1.234568p-1050); 269 270 printf("ok 3 - scanfloat\n"); 271 272 /* 273 * Tests specific to strtod(). 274 */ 275 276 assert(strtod("0xy", &endp) == 0); 277 assert(strcmp("xy", endp) == 0); 278 279 /* This used to cause an infinite loop and round the wrong way. */ 280 fesetround(FE_DOWNWARD); 281 assert(strtof("3.5e38", &endp) == FLT_MAX); 282 assert(strtod("2e308", &endp) == DBL_MAX); 283 fesetround(FE_UPWARD); 284 assert(strtof("3.5e38", &endp) == INFINITY); 285 assert(strtod("2e308", &endp) == INFINITY); 286 fesetround(FE_TOWARDZERO); 287 assert(strtof("3.5e38", &endp) == FLT_MAX); 288 assert(strtod("2e308", &endp) == DBL_MAX); 289 fesetround(FE_TONEAREST); 290 assert(strtof("3.5e38", &endp) == INFINITY); 291 assert(strtod("2e308", &endp) == INFINITY); 292 293 printf("ok 4 - scanfloat\n"); 294 295 return (0); 296} 297 298static int 299_eq(long double epsilon, long double a, long double b) 300{ 301 long double delta; 302 303 delta = fabsl(a - b); 304 return (delta <= epsilon); 305} 306