blob: 70a7a028a002a65d5d9d66cd547d4214c5180e58 [file] [log] [blame]
robbiew2c282cd2003-01-03 23:10:29 +00001/*
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
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
robbiew2c282cd2003-01-03 23:10:29 +000018 */
19
robbiew2c282cd2003-01-03 23:10:29 +000020/* 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
robbiew2c282cd2003-01-03 23:10:29 +000037#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"
robbiew2c282cd2003-01-03 23:10:29 +000045
46#define FAILED 0
47#define PASSED 1
48
49/***** *****/
50#define ERR 0.0000001
51
robbiew2c282cd2003-01-03 23:10:29 +000052double pi;
53
54double atof();
55
56/*char progname[]= "atof1()"; */
57/** LTP Port **/
Wanlong Gao354ebb42012-12-07 10:10:04 +080058char *TCID = "atof01"; /* Test program identifier */
robbiew2c282cd2003-01-03 23:10:29 +000059
60int local_flag = PASSED;
61int block_number;
62int errno;
63FILE *temp;
64int TST_TOTAL = 1;
robbiew2c282cd2003-01-03 23:10:29 +000065
66void setup();
Garrett Cooper4b20b1d2010-12-18 01:06:11 -080067void blenter();
68void blexit();
Wanlong Gao354ebb42012-12-07 10:10:04 +080069int numin(char *, double *);
70int checkbuf(char *, int, int);
robbiew2c282cd2003-01-03 23:10:29 +000071
72/*--------------------------------------------------------------*/
Wanlong Gao354ebb42012-12-07 10:10:04 +080073int main(int argc, char *argv[])
robbiew2c282cd2003-01-03 23:10:29 +000074{
75 register int i, j;
76 double r1, r2, x;
77 char buf[100];
78
Wanlong Gao354ebb42012-12-07 10:10:04 +080079 setup(); /* temp file is now open */
robbiew2c282cd2003-01-03 23:10:29 +000080 pi = 4.0 * atan(1.0);
81
82/*--------------------------------------------------------------*/
83 blenter();
Garrett Cooper2c282152010-12-16 00:55:50 -080084
Wanlong Gao354ebb42012-12-07 10:10:04 +080085 for (i = 0; i < 30; i++)
86 for (j = 0; j < 30; j++) {
robbiew2c282cd2003-01-03 23:10:29 +000087 sprintf(buf, "%*.*f", i, j, pi);
88 if (checkbuf(buf, i, j)) {
89 fprintf(temp, "output conversion incorrect.");
Wanlong Gao354ebb42012-12-07 10:10:04 +080090 fprintf(temp, "%*.*f = '%s'", i, j, pi, buf);
robbiew2c282cd2003-01-03 23:10:29 +000091 local_flag = FAILED;
92 }
93 r1 = atof(buf);
94 if (numin(buf, &r2)) {
95 fprintf(temp, "\tnumin('%s') failed\n", buf);
96 local_flag = FAILED;
97 }
98 x = fabs(r1 - r2);
99 if (x > ERR) {
100 fprintf(temp, "\tcompare fails, %f vs %f\n",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800101 r1, r2);
robbiew2c282cd2003-01-03 23:10:29 +0000102 fprintf(temp, "\terr value is %f\n", x);
103 local_flag = FAILED;
104 }
105 if (local_flag == FAILED)
106 break;
107 }
108
109 blexit();
110/*--------------------------------------------------------------*/
111 blenter();
112
113 x = 1.0 - exp(-100.0); /* 1.0 - very small number */
114 sprintf(buf, "%f", x);
115 r1 = atof(buf);
116 if (r1 != 1.0) {
117 fprintf(temp, "\tsprintf small # failed\n");
118 fprintf(temp, "\t printed '%s', expected 1.0\n", buf);
119 local_flag = FAILED;
120 }
121
122 blexit();
123/*--------------------------------------------------------------*/
124 blenter();
125
Wanlong Gao354ebb42012-12-07 10:10:04 +0800126 for (i = 1; i < 200; i++) {
127 x = 100.0 / (double)i;
robbiew2c282cd2003-01-03 23:10:29 +0000128 sprintf(buf, "%f", x);
129 r1 = atof(buf);
130 if (numin(buf, &r2)) {
131 fprintf(temp, "\tnumin('%s') failed\n", buf);
132 local_flag = FAILED;
133 }
134 /*
135 * Order subtraction to produce a positive number.
136 * Then subtrace "fudge" factor which should give us
137 * a negative number, as the result fo subtraction should
138 * always be smaller than the fudge factor.
139 */
140 if (r1 > r2)
141 x = r1 - r2 - 1e-10;
142 else
143 x = r2 - r1 - 1e-10;
144 if (x > 0.0) {
145 fprintf(temp, "\tx = %.15f = %e\n", x, x);
146 fprintf(temp, "\titeration %d\n", i);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800147 fprintf(temp, "\tcompare fails, %f vs %f\n", r1, r2);
robbiew2c282cd2003-01-03 23:10:29 +0000148 fprintf(temp, "\tcompare fails, %.15f vs %.15f\n",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800149 r1, r2);
robbiew2c282cd2003-01-03 23:10:29 +0000150 fprintf(temp, "\tbuf = '%s'\n", buf);
151 x = r1 - r2;
152 if (x == 0.0)
153 fprintf(temp, "\tx == 0.0\n");
154 else
155 fprintf(temp, "\tx != 0.0\n");
156 fprintf(temp, "\tx = %.15f = %e\n", x, x);
157 local_flag = FAILED;
158 }
159 if (local_flag == FAILED)
160 break;
161 }
162
robbiew2c282cd2003-01-03 23:10:29 +0000163 blexit();
164/*--------------------------------------------------------------*/
165 blenter();
166
Wanlong Gao354ebb42012-12-07 10:10:04 +0800167 for (i = -1; i > -200; i--) {
168 x = 100.0 / (double)i;
robbiew2c282cd2003-01-03 23:10:29 +0000169 sprintf(buf, "%f", x);
170 r1 = atof(buf);
171 if (numin(buf, &r2)) {
172 fprintf(temp, "\tnumin('%s') failed\n", buf);
173 local_flag = FAILED;
174 }
175 /*
176 * Same ordering of subtraction as above.
177 */
178 if (r1 > r2)
179 x = r1 - r2 - 1e-10;
180 else
181 x = r2 - r1 - 1e-10;
182 if (x > 0.0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800183 fprintf(temp, "\tcompare fails, %f vs %f\n", r1, r2);
robbiew2c282cd2003-01-03 23:10:29 +0000184 fprintf(temp, "\tcompare fails, %.15f vs %.15f\n",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800185 r1, r2);
robbiew2c282cd2003-01-03 23:10:29 +0000186 x = r1 - r2;
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800187 if (x == 0.0)
robbiew2c282cd2003-01-03 23:10:29 +0000188 fprintf(temp, "\tx == 0.0)\n");
189 else
190 fprintf(temp, "\tx != 0.0\n");
191 fprintf(temp, "\tx = %.15f = %e\n", x, x);
192 local_flag = FAILED;
193 }
194 if (local_flag == FAILED)
195 break;
196 }
197
robbiew2c282cd2003-01-03 23:10:29 +0000198 blexit();
199/*--------------------------------------------------------------*/
Garrett Cooper4b20b1d2010-12-18 01:06:11 -0800200 tst_exit();
robbiew2c282cd2003-01-03 23:10:29 +0000201}
Wanlong Gao354ebb42012-12-07 10:10:04 +0800202
robbiew2c282cd2003-01-03 23:10:29 +0000203/* FUNCTIONS GO HERE */
204
Wanlong Gao354ebb42012-12-07 10:10:04 +0800205int numin(str, rval)
206char *str;
207double *rval;
robbiew2c282cd2003-01-03 23:10:29 +0000208{
209 register int i, v3, e_flag;
210 register char c;
211 double val, v1, v2, k;
212 int neg_flag = 0;
213
214 val = v1 = v2 = 0.0;
215 v3 = 0;
216 k = 0.1;
217
218 while (*str == ' ') /* scan past white space */
219 str++;
220
221 if (*str == '-') { /* negitive value test */
222 neg_flag++;
223 str++;
224 }
225
226 for (;;) {
227 c = *str;
228 if (!isdigit(c))
229 break;
230 v1 *= 10.0;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800231 v1 += (double)(c - '0');
robbiew2c282cd2003-01-03 23:10:29 +0000232 str++;
233 }
234
235 val = v1;
236
237#ifdef DEBUG
238 printf("First conversion, val = %f = %e\n", val, val);
239#endif
240
241 if (*str == '.') {
242 str++;
243 for (;;) {
244 c = *str;
245 if (!isdigit(c))
246 break;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800247 v2 += k * (double)(c - '0');
robbiew2c282cd2003-01-03 23:10:29 +0000248 k /= 10.0;
249 str++;
250 }
251 val += v2;
252 }
robbiew2c282cd2003-01-03 23:10:29 +0000253#ifdef DEBUG
254 printf("Second conversion, val = %f = %e\n", val, val);
255#endif
256
257 if (*str == 'e') {
258 str++;
259 switch (*str) {
260 case '+':
261 e_flag = 1;
262 break;
263 case '-':
264 e_flag = -1;
265 break;
266 default:
267 fprintf(temp, "\tbad char '%c' after 'e'\n", *str);
268 printf("bad char '%c' after 'e'\n", *str);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800269 return (-1);
robbiew2c282cd2003-01-03 23:10:29 +0000270 }
271 str++;
272 if (!isdigit(*str)) {
273 fprintf(temp, "\tbad exponent field\n");
274 printf("bad exponent field\n");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800275 return (-1);
robbiew2c282cd2003-01-03 23:10:29 +0000276 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800277 v3 = 10 * (int)(*str - '0');
robbiew2c282cd2003-01-03 23:10:29 +0000278 str++;
279 if (!isdigit(*str)) {
280 fprintf(temp, "\tbad exponent field\n");
281 printf("bad exponent field\n");
Wanlong Gao354ebb42012-12-07 10:10:04 +0800282 return (-1);
robbiew2c282cd2003-01-03 23:10:29 +0000283 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800284 v3 += (int)(*str - '0');
robbiew2c282cd2003-01-03 23:10:29 +0000285 str++;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800286 for (i = 0; i < v3; i++) {
robbiew2c282cd2003-01-03 23:10:29 +0000287 if (e_flag > 0)
288 val *= 10.0;
289 else
290 val *= 0.1;
291 }
292 }
293
294 if (neg_flag)
295 val *= -1.0;
296
297#ifdef DEBUG
298 printf("Third conversion, val = %f = %e\n", val, val);
299 printf("v1 = %f, v2 = %f, v3 = %d\n", v1, v2, v3);
300#endif
301
302 switch (*str) {
303 case '\0':
304 case ' ':
305 case '\t':
306 case '\n':
307 break;
308 default:
309 printf("unexpected char '%c'\n", *str);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800310 return (-1);
robbiew2c282cd2003-01-03 23:10:29 +0000311 }
312
313 *rval = val;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800314 return (0);
robbiew2c282cd2003-01-03 23:10:29 +0000315}
316
317int checkbuf(str, n1, n2)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800318char *str;
319int n1;
320int n2;
robbiew2c282cd2003-01-03 23:10:29 +0000321{
322 register int bd; /* before decimal point */
323 register int ad; /* after decimal point */
324 register int tw; /* total width */
325 register int dp; /* decimal point */
326 char *buf;
327
328 bd = ad = dp = 0;
329 buf = str;
330
331 while (*str && *str != '.') {
332 bd++;
333 str++;
334 }
335 if (*str == '.') {
336 dp++;
337 str++;
338 if (*str) {
339 while (*str) {
340 ad++;
341 str++;
342 }
343 }
344 }
345
346 tw = bd + dp + ad;
347 if (!n1)
348 n1++;
349 if (tw < n1) {
350 fprintf(temp, "\tWidth too small.\n");
351 fprintf(temp, "\tn1 = %d, n2 = %d, buf= '%s'\n", n1, n2, buf);
352 return (-1);
353 }
354
355 if (ad != n2) {
356 fprintf(temp, "\tNumber after decimal wrong.\n");
357 fprintf(temp, "\tn1 = %d, n2 = %d, buf= '%s'\n", n1, n2, buf);
358 return (-1);
359 }
360
361 if (n2 && !dp) {
362 fprintf(temp, "\tMissed decimal point.\n");
363 fprintf(temp, "\tn1 = %d, n2 = %d, buf= '%s'\n", n1, n2, buf);
364 return (-1);
365 }
366
Wanlong Gao354ebb42012-12-07 10:10:04 +0800367 return (0);
robbiew2c282cd2003-01-03 23:10:29 +0000368}
369
370/** LTP Port **/
371void setup()
372{
Garrett Cooper4b20b1d2010-12-18 01:06:11 -0800373 temp = stderr;
robbiew2c282cd2003-01-03 23:10:29 +0000374}
375
Garrett Cooper4b20b1d2010-12-18 01:06:11 -0800376void blenter()
robbiew2c282cd2003-01-03 23:10:29 +0000377{
Garrett Cooper4b20b1d2010-12-18 01:06:11 -0800378 local_flag = PASSED;
robbiew2c282cd2003-01-03 23:10:29 +0000379}
380
Garrett Cooper4b20b1d2010-12-18 01:06:11 -0800381void blexit()
robbiew2c282cd2003-01-03 23:10:29 +0000382{
Garrett Cooper4b20b1d2010-12-18 01:06:11 -0800383 if (local_flag == PASSED)
384 tst_resm(TPASS, "Test passed");
385 else
386 tst_resm(TFAIL, "Test failed");
Chris Dearmanec6edca2012-10-17 19:54:01 -0700387}