• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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