scanfloat_test.c revision 179919
1139749Simp/*- 2158078Smarcel * Copyright (C) 2003, 2005 David Schultz <das@FreeBSD.org> 3158078Smarcel * All rights reserved. 4158078Smarcel * 5119815Smarcel * Redistribution and use in source and binary forms, with or without 6119815Smarcel * modification, are permitted provided that the following conditions 7119815Smarcel * are met: 8119815Smarcel * 1. Redistributions of source code must retain the above copyright 9119815Smarcel * notice, this list of conditions and the following disclaimer. 10119815Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11119815Smarcel * notice, this list of conditions and the following disclaimer in the 12119815Smarcel * documentation and/or other materials provided with the distribution. 13119815Smarcel * 14119815Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15119815Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16119815Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17119815Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18119815Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19119815Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20119815Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21119815Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22119815Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23119815Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24119815Smarcel * SUCH DAMAGE. 25119815Smarcel */ 26119815Smarcel 27119815Smarcel/* 28119815Smarcel * Test for scanf() floating point formats. 29119815Smarcel */ 30119815Smarcel 31119815Smarcel#include <sys/cdefs.h> 32119815Smarcel__FBSDID("$FreeBSD: head/tools/regression/lib/libc/stdio/test-scanfloat.c 179919 2008-06-21 19:28:26Z das $"); 33119815Smarcel 34119815Smarcel#include <assert.h> 35119815Smarcel#include <fenv.h> 36119815Smarcel#include <float.h> 37119815Smarcel#include <locale.h> 38119815Smarcel#include <math.h> 39119815Smarcel#include <stdio.h> 40119815Smarcel#include <string.h> 41119815Smarcel 42119815Smarcel#define eq(type, a, b) _eq(type##_EPSILON, (a), (b)) 43119815Smarcelstatic int _eq(long double epsilon, long double a, long double b); 44119815Smarcel 45158058Smarcelint 46158058Smarcelmain(int argc, char *argv[]) 47119815Smarcel{ 48119815Smarcel char buf[128]; 49119815Smarcel long double ld = 0.0; 50119815Smarcel double d = 0.0; 51119815Smarcel float f = 0.0; 52119815Smarcel char *endp; 53119815Smarcel 54119815Smarcel printf("1..4\n"); 55119815Smarcel 56119815Smarcel buf[0] = '\0'; 57119815Smarcel assert(setlocale(LC_NUMERIC, "")); 58119815Smarcel 59119815Smarcel /* 60119815Smarcel * Various tests for normalized numbers 61119815Smarcel */ 62119815Smarcel sscanf("3.141592", "%e", &f); 63119815Smarcel assert(eq(FLT, f, 3.141592)); 64158058Smarcel 65158058Smarcel sscanf("3.141592653589793", "%lf", &d); 66158058Smarcel assert(eq(DBL, d, 3.141592653589793)); 67158058Smarcel 68119815Smarcel sscanf("1.234568e+06", "%E", &f); 69119815Smarcel assert(eq(FLT, f, 1.234568e+06)); 70158058Smarcel 71119815Smarcel sscanf("-1.234568e6", "%lF", &d); 72119815Smarcel assert(eq(DBL, d, -1.234568e6)); 73119815Smarcel 74158078Smarcel sscanf("+1.234568e-52", "%LG", &ld); 75158078Smarcel assert(eq(LDBL, ld, 1.234568e-52L)); 76158078Smarcel 77158078Smarcel sscanf("0.1", "%la", &d); 78158058Smarcel assert(eq(DBL, d, 0.1)); 79158058Smarcel 80158078Smarcel sscanf("00.2", "%lA", &d); 81158078Smarcel assert(eq(DBL, d, 0.2)); 82169646Smarcel 83158078Smarcel sscanf("123456", "%5le%s", &d, buf); 84158058Smarcel assert(eq(DBL, d, 12345.)); 85158058Smarcel assert(strcmp(buf, "6") == 0); 86158058Smarcel 87158058Smarcel sscanf("1.0Q", "%*5le%s", buf); 88158058Smarcel assert(strcmp(buf, "Q") == 0); 89158058Smarcel 90158058Smarcel sscanf("-1.23e", "%e%s", &f, buf); 91158058Smarcel assert(eq(FLT, f, -1.23)); 92158058Smarcel assert(strcmp(buf, "e") == 0); 93158058Smarcel 94158058Smarcel sscanf("1.25e+", "%le%s", &d, buf); 95158078Smarcel assert(eq(DBL, d, 1.25)); 96158078Smarcel assert(strcmp(buf, "e+") == 0); 97158058Smarcel 98158058Smarcel sscanf("1.23E4E5", "%le%s", &d, buf); 99188472Skaiw assert(eq(DBL, d, 1.23e4)); 100158078Smarcel assert(strcmp(buf, "E5") == 0); 101158078Smarcel 102158078Smarcel sscanf("12e6", "%le", &d); 103158078Smarcel assert(eq(DBL, d, 12e6)); 104158078Smarcel 105158078Smarcel sscanf("1.a", "%le%s", &d, buf); 106158078Smarcel assert(eq(DBL, d, 1.0)); 107158078Smarcel assert(strcmp(buf, "a") == 0); 108158078Smarcel 109158078Smarcel sscanf(".0p4", "%le%s", &d, buf); 110158078Smarcel assert(eq(DBL, d, 0.0)); 111158078Smarcel assert(strcmp(buf, "p4") == 0); 112158078Smarcel 113158058Smarcel d = 0.25; 114158058Smarcel assert(sscanf(".", "%le", &d) == 0); 115119815Smarcel assert(d == 0.25); 116119815Smarcel 117119815Smarcel sscanf("0x08", "%le", &d); 118158058Smarcel assert(d == 0x8p0); 119119815Smarcel 120158058Smarcel sscanf("0x90a.bcdefP+09a", "%le%s", &d, buf); 121119815Smarcel assert(d == 0x90a.bcdefp+09); 122158058Smarcel assert(strcmp(buf, "a") == 0); 123158058Smarcel 124158058Smarcel#if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__) 125158058Smarcel sscanf("3.14159265358979323846", "%Lg", &ld); 126119815Smarcel assert(eq(LDBL, ld, 3.14159265358979323846L)); 127158058Smarcel 128158058Smarcel sscanf(" 0X.0123456789abcdefffp-3g", "%Le%s", &ld, buf); 129158058Smarcel assert(ld == 0x0.0123456789abcdefffp-3L); 130158058Smarcel assert(strcmp(buf, "g") == 0); 131158058Smarcel#endif 132158058Smarcel 133158058Smarcel sscanf("0xg", "%le%s", &d, buf); 134158058Smarcel assert(d == 0.0); 135158058Smarcel assert(strcmp(buf, "xg") == 0); 136158058Smarcel 137119815Smarcel assert(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */ 138119815Smarcel 139119815Smarcel sscanf("1.23", "%le%s", &d, buf); 140119815Smarcel assert(d == 1.0); 141119815Smarcel assert(strcmp(buf, ".23") == 0); 142119815Smarcel 143119815Smarcel sscanf("1,23", "%le", &d); 144119815Smarcel assert(d == 1.23); 145119815Smarcel 146119815Smarcel assert(setlocale(LC_NUMERIC, "")); 147158058Smarcel 148119815Smarcel printf("ok 1 - scanfloat\n"); 149119815Smarcel 150119815Smarcel /* 151119815Smarcel * Infinity and NaN tests 152119815Smarcel */ 153119815Smarcel sscanf("-Inf", "%le", &d); 154119815Smarcel assert(d < 0.0 && isinf(d)); 155119815Smarcel 156119815Smarcel sscanf("iNfInItY and beyond", "%le%s", &d, buf); 157119815Smarcel assert(d > 0.0 && isinf(d)); 158158058Smarcel assert(strcmp(buf, " and beyond")); 159119815Smarcel 160119815Smarcel sscanf("NaN", "%le", &d); 161119815Smarcel assert(isnan(d)); 162123019Simp 163 sscanf("NAN(123Y", "%le%s", &d, buf); 164 assert(isnan(d)); 165 assert(strcmp(buf, "(123Y") == 0); 166 167 sscanf("nan(f00f)plugh", "%le%s", &d, buf); 168 assert(isnan(d)); 169 assert(strcmp(buf, "plugh") == 0); 170 171 sscanf("-nan", "%le", &d); 172 assert(isnan(d)); 173 174 /* Only quiet NaNs should be returned. */ 175 sscanf("NaN", "%e", &f); 176 sscanf("nan", "%le", &d); 177 sscanf("nan", "%Le", &ld); 178 feclearexcept(FE_ALL_EXCEPT); 179 assert(f != f); 180 assert(d != d); 181 assert(ld != ld); 182 assert(fetestexcept(FE_INVALID) == 0); 183 sscanf("nan(1234)", "%e", &f); 184 sscanf("nan(1234)", "%le", &d); 185 sscanf("nan(1234)", "%Le", &ld); 186 feclearexcept(FE_ALL_EXCEPT); 187 assert(f != f); 188 assert(d != d); 189 assert(ld != ld); 190#if 0 191 /* 192 * POSIX says we should only generate quiet NaNs, but the gdtoa 193 * author convincingly argues that if you ask for a NaN format 194 * based on some implementation-defined string, you should get 195 * what you asked for, even if it's a signaling NaN. 196 */ 197 assert(fetestexcept(FE_INVALID) == 0); 198#endif 199 200 printf("ok 2 - scanfloat\n"); 201 202 /* 203 * Rounding tests 204 */ 205 206 fesetround(FE_DOWNWARD); 207 208 sscanf("1.999999999999999999999999999999999", "%le", &d); 209 assert(d < 2.0); 210 sscanf("0x1.ffffffffffffffp0", "%le", &d); 211 assert(d < 2.0); 212 sscanf("1.999999999999999999999999999999999", "%Le", &ld); 213 assert(ld < 2.0); 214 215 sscanf("1.0571892669084007", "%le", &d); 216 assert(d == 0x1.0ea3f4af0dc59p0); 217 sscanf("-1.0571892669084007", "%le", &d); 218 assert(d == -0x1.0ea3f4af0dc5ap0); 219 sscanf("1.0571892669084010", "%le", &d); 220 assert(d == 0x1.0ea3f4af0dc5ap0); 221 222 sscanf("0x1.23p-5000", "%le", &d); 223 assert(d == 0.0); 224 225 sscanf("0x1.2345678p-1050", "%le", &d); 226 assert(d == 0x1.234567p-1050); 227 228 fesetround(FE_UPWARD); 229 230 sscanf("1.0571892669084007", "%le", &d); 231 assert(d == 0x1.0ea3f4af0dc5ap0); 232 sscanf("-1.0571892669084007", "%le", &d); 233 assert(d == -0x1.0ea3f4af0dc59p0); 234 sscanf("1.0571892669084010", "%le", &d); 235 assert(d == 0x1.0ea3f4af0dc5bp0); 236 237 sscanf("0x1.23p-5000", "%le", &d); 238 assert(d == 0x1p-1074); 239 240 sscanf("0x1.2345678p-1050", "%le", &d); 241 assert(d == 0x1.234568p-1050); 242 243 fesetround(FE_TOWARDZERO); 244 245 sscanf("1.0571892669084007", "%le", &d); 246 assert(d == 0x1.0ea3f4af0dc59p0); 247 sscanf("-1.0571892669084007", "%le", &d); 248 assert(d == -0x1.0ea3f4af0dc59p0); 249 sscanf("1.0571892669084010", "%le", &d); 250 assert(d == 0x1.0ea3f4af0dc5ap0); 251 252 sscanf("0x1.23p-5000", "%le", &d); 253 assert(d == 0.0); 254 255 sscanf("0x1.2345678p-1050", "%le", &d); 256 assert(d == 0x1.234567p-1050); 257 258 fesetround(FE_TONEAREST); 259 260 /* 1.0571892669084007 is slightly closer to 0x1.0ea3f4af0dc59p0 */ 261 sscanf("1.0571892669084007", "%le", &d); 262 assert(d == 0x1.0ea3f4af0dc59p0); 263 sscanf("-1.0571892669084007", "%le", &d); 264 assert(d == -0x1.0ea3f4af0dc59p0); 265 sscanf("1.0571892669084010", "%le", &d); 266 assert(d == 0x1.0ea3f4af0dc5bp0); 267 268 /* strtod() should round small numbers to 0. */ 269 sscanf("0x1.23p-5000", "%le", &d); 270 assert(d == 0.0); 271 272 /* Extra digits in a denormal shouldn't break anything. */ 273 sscanf("0x1.2345678p-1050", "%le", &d); 274 assert(d == 0x1.234568p-1050); 275 276 printf("ok 3 - scanfloat\n"); 277 278 /* 279 * Tests specific to strtod(). 280 */ 281 282 assert(strtod("0xy", &endp) == 0); 283 assert(strcmp("xy", endp) == 0); 284 285 printf("ok 4 - scanfloat\n"); 286 287 return (0); 288} 289 290static int 291_eq(long double epsilon, long double a, long double b) 292{ 293 long double delta; 294 295 delta = a - b; 296 if (delta < 0) /* XXX no fabsl() */ 297 delta = -delta; 298 return (delta <= epsilon); 299} 300