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
52 double pi;
53
54 /*char progname[]= "atof1()"; */
55 /** LTP Port **/
56 char *TCID = "atof01"; /* Test program identifier */
57
58 int local_flag = PASSED;
59 int block_number;
60 FILE *temp;
61 int TST_TOTAL = 1;
62
63 static void setup(void);
64 static void blenter(void);
65 static void blexit(void);
66 static int numin(char *, double *);
67 static int checkbuf(char *, int, int);
68
69 /*--------------------------------------------------------------*/
main(int argc,char * argv[])70 int 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
numin(char * str,double * rval)202 static 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
checkbuf(char * str,int n1,int n2)312 static 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 **/
setup(void)363 static void setup(void)
364 {
365 temp = stderr;
366 }
367
blenter(void)368 static void blenter(void)
369 {
370 local_flag = PASSED;
371 }
372
blexit(void)373 static 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