• Home
  • 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 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