1 /*
2  * Copyright (c) 1994 Cygnus Support.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * and/or other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * at Cygnus Support, Inc.  Cygnus Support, Inc. may not be used to
11  * endorse or promote products derived from this software without
12  * specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 #include <stdlib.h>
18 #include <signal.h>
19 #include  "test.h"
20 #include <math.h>
21 #include <string.h>
22 #include <stdint.h>
23 #include <malloc.h>
24 int verbose;
25 static int count;
26 int inacc;
27 
28 int redo = 0;
29 extern int calc;
30 
31 #ifdef MALLOC_DEBUG
32 extern char **environ;
33 extern int _malloc_test_fail;
34 #endif
35 
36 int
main(int ac,char ** av)37 main (int ac,
38       char **av)
39 {
40 #ifdef MALLOC_DEBUG
41   environ = en;
42 #endif
43   int i;
44   int math2 = 1;
45   int string= 1;
46   int is = 1;
47   int math= 1;
48   int cvt = 1;
49 #ifdef _HAVE_IEEEFP_FUNCS
50   int ieee= 1;
51 #endif
52   int vector=0;
53   for (i = 1; i < ac; i++)
54   {
55     if (strcmp(av[i],"-v")==0)
56      verbose ++;
57     if (strcmp(av[i],"-nomath2") == 0)
58      math2 = 0;
59     (void) math2;
60     if (strcmp(av[i],"-nostrin") == 0)
61      string= 0;
62     (void) string;
63     if (strcmp(av[i],"-nois") == 0)
64      is = 0;
65     (void) is;
66     if (strcmp(av[i],"-nomath") == 0)
67      math= 0;
68     (void) math;
69     if (strcmp(av[i],"-nocvt") == 0)
70      cvt = 0;
71 #ifdef _HAVE_IEEEFP_FUNCS
72     if (strcmp(av[i],"-noiee") == 0)
73      ieee= 0;
74   (void) ieee;
75 #endif
76     if (strcmp(av[i],"-generate") == 0) {
77      vector = 1;
78      calc = 1;
79     }
80   }
81   if (cvt)
82    test_cvt();
83 
84 #if TEST_PART == 0 || TEST_PART == -1
85   if (math2)
86    test_math2();
87   if (string)
88    test_string();
89 #endif
90   if (math)
91    test_math(vector);
92 #if TEST_PART == 0 || TEST_PART == -1
93   if (is)
94    test_is();
95 #ifdef _HAVE_IEEEFP_FUNCS
96   if (ieee)
97    test_ieee();
98 #endif
99 #endif
100   printf("Tested %d functions, %d errors detected\n", count, inacc);
101   exit(inacc != 0);
102 }
103 
104 static const char *iname = "foo";
newfunc(const char * string)105 void newfunc (const char *string)
106 {
107   if (strcmp(iname, string))
108   {
109 #ifdef MALLOC_DEBUG
110     char *memcheck = getenv("CHECK_NAME");
111     if (memcheck && !strcmp(string, memcheck))
112       _malloc_test_fail = atoi(getenv("CHECK_COUNT"));
113     if (memcheck && !strcmp(iname, memcheck)) {
114       if (_malloc_test_fail) {
115 	printf("malloc test fail remain %d\n", _malloc_test_fail);
116 	_malloc_test_fail = 0;
117       }
118     }
119 #endif
120     printf("testing %s\n", string);
121     fflush(stdout);
122     iname = string;
123   }
124 
125 }
126 
127 
128 static int theline;
129 
line(int li)130 void line(int li)
131 {
132   if (verbose)
133   {
134     printf("  %d\n", li);
135   }
136   theline = li;
137 
138   count++;
139 }
140 
141 
142 
143 int reduce = 0;
144 
145 int strtod_vector = 0;
146 
147 int
bigger(__ieee_double_shape_type * a,__ieee_double_shape_type * b)148 bigger (__ieee_double_shape_type *a,
149 	   __ieee_double_shape_type *b)
150 {
151 
152   if (a->parts.msw > b->parts.msw)
153     {
154 
155       return 1;
156     }
157   else if (a->parts.msw == b->parts.msw)
158     {
159       if (a->parts.lsw > b->parts.lsw)
160 	{
161 	  return 1;
162 	}
163     }
164   return 0;
165 }
166 
167 int
fbigger(__ieee_float_shape_type * a,__ieee_float_shape_type * b)168 fbigger (__ieee_float_shape_type *a,
169 	   __ieee_float_shape_type *b)
170 {
171 
172   if (a->p1 > b->p1)
173     {
174       return 1;
175     }
176   return 0;
177 }
178 
179 
180 
181 /* Return the first bit different between two double numbers */
182 int
mag_of_error(double is,double shouldbe)183 mag_of_error (double is,
184        double shouldbe)
185 {
186   __ieee_double_shape_type a,b;
187   int i;
188   int a_big;
189   uint32_t mask;
190   uint32_t __x;
191   uint32_t msw, lsw;
192   a.value = is;
193 
194   b.value = shouldbe;
195 
196   if (a.parts.msw == b.parts.msw
197       && a.parts.lsw== b.parts.lsw) return 64;
198 
199 
200   /* Subtract the larger from the smaller number */
201 
202   a_big = bigger(&a, &b);
203 
204   if (!a_big) {
205     uint32_t t;
206     t = a.parts.msw;
207     a.parts.msw = b.parts.msw;
208     b.parts.msw = t;
209 
210     t = a.parts.lsw;
211     a.parts.lsw = b.parts.lsw;
212     b.parts.lsw = t;
213   }
214 
215 
216 
217   __x = (a.parts.lsw) - (b.parts.lsw);
218   msw = (a.parts.msw) - (b.parts.msw) - (__x > (a.parts.lsw));
219   lsw = __x;
220 
221 
222 
223 
224   /* Find out which bit the difference is in */
225   mask = 0x80000000UL;
226   for (i = 0; i < 32; i++)
227   {
228     if (((msw) & mask)!=0) return i;
229     mask >>=1;
230   }
231 
232   mask = 0x80000000UL;
233   for (i = 0; i < 32; i++)
234   {
235 
236     if (((lsw) & mask)!=0) return i+32;
237     mask >>=1;
238   }
239 
240   return 64;
241 
242 }
243 
244 /* Return the first bit different between two double numbers */
245 int
fmag_of_error(float is,float shouldbe)246 fmag_of_error (float is,
247        float shouldbe)
248 {
249   __ieee_float_shape_type a,b;
250   int i;
251   int a_big;
252   uint32_t mask;
253   uint32_t sw;
254   a.value = is;
255 
256   b.value = shouldbe;
257 
258   if (a.p1 == b.p1) return 32;
259 
260   /* Subtract the larger from the smaller number */
261 
262   a_big = fbigger(&a, &b);
263 
264   if (!a_big) {
265     uint32_t t;
266     t = a.p1;
267     a.p1 = b.p1;
268     b.p1 = t;
269   }
270 
271   sw = (a.p1) - (b.p1);
272 
273   mask = 0x80000000UL;
274   for (i = 0; i < 32; i++)
275   {
276 	  if (((sw) & mask)!=0) return i;
277 	  mask >>=1;
278   }
279   return 32;
280 }
281 
282  int ok_mag;
283 
284 
285 
286 void
test_sok(char * is,char * shouldbe)287 test_sok (char *is,
288        char *shouldbe)
289 {
290   if (strcmp(is,shouldbe))
291     {
292     printf("%s:%d, inacurate answer: (%s should be %s)\n",
293 	   iname,
294 	   theline,
295 	   is, shouldbe);
296     inacc++;
297   }
298 }
299 void
test_iok(int is,int shouldbe)300 test_iok (int is,
301        int shouldbe)
302 {
303   if (is != shouldbe){
304     printf("%s:%d, inacurate answer: (%08x should be %08x)\n",
305 	   iname,
306 	   theline,
307 	   is, shouldbe);
308     inacc++;
309   }
310 }
311 
312 
313 /* Compare counted strings upto a certain length - useful to test single
314    prec float conversions against double results
315 */
316 void
test_scok(char * is,char * shouldbe,int count)317 test_scok (char *is,
318        char *shouldbe,
319        int count)
320 {
321   if (strncmp(is,shouldbe, count))
322     {
323     printf("%s:%d, inacurate answer: (%s should be %s)\n",
324 	   iname,
325 	   theline,
326 	   is, shouldbe);
327     inacc++;
328   }
329 }
330 
331 /* Compare counted strings upto a certain length, allowing two forms - useful to test single
332    prec float conversions against double results
333 */
334 void
test_scok2(char * is,char * maybe1,char * maybe2,int count)335 test_scok2 (char *is,
336        char *maybe1,
337        char *maybe2,
338        int count)
339 {
340   if (strncmp(is,maybe1, count) && (maybe2 == NULL || strncmp(is,maybe2,count)))
341     {
342     printf("%s:%d, inacurate answer: (%s may be %s or %s)\n",
343 	   iname,
344 	   theline,
345 	   is, maybe1, maybe2 ? maybe2 : "(nothing)");
346     inacc++;
347   }
348 }
349 
350 void
test_eok(int is,int shouldbe)351 test_eok (int is,
352        int shouldbe)
353 {
354   if (is != shouldbe){
355     printf("%s:%d, bad errno answer: (%d should be %d)\n",
356 	   iname,
357 	   theline,
358 	   is, shouldbe);
359     inacc++;
360   }
361 }
362 
363 void
test_mok(double value,double shouldbe,int okmag)364 test_mok (double value,
365        double shouldbe,
366        int okmag)
367 {
368   __ieee_double_shape_type a,b;
369   int mag = mag_of_error(value, shouldbe);
370   if (mag == 0)
371   {
372     /* error in the first bit is ok if the numbers are both 0 */
373     if (value == 0.0 && shouldbe == 0.0)
374      return;
375 
376   }
377   a.value = shouldbe;
378   b.value = value;
379 
380   if (mag < okmag)
381   {
382     printf("%s:%d, wrong answer: bit %d ",
383 	   iname,
384 	   theline,
385 	   mag);
386      printf("%08lx%08lx %08lx%08lx) ",
387 	    (unsigned long) a.parts.msw,	     (unsigned long) a.parts.lsw,
388 	    (unsigned long) b.parts.msw,	     (unsigned long) b.parts.lsw);
389     printf("(%g %g)\n",   a.value, b.value);
390     inacc++;
391   }
392 }
393 
394 void
test_mfok(float value,float shouldbe,int okmag)395 test_mfok (float value,
396 	   float shouldbe,
397 	   int okmag)
398 {
399   __ieee_float_shape_type a,b;
400   int mag = fmag_of_error(value, shouldbe);
401   if (mag == 0)
402   {
403     /* error in the first bit is ok if the numbers are both 0 */
404     if (value == 0.0f && shouldbe == 0.0f)
405      return;
406 
407   }
408   a.value = shouldbe;
409   b.value = value;
410 
411   if (mag < okmag)
412   {
413     printf("%s:%d, wrong answer: bit %d ",
414 	   iname,
415 	   theline,
416 	   mag);
417      printf("%08lx %08lx) ",
418 	    (unsigned long) a.p1,
419 	    (unsigned long) b.p1);
420      printf("(%g %g)\n",   (double) a.value, (double) b.value);
421     inacc++;
422   }
423 }
424 
425 #ifdef __PCCNECV70__
kill()426 kill() {}
getpid()427 getpid() {}
428 #endif
429 
bt(void)430 void bt(void){
431 
432   double f1,f2;
433   f1 = 0.0;
434   f2 = 0.0/f1;
435   printf("(%g)\n", f2);
436 
437 }
438