• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) Bull S.A. 2001
3  * Copyright (c) International Business Machines  Corp., 2001
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 /******************************************************************************/
21 /*                                                                            */
22 /* Dec-03-2001  Created: Jacky Malcles & Jean Noel Cordenner                  */
23 /*              These tests are adapted from AIX float PVT tests.             */
24 /*                                                                            */
25 /******************************************************************************/
26 #include "tfloat.h"
27 
28 #define SAFE_FREE(p) { if (p) { free(p); (p)=NULL; } }
29 /*
30  * allocates a buffer and read a file to it
31  * input parameters:
32  *	fname: name of the file to read
33  *	data:  pointer where buffer addr. will be returned
34  *
35  * uses also external variable datadir to build file pathname
36  *
37  * returns:
38  *	0 in case of failure
39  *	# of bytes read elsewhere
40  */
read_file(char * fname,void ** data)41 static size_t read_file(char *fname, void **data)
42 {
43 	struct stat bufstat;
44 	char path[PATH_MAX];
45 	size_t fsize;
46 	void *buffer;
47 	int fd;
48 	int maxretries = 1;
49 
50 	(void)sprintf(path, "%s/%s", datadir, fname);
51 
52 	errno = 0;
53 
54 	while (stat(path, &bufstat)) {
55 		if (errno == ETIMEDOUT || errno == EINTR || errno == 0) {
56 			printf("Error stat'ing %s: %s\n",
57 			       path, strerror(errno));
58 			pthread_testcancel();
59 			/* retrying... */
60 			if (maxretries--)
61 				continue;
62 		}
63 		return (size_t) 0;
64 	}
65 
66 	fsize = bufstat.st_size;
67 	if (!fsize) {
68 		errno = ENOENT;
69 		return (size_t) 0;
70 	}
71 
72 	while ((buffer = malloc(fsize)) == NULL) {
73 		if (errno == EINTR || errno == 0) {
74 			printf("Error malloc'ing: %s\n", strerror(errno));
75 			pthread_testcancel();
76 			/* retrying... */
77 			if (maxretries--)
78 				continue;
79 		}
80 		return (size_t) 0;
81 	}
82 
83 	while ((fd = open(path, O_RDONLY)) < 0) {
84 		if (errno == ETIMEDOUT || errno == EINTR || errno == 0) {
85 			printf("Error opening %s: %s\n", path, strerror(errno));
86 			pthread_testcancel();
87 			/* retrying... */
88 			if (maxretries--)
89 				continue;
90 		}
91 		SAFE_FREE(buffer);
92 		return (size_t) 0;
93 	}
94 
95 	while (read(fd, buffer, fsize) != fsize) {
96 		if (errno == ETIMEDOUT || errno == EINTR || errno == 0) {
97 			printf("Error reading %s: %s\n", path, strerror(errno));
98 			pthread_testcancel();
99 			/* retrying... */
100 			if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) 0) {
101 				if (maxretries--)
102 					continue;
103 			}
104 		}
105 		(void)close(fd);
106 		SAFE_FREE(buffer);
107 		return (size_t) 0;
108 	}
109 
110 	(void)close(fd);
111 	*data = buffer;
112 	return fsize;
113 }
114 
115 /* this subroutine is used in compute_xxx functions to check results
116    and record errors if appropriate */
check_error(TH_DATA * th_data,double e,double r,int index)117 static void check_error(TH_DATA * th_data, double e, double r, int index)
118 {
119 	double x;
120 	int pe, pr, px;
121 	static const char errtmplt[] =
122 	    "%s failed at index %d: OLD: %2.18e NEW: %2.18e DIFF: %2.18e\n";
123 
124 	x = fabs(r - e);	/* diff expected/computed */
125 
126 	if (x > EPS) {		/* error ? */
127 		/* compute exponent parts */
128 		(void)frexp(r, &pr);	/* for computed */
129 		(void)frexp(x, &px);	/* for difference */
130 		(void)frexp(e, &pe);	/* for dexected */
131 
132 		if (abs(pe - px) < th_data->th_func.precision ||
133 		    abs(pr - px) < th_data->th_func.precision) {
134 			/* not a rounding error */
135 			++th_data->th_nerror;
136 			/* record first error only ! */
137 			if (th_data->th_result == 0) {
138 				sprintf(th_data->detail_data,
139 					errtmplt,
140 					th_data->th_func.fident,
141 					index, e, r, x);
142 				th_data->th_result = 1;
143 			}
144 		}
145 	}
146 }
147 
148 /*
149  * these functions handle the various cases of computation
150  * they are called by pthread_code
151  */
152 
153 /* normal case: compares f(input data) to expected data */
compute_normal(TH_DATA * th_data,double * din,double * dex,int index)154 static void compute_normal(TH_DATA * th_data, double *din, double *dex,
155 			   int index)
156 {
157 	double d, r, e;
158 
159 	d = din[index];
160 	e = dex[index];
161 	r = (*(th_data->th_func.funct)) (d);
162 
163 	check_error(th_data, e, r, index);
164 }
165 
166 /* atan2 and hypot case: compares f(sin(input data),cos(input data))
167    to expected data */
compute_atan2_hypot(TH_DATA * th_data,double * din,double * dex,int index)168 static void compute_atan2_hypot(TH_DATA * th_data, double *din, double *dex,
169 				int index)
170 {
171 	double d, r, e;
172 
173 	d = din[index];
174 	e = dex[index];
175 	r = (*(th_data->th_func.funct)) (sin(d), cos(d));
176 
177 	check_error(th_data, e, r, index);
178 }
179 
180 /* modf case: compares integral and fractional parts to expected datas */
compute_modf(TH_DATA * th_data,double * din,double * dex,double * dex2,int index)181 static void compute_modf(TH_DATA * th_data, double *din, double *dex,
182 			 double *dex2, int index)
183 {
184 	static const char errtmplt1[] =
185 	    "%s failed at index %d: OLD integral part: %f NEW: %f\n";
186 	double d, r, e;
187 	double tmp;
188 
189 	d = din[index];
190 	e = dex[index];
191 	r = (*(th_data->th_func.funct)) (d, &tmp);
192 
193 	if (tmp != dex2[index]) {	/* bad integral part! */
194 		++th_data->th_nerror;
195 		/* record first error only ! */
196 		if (th_data->th_result == 0) {
197 			sprintf(th_data->detail_data,
198 				errtmplt1,
199 				th_data->th_func.fident,
200 				index, dex2[index], tmp);
201 			th_data->th_result = 1;
202 		}
203 		return;
204 	}
205 
206 	check_error(th_data, e, r, index);
207 }
208 
209 /* fmod and pow case: compares f(input data, input data2) to expected data */
compute_fmod_pow(TH_DATA * th_data,double * din,double * dex,double * dex2,int index)210 static void compute_fmod_pow(TH_DATA * th_data, double *din, double *dex,
211 			     double *dex2, int index)
212 {
213 	double d, r, e;
214 
215 	d = din[index];
216 	e = dex[index];
217 	r = (*(th_data->th_func.funct)) (d, dex2[index]);
218 
219 	check_error(th_data, e, r, index);
220 }
221 
222 /* frexp case: compares mantissa and exponent to expected datas */
223 /* lgamma case: compares result and signgam to expected datas */
compute_frexp_lgamma(TH_DATA * th_data,double * din,double * dex,int * dex2,int index)224 static void compute_frexp_lgamma(TH_DATA * th_data, double *din, double *dex,
225 				 int *dex2, int index)
226 {
227 	static const char errtmplt2[] =
228 	    "%s failed at index %d: OLD (exp. or sign): %d NEW: %d\n";
229 	double d, r, e;
230 	int tmp;
231 	static const char xinf[8] = "lgamma";
232 
233 	d = din[index];
234 	e = dex[index];
235 	r = (*(th_data->th_func.funct)) (d, &tmp);
236 
237 	if (strcmp(th_data->th_func.fident, xinf) != 0) {
238 		if (tmp != dex2[index]) {	/* bad exponent! */
239 			++th_data->th_nerror;
240 			/* record first error only ! */
241 			if (th_data->th_result == 0) {
242 				sprintf(th_data->detail_data,
243 					errtmplt2,
244 					th_data->th_func.fident,
245 					index, dex2[index], tmp);
246 				th_data->th_result = 1;
247 			}
248 			return;
249 		}
250 	}
251 
252 	check_error(th_data, e, r, index);
253 }
254 
255 /* ldexp case: compares f(input data, input data2) to expected data */
compute_ldexp(TH_DATA * th_data,double * din,double * dex,int * din2,int index)256 static void compute_ldexp(TH_DATA * th_data, double *din, double *dex,
257 			  int *din2, int index)
258 {
259 	double d, r, e;
260 
261 	d = din[index];
262 	e = dex[index];
263 	r = (*(th_data->th_func.funct)) (d, din2[index]);
264 
265 	check_error(th_data, e, r, index);
266 }
267 
268 /*
269  * Function which does the job, to be called as the
270  * "start routine" parameter of pthread_create subroutine.
271  * Uses the compute_xxx subroutines above.
272  *
273  * input parameters ("arg" parameter of pthread_create subroutine):
274  *	pointer to a TH_DATA structure.
275  *
276  */
thread_code(void * arg)277 void *thread_code(void *arg)
278 {
279 	TH_DATA *th_data = (TH_DATA *) arg;
280 	size_t fsize, fsize2, fsize3;
281 	double *din, *dex, *dex2 = NULL;
282 	int imax, index;
283 
284 	fsize = read_file(th_data->th_func.din_fname, (void **)&din);
285 	if (fsize == (size_t) 0) {
286 		sprintf(th_data->detail_data,
287 			"FAIL: %s: reading %s, %s\n",
288 			th_data->th_func.fident,
289 			th_data->th_func.din_fname, strerror(errno));
290 		th_data->th_result = 1;
291 		SAFE_FREE(din);
292 		pthread_exit((void *)1);
293 	}
294 	fsize2 = read_file(th_data->th_func.dex_fname, (void **)&dex);
295 	if (fsize2 == (size_t) 0) {
296 		sprintf(th_data->detail_data,
297 			"FAIL: %s: reading %s, %s\n",
298 			th_data->th_func.fident,
299 			th_data->th_func.dex_fname, strerror(errno));
300 		th_data->th_result = 1;
301 		SAFE_FREE(din);
302 		SAFE_FREE(dex);
303 		pthread_exit((void *)1);
304 	}
305 
306 	fsize3 = (size_t) 0;
307 	switch (th_data->th_func.code_funct) {
308 	case FUNC_MODF:
309 	case FUNC_FMOD:
310 	case FUNC_POW:
311 	case FUNC_FREXP:
312 	case FUNC_LDEXP:
313 	case FUNC_GAM:
314 		fsize3 = read_file(th_data->th_func.dex2_fname, (void **)&dex2);
315 		if (fsize3 == (size_t) 0) {
316 			sprintf(th_data->detail_data,
317 				"FAIL: %s: reading %s, %s\n",
318 				th_data->th_func.fident,
319 				th_data->th_func.dex2_fname, strerror(errno));
320 			th_data->th_result = 1;
321 			SAFE_FREE(din);
322 			SAFE_FREE(dex);
323 			pthread_exit((void *)1);
324 		}
325 	}
326 
327 	switch (th_data->th_func.code_funct) {
328 	case FUNC_NORMAL:
329 	case FUNC_ATAN2:
330 	case FUNC_HYPOT:
331 		if (fsize2 != fsize)
332 			goto file_size_error;
333 		break;
334 	case FUNC_MODF:
335 	case FUNC_FMOD:
336 	case FUNC_POW:
337 		if (fsize2 != fsize || fsize3 != fsize)
338 			goto file_size_error;
339 		break;
340 	case FUNC_FREXP:
341 	case FUNC_LDEXP:
342 	case FUNC_GAM:
343 		if (fsize2 != fsize ||
344 		    (sizeof(double) / sizeof(int)) * fsize3 != fsize)
345 			goto file_size_error;
346 		break;
347 	default:
348 file_size_error:
349 		sprintf(th_data->detail_data,
350 			"FAIL: %s: file sizes don't match\n",
351 			th_data->th_func.fident);
352 		th_data->th_result = 1;
353 		SAFE_FREE(din);
354 		SAFE_FREE(dex);
355 		if (fsize3)
356 			SAFE_FREE(dex2);
357 		pthread_exit((void *)1);
358 	}
359 
360 	imax = fsize / sizeof(double);
361 
362 	while (th_data->th_nloop <= num_loops) {
363 		/* loop stopped by pthread_cancel */
364 
365 		for (index = th_data->th_num; index < imax; index += num_threads) {	/* computation loop */
366 			switch (th_data->th_func.code_funct) {
367 			case FUNC_NORMAL:
368 				compute_normal(th_data, din, dex, index);
369 				break;
370 			case FUNC_ATAN2:
371 			case FUNC_HYPOT:
372 				compute_atan2_hypot(th_data, din, dex, index);
373 				break;
374 			case FUNC_MODF:
375 				compute_modf(th_data, din, dex, dex2, index);
376 				break;
377 			case FUNC_FMOD:
378 			case FUNC_POW:
379 				compute_fmod_pow(th_data,
380 						 din, dex, dex2, index);
381 				break;
382 			case FUNC_FREXP:
383 			case FUNC_GAM:
384 				compute_frexp_lgamma(th_data,
385 						     din, dex, (int *)dex2,
386 						     index);
387 				break;
388 			case FUNC_LDEXP:
389 				compute_ldexp(th_data,
390 					      din, dex, (int *)dex2, index);
391 				break;
392 			default:
393 				sprintf(th_data->detail_data,
394 					"FAIL: %s: unexpected function type\n",
395 					th_data->th_func.fident);
396 				th_data->th_result = 1;
397 				SAFE_FREE(din);
398 				SAFE_FREE(dex);
399 				if (fsize3)
400 					SAFE_FREE(dex2);
401 				pthread_exit((void *)1);
402 			}
403 			pthread_testcancel();
404 		}		/* end of computation loop */
405 		++th_data->th_nloop;
406 	}			/* end of loop */
407 	SAFE_FREE(din);
408 	SAFE_FREE(dex);
409 	if (fsize3)
410 		SAFE_FREE(dex2);
411 	pthread_exit(NULL);
412 }
413