1/* 2 * 3 * Copyright (c) International Business Machines Corp., 2002 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20/* 01/02/2003 Port to LTP avenkat@us.ibm.com */ 21/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */ 22 23/* 24 * NAME 25 * atof1 -- ascii to floating point test 26 * 27 * CALLS 28 * atof(3), sprintf(3), ( doprnt.s ) 29 * 30 * ALGORITHM 31 * Do some checks of floating point to ascii and back, arbitrate 32 * with a 3rd algorithm written in C. 33 * 34 * RESTRICTIONS 35 */ 36 37#include <stdio.h> 38#include <ctype.h> 39#include <math.h> 40#include <stdlib.h> 41#include <errno.h> 42 43/** LTP Port **/ 44#include "test.h" 45 46#define FAILED 0 47#define PASSED 1 48 49/***** *****/ 50#define ERR 0.0000001 51 52double pi; 53 54/*char progname[]= "atof1()"; */ 55/** LTP Port **/ 56char *TCID = "atof01"; /* Test program identifier */ 57 58int local_flag = PASSED; 59int block_number; 60FILE *temp; 61int TST_TOTAL = 1; 62 63static void setup(void); 64static void blenter(void); 65static void blexit(void); 66static int numin(char *, double *); 67static int checkbuf(char *, int, int); 68 69/*--------------------------------------------------------------*/ 70int main(int argc, char *argv[]) 71{ 72 register int i, j; 73 double r1, r2, x; 74 char buf[100]; 75 76 setup(); /* temp file is now open */ 77 pi = 4.0 * atan(1.0); 78 79/*--------------------------------------------------------------*/ 80 blenter(); 81 82 for (i = 0; i < 30; i++) 83 for (j = 0; j < 30; j++) { 84 sprintf(buf, "%*.*f", i, j, pi); 85 if (checkbuf(buf, i, j)) { 86 fprintf(temp, "output conversion incorrect."); 87 fprintf(temp, "%*.*f = '%s'", i, j, pi, buf); 88 local_flag = FAILED; 89 } 90 r1 = atof(buf); 91 if (numin(buf, &r2)) { 92 fprintf(temp, "\tnumin('%s') failed\n", buf); 93 local_flag = FAILED; 94 } 95 x = fabs(r1 - r2); 96 if (x > ERR) { 97 fprintf(temp, "\tcompare fails, %f vs %f\n", 98 r1, r2); 99 fprintf(temp, "\terr value is %f\n", x); 100 local_flag = FAILED; 101 } 102 if (local_flag == FAILED) 103 break; 104 } 105 106 blexit(); 107/*--------------------------------------------------------------*/ 108 blenter(); 109 110 x = 1.0 - exp(-100.0); /* 1.0 - very small number */ 111 sprintf(buf, "%f", x); 112 r1 = atof(buf); 113 if (r1 != 1.0) { 114 fprintf(temp, "\tsprintf small # failed\n"); 115 fprintf(temp, "\t printed '%s', expected 1.0\n", buf); 116 local_flag = FAILED; 117 } 118 119 blexit(); 120/*--------------------------------------------------------------*/ 121 blenter(); 122 123 for (i = 1; i < 200; i++) { 124 x = 100.0 / (double)i; 125 sprintf(buf, "%f", x); 126 r1 = atof(buf); 127 if (numin(buf, &r2)) { 128 fprintf(temp, "\tnumin('%s') failed\n", buf); 129 local_flag = FAILED; 130 } 131 /* 132 * Order subtraction to produce a positive number. 133 * Then subtrace "fudge" factor which should give us 134 * a negative number, as the result fo subtraction should 135 * always be smaller than the fudge factor. 136 */ 137 if (r1 > r2) 138 x = r1 - r2 - 1e-10; 139 else 140 x = r2 - r1 - 1e-10; 141 if (x > 0.0) { 142 fprintf(temp, "\tx = %.15f = %e\n", x, x); 143 fprintf(temp, "\titeration %d\n", i); 144 fprintf(temp, "\tcompare fails, %f vs %f\n", r1, r2); 145 fprintf(temp, "\tcompare fails, %.15f vs %.15f\n", 146 r1, r2); 147 fprintf(temp, "\tbuf = '%s'\n", buf); 148 x = r1 - r2; 149 if (x == 0.0) 150 fprintf(temp, "\tx == 0.0\n"); 151 else 152 fprintf(temp, "\tx != 0.0\n"); 153 fprintf(temp, "\tx = %.15f = %e\n", x, x); 154 local_flag = FAILED; 155 } 156 if (local_flag == FAILED) 157 break; 158 } 159 160 blexit(); 161/*--------------------------------------------------------------*/ 162 blenter(); 163 164 for (i = -1; i > -200; i--) { 165 x = 100.0 / (double)i; 166 sprintf(buf, "%f", x); 167 r1 = atof(buf); 168 if (numin(buf, &r2)) { 169 fprintf(temp, "\tnumin('%s') failed\n", buf); 170 local_flag = FAILED; 171 } 172 /* 173 * Same ordering of subtraction as above. 174 */ 175 if (r1 > r2) 176 x = r1 - r2 - 1e-10; 177 else 178 x = r2 - r1 - 1e-10; 179 if (x > 0.0) { 180 fprintf(temp, "\tcompare fails, %f vs %f\n", r1, r2); 181 fprintf(temp, "\tcompare fails, %.15f vs %.15f\n", 182 r1, r2); 183 x = r1 - r2; 184 if (x == 0.0) 185 fprintf(temp, "\tx == 0.0)\n"); 186 else 187 fprintf(temp, "\tx != 0.0\n"); 188 fprintf(temp, "\tx = %.15f = %e\n", x, x); 189 local_flag = FAILED; 190 } 191 if (local_flag == FAILED) 192 break; 193 } 194 195 blexit(); 196/*--------------------------------------------------------------*/ 197 tst_exit(); 198} 199 200/* FUNCTIONS GO HERE */ 201 202static int numin(char *str, double *rval) 203{ 204 register int i, v3, e_flag; 205 register char c; 206 double val, v1, v2, k; 207 int neg_flag = 0; 208 209 val = v1 = v2 = 0.0; 210 v3 = 0; 211 k = 0.1; 212 213 while (*str == ' ') /* scan past white space */ 214 str++; 215 216 if (*str == '-') { /* negitive value test */ 217 neg_flag++; 218 str++; 219 } 220 221 for (;;) { 222 c = *str; 223 if (!isdigit(c)) 224 break; 225 v1 *= 10.0; 226 v1 += (double)(c - '0'); 227 str++; 228 } 229 230 val = v1; 231 232#ifdef DEBUG 233 printf("First conversion, val = %f = %e\n", val, val); 234#endif 235 236 if (*str == '.') { 237 str++; 238 for (;;) { 239 c = *str; 240 if (!isdigit(c)) 241 break; 242 v2 += k * (double)(c - '0'); 243 k /= 10.0; 244 str++; 245 } 246 val += v2; 247 } 248#ifdef DEBUG 249 printf("Second conversion, val = %f = %e\n", val, val); 250#endif 251 252 if (*str == 'e') { 253 str++; 254 switch (*str) { 255 case '+': 256 e_flag = 1; 257 break; 258 case '-': 259 e_flag = -1; 260 break; 261 default: 262 fprintf(temp, "\tbad char '%c' after 'e'\n", *str); 263 printf("bad char '%c' after 'e'\n", *str); 264 return (-1); 265 } 266 str++; 267 if (!isdigit(*str)) { 268 fprintf(temp, "\tbad exponent field\n"); 269 printf("bad exponent field\n"); 270 return (-1); 271 } 272 v3 = 10 * (int)(*str - '0'); 273 str++; 274 if (!isdigit(*str)) { 275 fprintf(temp, "\tbad exponent field\n"); 276 printf("bad exponent field\n"); 277 return (-1); 278 } 279 v3 += (int)(*str - '0'); 280 str++; 281 for (i = 0; i < v3; i++) { 282 if (e_flag > 0) 283 val *= 10.0; 284 else 285 val *= 0.1; 286 } 287 } 288 289 if (neg_flag) 290 val *= -1.0; 291 292#ifdef DEBUG 293 printf("Third conversion, val = %f = %e\n", val, val); 294 printf("v1 = %f, v2 = %f, v3 = %d\n", v1, v2, v3); 295#endif 296 297 switch (*str) { 298 case '\0': 299 case ' ': 300 case '\t': 301 case '\n': 302 break; 303 default: 304 printf("unexpected char '%c'\n", *str); 305 return (-1); 306 } 307 308 *rval = val; 309 return (0); 310} 311 312static int checkbuf(char *str, int n1, int n2) 313{ 314 register int bd; /* before decimal point */ 315 register int ad; /* after decimal point */ 316 register int tw; /* total width */ 317 register int dp; /* decimal point */ 318 char *buf; 319 320 bd = ad = dp = 0; 321 buf = str; 322 323 while (*str && *str != '.') { 324 bd++; 325 str++; 326 } 327 if (*str == '.') { 328 dp++; 329 str++; 330 if (*str) { 331 while (*str) { 332 ad++; 333 str++; 334 } 335 } 336 } 337 338 tw = bd + dp + ad; 339 if (!n1) 340 n1++; 341 if (tw < n1) { 342 fprintf(temp, "\tWidth too small.\n"); 343 fprintf(temp, "\tn1 = %d, n2 = %d, buf= '%s'\n", n1, n2, buf); 344 return (-1); 345 } 346 347 if (ad != n2) { 348 fprintf(temp, "\tNumber after decimal wrong.\n"); 349 fprintf(temp, "\tn1 = %d, n2 = %d, buf= '%s'\n", n1, n2, buf); 350 return (-1); 351 } 352 353 if (n2 && !dp) { 354 fprintf(temp, "\tMissed decimal point.\n"); 355 fprintf(temp, "\tn1 = %d, n2 = %d, buf= '%s'\n", n1, n2, buf); 356 return (-1); 357 } 358 359 return (0); 360} 361 362/** LTP Port **/ 363static void setup(void) 364{ 365 temp = stderr; 366} 367 368static void blenter(void) 369{ 370 local_flag = PASSED; 371} 372 373static void blexit(void) 374{ 375 if (local_flag == PASSED) 376 tst_resm(TPASS, "Test passed"); 377 else 378 tst_resm(TFAIL, "Test failed"); 379} 380