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 int errno;
61 FILE *temp;
62 int TST_TOTAL = 1;
63
64 static void setup(void);
65 static void blenter(void);
66 static void blexit(void);
67 static int numin(char *, double *);
68 static int checkbuf(char *, int, int);
69
70 /*--------------------------------------------------------------*/
main(int argc,char * argv[])71 int main(int argc, char *argv[])
72 {
73 register int i, j;
74 double r1, r2, x;
75 char buf[100];
76
77 setup(); /* temp file is now open */
78 pi = 4.0 * atan(1.0);
79
80 /*--------------------------------------------------------------*/
81 blenter();
82
83 for (i = 0; i < 30; i++)
84 for (j = 0; j < 30; j++) {
85 sprintf(buf, "%*.*f", i, j, pi);
86 if (checkbuf(buf, i, j)) {
87 fprintf(temp, "output conversion incorrect.");
88 fprintf(temp, "%*.*f = '%s'", i, j, pi, buf);
89 local_flag = FAILED;
90 }
91 r1 = atof(buf);
92 if (numin(buf, &r2)) {
93 fprintf(temp, "\tnumin('%s') failed\n", buf);
94 local_flag = FAILED;
95 }
96 x = fabs(r1 - r2);
97 if (x > ERR) {
98 fprintf(temp, "\tcompare fails, %f vs %f\n",
99 r1, r2);
100 fprintf(temp, "\terr value is %f\n", x);
101 local_flag = FAILED;
102 }
103 if (local_flag == FAILED)
104 break;
105 }
106
107 blexit();
108 /*--------------------------------------------------------------*/
109 blenter();
110
111 x = 1.0 - exp(-100.0); /* 1.0 - very small number */
112 sprintf(buf, "%f", x);
113 r1 = atof(buf);
114 if (r1 != 1.0) {
115 fprintf(temp, "\tsprintf small # failed\n");
116 fprintf(temp, "\t printed '%s', expected 1.0\n", buf);
117 local_flag = FAILED;
118 }
119
120 blexit();
121 /*--------------------------------------------------------------*/
122 blenter();
123
124 for (i = 1; i < 200; i++) {
125 x = 100.0 / (double)i;
126 sprintf(buf, "%f", x);
127 r1 = atof(buf);
128 if (numin(buf, &r2)) {
129 fprintf(temp, "\tnumin('%s') failed\n", buf);
130 local_flag = FAILED;
131 }
132 /*
133 * Order subtraction to produce a positive number.
134 * Then subtrace "fudge" factor which should give us
135 * a negative number, as the result fo subtraction should
136 * always be smaller than the fudge factor.
137 */
138 if (r1 > r2)
139 x = r1 - r2 - 1e-10;
140 else
141 x = r2 - r1 - 1e-10;
142 if (x > 0.0) {
143 fprintf(temp, "\tx = %.15f = %e\n", x, x);
144 fprintf(temp, "\titeration %d\n", i);
145 fprintf(temp, "\tcompare fails, %f vs %f\n", r1, r2);
146 fprintf(temp, "\tcompare fails, %.15f vs %.15f\n",
147 r1, r2);
148 fprintf(temp, "\tbuf = '%s'\n", buf);
149 x = r1 - r2;
150 if (x == 0.0)
151 fprintf(temp, "\tx == 0.0\n");
152 else
153 fprintf(temp, "\tx != 0.0\n");
154 fprintf(temp, "\tx = %.15f = %e\n", x, x);
155 local_flag = FAILED;
156 }
157 if (local_flag == FAILED)
158 break;
159 }
160
161 blexit();
162 /*--------------------------------------------------------------*/
163 blenter();
164
165 for (i = -1; i > -200; i--) {
166 x = 100.0 / (double)i;
167 sprintf(buf, "%f", x);
168 r1 = atof(buf);
169 if (numin(buf, &r2)) {
170 fprintf(temp, "\tnumin('%s') failed\n", buf);
171 local_flag = FAILED;
172 }
173 /*
174 * Same ordering of subtraction as above.
175 */
176 if (r1 > r2)
177 x = r1 - r2 - 1e-10;
178 else
179 x = r2 - r1 - 1e-10;
180 if (x > 0.0) {
181 fprintf(temp, "\tcompare fails, %f vs %f\n", r1, r2);
182 fprintf(temp, "\tcompare fails, %.15f vs %.15f\n",
183 r1, r2);
184 x = r1 - r2;
185 if (x == 0.0)
186 fprintf(temp, "\tx == 0.0)\n");
187 else
188 fprintf(temp, "\tx != 0.0\n");
189 fprintf(temp, "\tx = %.15f = %e\n", x, x);
190 local_flag = FAILED;
191 }
192 if (local_flag == FAILED)
193 break;
194 }
195
196 blexit();
197 /*--------------------------------------------------------------*/
198 tst_exit();
199 }
200
201 /* FUNCTIONS GO HERE */
202
numin(char * str,double * rval)203 static int numin(char *str, double *rval)
204 {
205 register int i, v3, e_flag;
206 register char c;
207 double val, v1, v2, k;
208 int neg_flag = 0;
209
210 val = v1 = v2 = 0.0;
211 v3 = 0;
212 k = 0.1;
213
214 while (*str == ' ') /* scan past white space */
215 str++;
216
217 if (*str == '-') { /* negitive value test */
218 neg_flag++;
219 str++;
220 }
221
222 for (;;) {
223 c = *str;
224 if (!isdigit(c))
225 break;
226 v1 *= 10.0;
227 v1 += (double)(c - '0');
228 str++;
229 }
230
231 val = v1;
232
233 #ifdef DEBUG
234 printf("First conversion, val = %f = %e\n", val, val);
235 #endif
236
237 if (*str == '.') {
238 str++;
239 for (;;) {
240 c = *str;
241 if (!isdigit(c))
242 break;
243 v2 += k * (double)(c - '0');
244 k /= 10.0;
245 str++;
246 }
247 val += v2;
248 }
249 #ifdef DEBUG
250 printf("Second conversion, val = %f = %e\n", val, val);
251 #endif
252
253 if (*str == 'e') {
254 str++;
255 switch (*str) {
256 case '+':
257 e_flag = 1;
258 break;
259 case '-':
260 e_flag = -1;
261 break;
262 default:
263 fprintf(temp, "\tbad char '%c' after 'e'\n", *str);
264 printf("bad char '%c' after 'e'\n", *str);
265 return (-1);
266 }
267 str++;
268 if (!isdigit(*str)) {
269 fprintf(temp, "\tbad exponent field\n");
270 printf("bad exponent field\n");
271 return (-1);
272 }
273 v3 = 10 * (int)(*str - '0');
274 str++;
275 if (!isdigit(*str)) {
276 fprintf(temp, "\tbad exponent field\n");
277 printf("bad exponent field\n");
278 return (-1);
279 }
280 v3 += (int)(*str - '0');
281 str++;
282 for (i = 0; i < v3; i++) {
283 if (e_flag > 0)
284 val *= 10.0;
285 else
286 val *= 0.1;
287 }
288 }
289
290 if (neg_flag)
291 val *= -1.0;
292
293 #ifdef DEBUG
294 printf("Third conversion, val = %f = %e\n", val, val);
295 printf("v1 = %f, v2 = %f, v3 = %d\n", v1, v2, v3);
296 #endif
297
298 switch (*str) {
299 case '\0':
300 case ' ':
301 case '\t':
302 case '\n':
303 break;
304 default:
305 printf("unexpected char '%c'\n", *str);
306 return (-1);
307 }
308
309 *rval = val;
310 return (0);
311 }
312
checkbuf(char * str,int n1,int n2)313 static int checkbuf(char *str, int n1, int n2)
314 {
315 register int bd; /* before decimal point */
316 register int ad; /* after decimal point */
317 register int tw; /* total width */
318 register int dp; /* decimal point */
319 char *buf;
320
321 bd = ad = dp = 0;
322 buf = str;
323
324 while (*str && *str != '.') {
325 bd++;
326 str++;
327 }
328 if (*str == '.') {
329 dp++;
330 str++;
331 if (*str) {
332 while (*str) {
333 ad++;
334 str++;
335 }
336 }
337 }
338
339 tw = bd + dp + ad;
340 if (!n1)
341 n1++;
342 if (tw < n1) {
343 fprintf(temp, "\tWidth too small.\n");
344 fprintf(temp, "\tn1 = %d, n2 = %d, buf= '%s'\n", n1, n2, buf);
345 return (-1);
346 }
347
348 if (ad != n2) {
349 fprintf(temp, "\tNumber after decimal wrong.\n");
350 fprintf(temp, "\tn1 = %d, n2 = %d, buf= '%s'\n", n1, n2, buf);
351 return (-1);
352 }
353
354 if (n2 && !dp) {
355 fprintf(temp, "\tMissed decimal point.\n");
356 fprintf(temp, "\tn1 = %d, n2 = %d, buf= '%s'\n", n1, n2, buf);
357 return (-1);
358 }
359
360 return (0);
361 }
362
363 /** LTP Port **/
setup(void)364 static void setup(void)
365 {
366 temp = stderr;
367 }
368
blenter(void)369 static void blenter(void)
370 {
371 local_flag = PASSED;
372 }
373
blexit(void)374 static void blexit(void)
375 {
376 if (local_flag == PASSED)
377 tst_resm(TPASS, "Test passed");
378 else
379 tst_resm(TFAIL, "Test failed");
380 }
381