1
2 /*
3 ===============================================================================
4
5 This C source file is part of TestFloat, Release 2a, a package of programs
6 for testing the correctness of floating-point arithmetic complying to the
7 IEC/IEEE Standard for Floating-Point.
8
9 Written by John R. Hauser. More information is available through the Web
10 page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'.
11
12 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
13 has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
14 TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
15 PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
16 AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
17
18 Derivative works are acceptable, even for commercial purposes, so long as
19 (1) they include prominent notice that the work is derivative, and (2) they
20 include prominent notice akin to these four paragraphs for those parts of
21 this code that are retained.
22
23 ===============================================================================
24 */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #include <stdlib.h>
30 #include <signal.h>
31 #include <string.h>
32 #include "milieu.h"
33 #include "fail.h"
34 #include "softfloat.h"
35 #include "slowfloat.h"
36 #include "testCases.h"
37 #include "testLoops.h"
38
catchSIGINT(int signalCode)39 static void catchSIGINT( int signalCode )
40 {
41
42 if ( stop ) exit( EXIT_FAILURE );
43 stop = TRUE;
44
45 }
46
clearFlags(void)47 int8 clearFlags( void )
48 {
49 int8 flags;
50
51 flags = float_exception_flags;
52 float_exception_flags = 0;
53 return flags;
54
55 }
56
57 enum {
58 INT32_TO_FLOAT32 = 1,
59 INT32_TO_FLOAT64,
60 #ifdef FLOATX80
61 INT32_TO_FLOATX80,
62 #endif
63 #ifdef FLOAT128
64 INT32_TO_FLOAT128,
65 #endif
66 #ifdef BITS64
67 INT64_TO_FLOAT32,
68 INT64_TO_FLOAT64,
69 #ifdef FLOATX80
70 INT64_TO_FLOATX80,
71 #endif
72 #ifdef FLOAT128
73 INT64_TO_FLOAT128,
74 #endif
75 #endif
76 FLOAT32_TO_INT32,
77 FLOAT32_TO_INT32_ROUND_TO_ZERO,
78 #ifdef BITS64
79 FLOAT32_TO_INT64,
80 FLOAT32_TO_INT64_ROUND_TO_ZERO,
81 #endif
82 FLOAT32_TO_FLOAT64,
83 #ifdef FLOATX80
84 FLOAT32_TO_FLOATX80,
85 #endif
86 #ifdef FLOAT128
87 FLOAT32_TO_FLOAT128,
88 #endif
89 FLOAT32_ROUND_TO_INT,
90 FLOAT32_ADD,
91 FLOAT32_SUB,
92 FLOAT32_MUL,
93 FLOAT32_DIV,
94 FLOAT32_REM,
95 FLOAT32_SQRT,
96 FLOAT32_EQ,
97 FLOAT32_LE,
98 FLOAT32_LT,
99 FLOAT32_EQ_SIGNALING,
100 FLOAT32_LE_QUIET,
101 FLOAT32_LT_QUIET,
102 FLOAT64_TO_INT32,
103 FLOAT64_TO_INT32_ROUND_TO_ZERO,
104 #ifdef BITS64
105 FLOAT64_TO_INT64,
106 FLOAT64_TO_INT64_ROUND_TO_ZERO,
107 #endif
108 FLOAT64_TO_FLOAT32,
109 #ifdef FLOATX80
110 FLOAT64_TO_FLOATX80,
111 #endif
112 #ifdef FLOAT128
113 FLOAT64_TO_FLOAT128,
114 #endif
115 FLOAT64_ROUND_TO_INT,
116 FLOAT64_ADD,
117 FLOAT64_SUB,
118 FLOAT64_MUL,
119 FLOAT64_DIV,
120 FLOAT64_REM,
121 FLOAT64_SQRT,
122 FLOAT64_EQ,
123 FLOAT64_LE,
124 FLOAT64_LT,
125 FLOAT64_EQ_SIGNALING,
126 FLOAT64_LE_QUIET,
127 FLOAT64_LT_QUIET,
128 #ifdef FLOATX80
129 FLOATX80_TO_INT32,
130 FLOATX80_TO_INT32_ROUND_TO_ZERO,
131 #ifdef BITS64
132 FLOATX80_TO_INT64,
133 FLOATX80_TO_INT64_ROUND_TO_ZERO,
134 #endif
135 FLOATX80_TO_FLOAT32,
136 FLOATX80_TO_FLOAT64,
137 #ifdef FLOAT128
138 FLOATX80_TO_FLOAT128,
139 #endif
140 FLOATX80_ROUND_TO_INT,
141 FLOATX80_ADD,
142 FLOATX80_SUB,
143 FLOATX80_MUL,
144 FLOATX80_DIV,
145 FLOATX80_REM,
146 FLOATX80_SQRT,
147 FLOATX80_EQ,
148 FLOATX80_LE,
149 FLOATX80_LT,
150 FLOATX80_EQ_SIGNALING,
151 FLOATX80_LE_QUIET,
152 FLOATX80_LT_QUIET,
153 #endif
154 #ifdef FLOAT128
155 FLOAT128_TO_INT32,
156 FLOAT128_TO_INT32_ROUND_TO_ZERO,
157 #ifdef BITS64
158 FLOAT128_TO_INT64,
159 FLOAT128_TO_INT64_ROUND_TO_ZERO,
160 #endif
161 FLOAT128_TO_FLOAT32,
162 FLOAT128_TO_FLOAT64,
163 #ifdef FLOATX80
164 FLOAT128_TO_FLOATX80,
165 #endif
166 FLOAT128_ROUND_TO_INT,
167 FLOAT128_ADD,
168 FLOAT128_SUB,
169 FLOAT128_MUL,
170 FLOAT128_DIV,
171 FLOAT128_REM,
172 FLOAT128_SQRT,
173 FLOAT128_EQ,
174 FLOAT128_LE,
175 FLOAT128_LT,
176 FLOAT128_EQ_SIGNALING,
177 FLOAT128_LE_QUIET,
178 FLOAT128_LT_QUIET,
179 #endif
180 NUM_FUNCTIONS
181 };
182 static struct {
183 char *name;
184 int8 numInputs;
185 flag roundingPrecision, roundingMode;
186 flag tininessMode, tininessModeAtReducedPrecision;
187 } functions[ NUM_FUNCTIONS ] = {
188 { 0, 0, 0, 0, 0, 0 },
189 { "int32_to_float32", 1, FALSE, TRUE, FALSE, FALSE },
190 { "int32_to_float64", 1, FALSE, FALSE, FALSE, FALSE },
191 #ifdef FLOATX80
192 { "int32_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE },
193 #endif
194 #ifdef FLOAT128
195 { "int32_to_float128", 1, FALSE, FALSE, FALSE, FALSE },
196 #endif
197 #ifdef BITS64
198 { "int64_to_float32", 1, FALSE, TRUE, FALSE, FALSE },
199 { "int64_to_float64", 1, FALSE, TRUE, FALSE, FALSE },
200 #ifdef FLOATX80
201 { "int64_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE },
202 #endif
203 #ifdef FLOAT128
204 { "int64_to_float128", 1, FALSE, FALSE, FALSE, FALSE },
205 #endif
206 #endif
207 { "float32_to_int32", 1, FALSE, TRUE, FALSE, FALSE },
208 { "float32_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
209 #ifdef BITS64
210 { "float32_to_int64", 1, FALSE, TRUE, FALSE, FALSE },
211 { "float32_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
212 #endif
213 { "float32_to_float64", 1, FALSE, FALSE, FALSE, FALSE },
214 #ifdef FLOATX80
215 { "float32_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE },
216 #endif
217 #ifdef FLOAT128
218 { "float32_to_float128", 1, FALSE, FALSE, FALSE, FALSE },
219 #endif
220 { "float32_round_to_int", 1, FALSE, TRUE, FALSE, FALSE },
221 { "float32_add", 2, FALSE, TRUE, FALSE, FALSE },
222 { "float32_sub", 2, FALSE, TRUE, FALSE, FALSE },
223 { "float32_mul", 2, FALSE, TRUE, TRUE, FALSE },
224 { "float32_div", 2, FALSE, TRUE, FALSE, FALSE },
225 { "float32_rem", 2, FALSE, FALSE, FALSE, FALSE },
226 { "float32_sqrt", 1, FALSE, TRUE, FALSE, FALSE },
227 { "float32_eq", 2, FALSE, FALSE, FALSE, FALSE },
228 { "float32_le", 2, FALSE, FALSE, FALSE, FALSE },
229 { "float32_lt", 2, FALSE, FALSE, FALSE, FALSE },
230 { "float32_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE },
231 { "float32_le_quiet", 2, FALSE, FALSE, FALSE, FALSE },
232 { "float32_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE },
233 { "float64_to_int32", 1, FALSE, TRUE, FALSE, FALSE },
234 { "float64_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
235 #ifdef BITS64
236 { "float64_to_int64", 1, FALSE, TRUE, FALSE, FALSE },
237 { "float64_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
238 #endif
239 { "float64_to_float32", 1, FALSE, TRUE, TRUE, FALSE },
240 #ifdef FLOATX80
241 { "float64_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE },
242 #endif
243 #ifdef FLOAT128
244 { "float64_to_float128", 1, FALSE, FALSE, FALSE, FALSE },
245 #endif
246 { "float64_round_to_int", 1, FALSE, TRUE, FALSE, FALSE },
247 { "float64_add", 2, FALSE, TRUE, FALSE, FALSE },
248 { "float64_sub", 2, FALSE, TRUE, FALSE, FALSE },
249 { "float64_mul", 2, FALSE, TRUE, TRUE, FALSE },
250 { "float64_div", 2, FALSE, TRUE, FALSE, FALSE },
251 { "float64_rem", 2, FALSE, FALSE, FALSE, FALSE },
252 { "float64_sqrt", 1, FALSE, TRUE, FALSE, FALSE },
253 { "float64_eq", 2, FALSE, FALSE, FALSE, FALSE },
254 { "float64_le", 2, FALSE, FALSE, FALSE, FALSE },
255 { "float64_lt", 2, FALSE, FALSE, FALSE, FALSE },
256 { "float64_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE },
257 { "float64_le_quiet", 2, FALSE, FALSE, FALSE, FALSE },
258 { "float64_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE },
259 #ifdef FLOATX80
260 { "floatx80_to_int32", 1, FALSE, TRUE, FALSE, FALSE },
261 { "floatx80_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
262 #ifdef BITS64
263 { "floatx80_to_int64", 1, FALSE, TRUE, FALSE, FALSE },
264 { "floatx80_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
265 #endif
266 { "floatx80_to_float32", 1, FALSE, TRUE, TRUE, FALSE },
267 { "floatx80_to_float64", 1, FALSE, TRUE, TRUE, FALSE },
268 #ifdef FLOAT128
269 { "floatx80_to_float128", 1, FALSE, FALSE, FALSE, FALSE },
270 #endif
271 { "floatx80_round_to_int", 1, FALSE, TRUE, FALSE, FALSE },
272 { "floatx80_add", 2, TRUE, TRUE, FALSE, TRUE },
273 { "floatx80_sub", 2, TRUE, TRUE, FALSE, TRUE },
274 { "floatx80_mul", 2, TRUE, TRUE, TRUE, TRUE },
275 { "floatx80_div", 2, TRUE, TRUE, FALSE, TRUE },
276 { "floatx80_rem", 2, FALSE, FALSE, FALSE, FALSE },
277 { "floatx80_sqrt", 1, TRUE, TRUE, FALSE, FALSE },
278 { "floatx80_eq", 2, FALSE, FALSE, FALSE, FALSE },
279 { "floatx80_le", 2, FALSE, FALSE, FALSE, FALSE },
280 { "floatx80_lt", 2, FALSE, FALSE, FALSE, FALSE },
281 { "floatx80_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE },
282 { "floatx80_le_quiet", 2, FALSE, FALSE, FALSE, FALSE },
283 { "floatx80_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE },
284 #endif
285 #ifdef FLOAT128
286 { "float128_to_int32", 1, FALSE, TRUE, FALSE, FALSE },
287 { "float128_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
288 #ifdef BITS64
289 { "float128_to_int64", 1, FALSE, TRUE, FALSE, FALSE },
290 { "float128_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
291 #endif
292 { "float128_to_float32", 1, FALSE, TRUE, TRUE, FALSE },
293 { "float128_to_float64", 1, FALSE, TRUE, TRUE, FALSE },
294 #ifdef FLOATX80
295 { "float128_to_floatx80", 1, FALSE, TRUE, TRUE, FALSE },
296 #endif
297 { "float128_round_to_int", 1, FALSE, TRUE, FALSE, FALSE },
298 { "float128_add", 2, FALSE, TRUE, FALSE, FALSE },
299 { "float128_sub", 2, FALSE, TRUE, FALSE, FALSE },
300 { "float128_mul", 2, FALSE, TRUE, TRUE, FALSE },
301 { "float128_div", 2, FALSE, TRUE, FALSE, FALSE },
302 { "float128_rem", 2, FALSE, FALSE, FALSE, FALSE },
303 { "float128_sqrt", 1, FALSE, TRUE, FALSE, FALSE },
304 { "float128_eq", 2, FALSE, FALSE, FALSE, FALSE },
305 { "float128_le", 2, FALSE, FALSE, FALSE, FALSE },
306 { "float128_lt", 2, FALSE, FALSE, FALSE, FALSE },
307 { "float128_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE },
308 { "float128_le_quiet", 2, FALSE, FALSE, FALSE, FALSE },
309 { "float128_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE },
310 #endif
311 };
312
313 enum {
314 ROUND_NEAREST_EVEN = 1,
315 ROUND_TO_ZERO,
316 ROUND_DOWN,
317 ROUND_UP,
318 NUM_ROUNDINGMODES
319 };
320 enum {
321 TININESS_BEFORE_ROUNDING = 1,
322 TININESS_AFTER_ROUNDING,
323 NUM_TININESSMODES
324 };
325
326 static void
testFunctionVariety(uint8 functionCode,int8 roundingPrecision,int8 roundingMode,int8 tininessMode)327 testFunctionVariety(
328 uint8 functionCode,
329 int8 roundingPrecision,
330 int8 roundingMode,
331 int8 tininessMode
332 )
333 {
334 uint8 roundingCode;
335 int8 tininessCode;
336
337 functionName = functions[ functionCode ].name;
338 if ( roundingPrecision == 32 ) {
339 roundingPrecisionName = "32";
340 }
341 else if ( roundingPrecision == 64 ) {
342 roundingPrecisionName = "64";
343 }
344 else if ( roundingPrecision == 80 ) {
345 roundingPrecisionName = "80";
346 }
347 else {
348 roundingPrecisionName = 0;
349 }
350 #ifdef FLOATX80
351 floatx80_rounding_precision = roundingPrecision;
352 slow_floatx80_rounding_precision = roundingPrecision;
353 #endif
354 switch ( roundingMode ) {
355 default:
356 roundingModeName = 0;
357 roundingCode = float_round_nearest_even;
358 break;
359 case ROUND_NEAREST_EVEN:
360 roundingModeName = "nearest_even";
361 roundingCode = float_round_nearest_even;
362 break;
363 case ROUND_TO_ZERO:
364 roundingModeName = "to_zero";
365 roundingCode = float_round_to_zero;
366 break;
367 case ROUND_DOWN:
368 roundingModeName = "down";
369 roundingCode = float_round_down;
370 break;
371 case ROUND_UP:
372 roundingModeName = "up";
373 roundingCode = float_round_up;
374 break;
375 }
376 float_rounding_mode = roundingCode;
377 slow_float_rounding_mode = roundingCode;
378 switch ( tininessMode ) {
379 default:
380 tininessModeName = 0;
381 tininessCode = float_tininess_after_rounding;
382 break;
383 case TININESS_BEFORE_ROUNDING:
384 tininessModeName = "before";
385 tininessCode = float_tininess_before_rounding;
386 break;
387 case TININESS_AFTER_ROUNDING:
388 tininessModeName = "after";
389 tininessCode = float_tininess_after_rounding;
390 break;
391 }
392 float_detect_tininess = tininessCode;
393 slow_float_detect_tininess = tininessCode;
394 fputs( "Testing ", stderr );
395 writeFunctionName( stderr );
396 fputs( ".\n", stderr );
397 switch ( functionCode ) {
398 case INT32_TO_FLOAT32:
399 test_a_int32_z_float32( slow_int32_to_float32, int32_to_float32 );
400 break;
401 case INT32_TO_FLOAT64:
402 test_a_int32_z_float64( slow_int32_to_float64, int32_to_float64 );
403 break;
404 #ifdef FLOATX80
405 case INT32_TO_FLOATX80:
406 test_a_int32_z_floatx80( slow_int32_to_floatx80, int32_to_floatx80 );
407 break;
408 #endif
409 #ifdef FLOAT128
410 case INT32_TO_FLOAT128:
411 test_a_int32_z_float128( slow_int32_to_float128, int32_to_float128 );
412 break;
413 #endif
414 #ifdef BITS64
415 case INT64_TO_FLOAT32:
416 test_a_int64_z_float32( slow_int64_to_float32, int64_to_float32 );
417 break;
418 case INT64_TO_FLOAT64:
419 test_a_int64_z_float64( slow_int64_to_float64, int64_to_float64 );
420 break;
421 #ifdef FLOATX80
422 case INT64_TO_FLOATX80:
423 test_a_int64_z_floatx80( slow_int64_to_floatx80, int64_to_floatx80 );
424 break;
425 #endif
426 #ifdef FLOAT128
427 case INT64_TO_FLOAT128:
428 test_a_int64_z_float128( slow_int64_to_float128, int64_to_float128 );
429 break;
430 #endif
431 #endif
432 case FLOAT32_TO_INT32:
433 test_a_float32_z_int32( slow_float32_to_int32, float32_to_int32 );
434 break;
435 case FLOAT32_TO_INT32_ROUND_TO_ZERO:
436 test_a_float32_z_int32(
437 slow_float32_to_int32_round_to_zero,
438 float32_to_int32_round_to_zero
439 );
440 break;
441 #ifdef BITS64
442 case FLOAT32_TO_INT64:
443 test_a_float32_z_int64( slow_float32_to_int64, float32_to_int64 );
444 break;
445 case FLOAT32_TO_INT64_ROUND_TO_ZERO:
446 test_a_float32_z_int64(
447 slow_float32_to_int64_round_to_zero,
448 float32_to_int64_round_to_zero
449 );
450 break;
451 #endif
452 case FLOAT32_TO_FLOAT64:
453 test_a_float32_z_float64(
454 slow_float32_to_float64, float32_to_float64 );
455 break;
456 #ifdef FLOATX80
457 case FLOAT32_TO_FLOATX80:
458 test_a_float32_z_floatx80(
459 slow_float32_to_floatx80, float32_to_floatx80 );
460 break;
461 #endif
462 #ifdef FLOAT128
463 case FLOAT32_TO_FLOAT128:
464 test_a_float32_z_float128(
465 slow_float32_to_float128, float32_to_float128 );
466 break;
467 #endif
468 case FLOAT32_ROUND_TO_INT:
469 test_az_float32( slow_float32_round_to_int, float32_round_to_int );
470 break;
471 case FLOAT32_ADD:
472 test_abz_float32( slow_float32_add, float32_add );
473 break;
474 case FLOAT32_SUB:
475 test_abz_float32( slow_float32_sub, float32_sub );
476 break;
477 case FLOAT32_MUL:
478 test_abz_float32( slow_float32_mul, float32_mul );
479 break;
480 case FLOAT32_DIV:
481 test_abz_float32( slow_float32_div, float32_div );
482 break;
483 case FLOAT32_REM:
484 test_abz_float32( slow_float32_rem, float32_rem );
485 break;
486 case FLOAT32_SQRT:
487 test_az_float32( slow_float32_sqrt, float32_sqrt );
488 break;
489 case FLOAT32_EQ:
490 test_ab_float32_z_flag( slow_float32_eq, float32_eq );
491 break;
492 case FLOAT32_LE:
493 test_ab_float32_z_flag( slow_float32_le, float32_le );
494 break;
495 case FLOAT32_LT:
496 test_ab_float32_z_flag( slow_float32_lt, float32_lt );
497 break;
498 case FLOAT32_EQ_SIGNALING:
499 test_ab_float32_z_flag(
500 slow_float32_eq_signaling, float32_eq_signaling );
501 break;
502 case FLOAT32_LE_QUIET:
503 test_ab_float32_z_flag( slow_float32_le_quiet, float32_le_quiet );
504 break;
505 case FLOAT32_LT_QUIET:
506 test_ab_float32_z_flag( slow_float32_lt_quiet, float32_lt_quiet );
507 break;
508 case FLOAT64_TO_INT32:
509 test_a_float64_z_int32( slow_float64_to_int32, float64_to_int32 );
510 break;
511 case FLOAT64_TO_INT32_ROUND_TO_ZERO:
512 test_a_float64_z_int32(
513 slow_float64_to_int32_round_to_zero,
514 float64_to_int32_round_to_zero
515 );
516 break;
517 #ifdef BITS64
518 case FLOAT64_TO_INT64:
519 test_a_float64_z_int64( slow_float64_to_int64, float64_to_int64 );
520 break;
521 case FLOAT64_TO_INT64_ROUND_TO_ZERO:
522 test_a_float64_z_int64(
523 slow_float64_to_int64_round_to_zero,
524 float64_to_int64_round_to_zero
525 );
526 break;
527 #endif
528 case FLOAT64_TO_FLOAT32:
529 test_a_float64_z_float32(
530 slow_float64_to_float32, float64_to_float32 );
531 break;
532 #ifdef FLOATX80
533 case FLOAT64_TO_FLOATX80:
534 test_a_float64_z_floatx80(
535 slow_float64_to_floatx80, float64_to_floatx80 );
536 break;
537 #endif
538 #ifdef FLOAT128
539 case FLOAT64_TO_FLOAT128:
540 test_a_float64_z_float128(
541 slow_float64_to_float128, float64_to_float128 );
542 break;
543 #endif
544 case FLOAT64_ROUND_TO_INT:
545 test_az_float64( slow_float64_round_to_int, float64_round_to_int );
546 break;
547 case FLOAT64_ADD:
548 test_abz_float64( slow_float64_add, float64_add );
549 break;
550 case FLOAT64_SUB:
551 test_abz_float64( slow_float64_sub, float64_sub );
552 break;
553 case FLOAT64_MUL:
554 test_abz_float64( slow_float64_mul, float64_mul );
555 break;
556 case FLOAT64_DIV:
557 test_abz_float64( slow_float64_div, float64_div );
558 break;
559 case FLOAT64_REM:
560 test_abz_float64( slow_float64_rem, float64_rem );
561 break;
562 case FLOAT64_SQRT:
563 test_az_float64( slow_float64_sqrt, float64_sqrt );
564 break;
565 case FLOAT64_EQ:
566 test_ab_float64_z_flag( slow_float64_eq, float64_eq );
567 break;
568 case FLOAT64_LE:
569 test_ab_float64_z_flag( slow_float64_le, float64_le );
570 break;
571 case FLOAT64_LT:
572 test_ab_float64_z_flag( slow_float64_lt, float64_lt );
573 break;
574 case FLOAT64_EQ_SIGNALING:
575 test_ab_float64_z_flag(
576 slow_float64_eq_signaling, float64_eq_signaling );
577 break;
578 case FLOAT64_LE_QUIET:
579 test_ab_float64_z_flag( slow_float64_le_quiet, float64_le_quiet );
580 break;
581 case FLOAT64_LT_QUIET:
582 test_ab_float64_z_flag( slow_float64_lt_quiet, float64_lt_quiet );
583 break;
584 #ifdef FLOATX80
585 case FLOATX80_TO_INT32:
586 test_a_floatx80_z_int32( slow_floatx80_to_int32, floatx80_to_int32 );
587 break;
588 case FLOATX80_TO_INT32_ROUND_TO_ZERO:
589 test_a_floatx80_z_int32(
590 slow_floatx80_to_int32_round_to_zero,
591 floatx80_to_int32_round_to_zero
592 );
593 break;
594 #ifdef BITS64
595 case FLOATX80_TO_INT64:
596 test_a_floatx80_z_int64( slow_floatx80_to_int64, floatx80_to_int64 );
597 break;
598 case FLOATX80_TO_INT64_ROUND_TO_ZERO:
599 test_a_floatx80_z_int64(
600 slow_floatx80_to_int64_round_to_zero,
601 floatx80_to_int64_round_to_zero
602 );
603 break;
604 #endif
605 case FLOATX80_TO_FLOAT32:
606 test_a_floatx80_z_float32(
607 slow_floatx80_to_float32, floatx80_to_float32 );
608 break;
609 case FLOATX80_TO_FLOAT64:
610 test_a_floatx80_z_float64(
611 slow_floatx80_to_float64, floatx80_to_float64 );
612 break;
613 #ifdef FLOAT128
614 case FLOATX80_TO_FLOAT128:
615 test_a_floatx80_z_float128(
616 slow_floatx80_to_float128, floatx80_to_float128 );
617 break;
618 #endif
619 case FLOATX80_ROUND_TO_INT:
620 test_az_floatx80( slow_floatx80_round_to_int, floatx80_round_to_int );
621 break;
622 case FLOATX80_ADD:
623 test_abz_floatx80( slow_floatx80_add, floatx80_add );
624 break;
625 case FLOATX80_SUB:
626 test_abz_floatx80( slow_floatx80_sub, floatx80_sub );
627 break;
628 case FLOATX80_MUL:
629 test_abz_floatx80( slow_floatx80_mul, floatx80_mul );
630 break;
631 case FLOATX80_DIV:
632 test_abz_floatx80( slow_floatx80_div, floatx80_div );
633 break;
634 case FLOATX80_REM:
635 test_abz_floatx80( slow_floatx80_rem, floatx80_rem );
636 break;
637 case FLOATX80_SQRT:
638 test_az_floatx80( slow_floatx80_sqrt, floatx80_sqrt );
639 break;
640 case FLOATX80_EQ:
641 test_ab_floatx80_z_flag( slow_floatx80_eq, floatx80_eq );
642 break;
643 case FLOATX80_LE:
644 test_ab_floatx80_z_flag( slow_floatx80_le, floatx80_le );
645 break;
646 case FLOATX80_LT:
647 test_ab_floatx80_z_flag( slow_floatx80_lt, floatx80_lt );
648 break;
649 case FLOATX80_EQ_SIGNALING:
650 test_ab_floatx80_z_flag(
651 slow_floatx80_eq_signaling, floatx80_eq_signaling );
652 break;
653 case FLOATX80_LE_QUIET:
654 test_ab_floatx80_z_flag( slow_floatx80_le_quiet, floatx80_le_quiet );
655 break;
656 case FLOATX80_LT_QUIET:
657 test_ab_floatx80_z_flag( slow_floatx80_lt_quiet, floatx80_lt_quiet );
658 break;
659 #endif
660 #ifdef FLOAT128
661 case FLOAT128_TO_INT32:
662 test_a_float128_z_int32( slow_float128_to_int32, float128_to_int32 );
663 break;
664 case FLOAT128_TO_INT32_ROUND_TO_ZERO:
665 test_a_float128_z_int32(
666 slow_float128_to_int32_round_to_zero,
667 float128_to_int32_round_to_zero
668 );
669 break;
670 #ifdef BITS64
671 case FLOAT128_TO_INT64:
672 test_a_float128_z_int64( slow_float128_to_int64, float128_to_int64 );
673 break;
674 case FLOAT128_TO_INT64_ROUND_TO_ZERO:
675 test_a_float128_z_int64(
676 slow_float128_to_int64_round_to_zero,
677 float128_to_int64_round_to_zero
678 );
679 break;
680 #endif
681 case FLOAT128_TO_FLOAT32:
682 test_a_float128_z_float32(
683 slow_float128_to_float32, float128_to_float32 );
684 break;
685 case FLOAT128_TO_FLOAT64:
686 test_a_float128_z_float64(
687 slow_float128_to_float64, float128_to_float64 );
688 break;
689 #ifdef FLOATX80
690 case FLOAT128_TO_FLOATX80:
691 test_a_float128_z_floatx80(
692 slow_float128_to_floatx80, float128_to_floatx80 );
693 break;
694 #endif
695 case FLOAT128_ROUND_TO_INT:
696 test_az_float128( slow_float128_round_to_int, float128_round_to_int );
697 break;
698 case FLOAT128_ADD:
699 test_abz_float128( slow_float128_add, float128_add );
700 break;
701 case FLOAT128_SUB:
702 test_abz_float128( slow_float128_sub, float128_sub );
703 break;
704 case FLOAT128_MUL:
705 test_abz_float128( slow_float128_mul, float128_mul );
706 break;
707 case FLOAT128_DIV:
708 test_abz_float128( slow_float128_div, float128_div );
709 break;
710 case FLOAT128_REM:
711 test_abz_float128( slow_float128_rem, float128_rem );
712 break;
713 case FLOAT128_SQRT:
714 test_az_float128( slow_float128_sqrt, float128_sqrt );
715 break;
716 case FLOAT128_EQ:
717 test_ab_float128_z_flag( slow_float128_eq, float128_eq );
718 break;
719 case FLOAT128_LE:
720 test_ab_float128_z_flag( slow_float128_le, float128_le );
721 break;
722 case FLOAT128_LT:
723 test_ab_float128_z_flag( slow_float128_lt, float128_lt );
724 break;
725 case FLOAT128_EQ_SIGNALING:
726 test_ab_float128_z_flag(
727 slow_float128_eq_signaling, float128_eq_signaling );
728 break;
729 case FLOAT128_LE_QUIET:
730 test_ab_float128_z_flag( slow_float128_le_quiet, float128_le_quiet );
731 break;
732 case FLOAT128_LT_QUIET:
733 test_ab_float128_z_flag( slow_float128_lt_quiet, float128_lt_quiet );
734 break;
735 #endif
736 }
737 if ( ( errorStop && anyErrors ) || stop ) exitWithStatus();
738
739 }
740
741 static void
testFunction(uint8 functionCode,int8 roundingPrecisionIn,int8 roundingModeIn,int8 tininessModeIn)742 testFunction(
743 uint8 functionCode,
744 int8 roundingPrecisionIn,
745 int8 roundingModeIn,
746 int8 tininessModeIn
747 )
748 {
749 int8 roundingPrecision, roundingMode, tininessMode;
750
751 roundingPrecision = 32;
752 for (;;) {
753 if ( ! functions[ functionCode ].roundingPrecision ) {
754 roundingPrecision = 0;
755 }
756 else if ( roundingPrecisionIn ) {
757 roundingPrecision = roundingPrecisionIn;
758 }
759 for ( roundingMode = 1;
760 roundingMode < NUM_ROUNDINGMODES;
761 ++roundingMode
762 ) {
763 if ( ! functions[ functionCode ].roundingMode ) {
764 roundingMode = 0;
765 }
766 else if ( roundingModeIn ) {
767 roundingMode = roundingModeIn;
768 }
769 for ( tininessMode = 1;
770 tininessMode < NUM_TININESSMODES;
771 ++tininessMode
772 ) {
773 if ( ( roundingPrecision == 32 )
774 || ( roundingPrecision == 64 ) ) {
775 if ( ! functions[ functionCode ]
776 .tininessModeAtReducedPrecision
777 ) {
778 tininessMode = 0;
779 }
780 else if ( tininessModeIn ) {
781 tininessMode = tininessModeIn;
782 }
783 }
784 else {
785 if ( ! functions[ functionCode ].tininessMode ) {
786 tininessMode = 0;
787 }
788 else if ( tininessModeIn ) {
789 tininessMode = tininessModeIn;
790 }
791 }
792 testFunctionVariety(
793 functionCode, roundingPrecision, roundingMode, tininessMode
794 );
795 if ( tininessModeIn || ! tininessMode ) break;
796 }
797 if ( roundingModeIn || ! roundingMode ) break;
798 }
799 if ( roundingPrecisionIn || ! roundingPrecision ) break;
800 if ( roundingPrecision == 80 ) {
801 break;
802 }
803 else if ( roundingPrecision == 64 ) {
804 roundingPrecision = 80;
805 }
806 else if ( roundingPrecision == 32 ) {
807 roundingPrecision = 64;
808 }
809 }
810
811 }
812
813 int
main(int argc,char ** argv)814 main( int argc, char **argv )
815 {
816 char *argPtr;
817 flag functionArgument;
818 uint8 functionCode;
819 int8 operands, roundingPrecision, roundingMode, tininessMode;
820
821 fail_programName = "testsoftfloat";
822 if ( argc <= 1 ) goto writeHelpMessage;
823 testCases_setLevel( 1 );
824 trueName = "true";
825 testName = "soft";
826 errorStop = FALSE;
827 forever = FALSE;
828 maxErrorCount = 20;
829 trueFlagsPtr = &slow_float_exception_flags;
830 testFlagsFunctionPtr = clearFlags;
831 functionArgument = FALSE;
832 functionCode = 0;
833 operands = 0;
834 roundingPrecision = 0;
835 roundingMode = 0;
836 tininessMode = 0;
837 --argc;
838 ++argv;
839 while ( argc && ( argPtr = argv[ 0 ] ) ) {
840 if ( argPtr[ 0 ] == '-' ) ++argPtr;
841 if ( strcmp( argPtr, "help" ) == 0 ) {
842 writeHelpMessage:
843 fputs(
844 "testsoftfloat [<option>...] <function>\n"
845 " <option>: (* is default)\n"
846 " -help --Write this message and exit.\n"
847 " -level <num> --Testing level <num> (1 or 2).\n"
848 " * -level 1\n"
849 " -errors <num> --Stop each function test after <num> errors.\n"
850 " * -errors 20\n"
851 " -errorstop --Exit after first function with any error.\n"
852 " -forever --Test one function repeatedly (implies `-level 2').\n"
853 #ifdef FLOATX80
854 " -precision32 --Only test rounding precision equivalent to float32.\n"
855 " -precision64 --Only test rounding precision equivalent to float64.\n"
856 " -precision80 --Only test maximum rounding precision.\n"
857 #endif
858 " -nearesteven --Only test rounding to nearest/even.\n"
859 " -tozero --Only test rounding to zero.\n"
860 " -down --Only test rounding down.\n"
861 " -up --Only test rounding up.\n"
862 " -tininessbefore --Only test underflow tininess before rounding.\n"
863 " -tininessafter --Only test underflow tininess after rounding.\n"
864 " <function>:\n"
865 " int32_to_<float> <float>_add <float>_eq\n"
866 " <float>_to_int32 <float>_sub <float>_le\n"
867 " <float>_to_int32_round_to_zero <float>_mul <float>_lt\n"
868 #ifdef BITS64
869 " int64_to_<float> <float>_div <float>_eq_signaling\n"
870 " <float>_to_int64 <float>_rem <float>_le_quiet\n"
871 " <float>_to_int64_round_to_zero <float>_lt_quiet\n"
872 " <float>_to_<float>\n"
873 " <float>_round_to_int\n"
874 " <float>_sqrt\n"
875 #else
876 " <float>_to_<float> <float>_div <float>_eq_signaling\n"
877 " <float>_round_to_int <float>_rem <float>_le_quiet\n"
878 " <float>_sqrt <float>_lt_quiet\n"
879 #endif
880 " -all1 --All 1-operand functions.\n"
881 " -all2 --All 2-operand functions.\n"
882 " -all --All functions.\n"
883 " <float>:\n"
884 " float32 --Single precision.\n"
885 " float64 --Double precision.\n"
886 #ifdef FLOATX80
887 " floatx80 --Extended double precision.\n"
888 #endif
889 #ifdef FLOAT128
890 " float128 --Quadruple precision.\n"
891 #endif
892 ,
893 stdout
894 );
895 return EXIT_SUCCESS;
896 }
897 else if ( strcmp( argPtr, "level" ) == 0 ) {
898 if ( argc < 2 ) goto optionError;
899 testCases_setLevel( atoi( argv[ 1 ] ) );
900 --argc;
901 ++argv;
902 }
903 else if ( strcmp( argPtr, "level1" ) == 0 ) {
904 testCases_setLevel( 1 );
905 }
906 else if ( strcmp( argPtr, "level2" ) == 0 ) {
907 testCases_setLevel( 2 );
908 }
909 else if ( strcmp( argPtr, "errors" ) == 0 ) {
910 if ( argc < 2 ) {
911 optionError:
912 fail( "`%s' option requires numeric argument", argv[ 0 ] );
913 }
914 maxErrorCount = atoi( argv[ 1 ] );
915 --argc;
916 ++argv;
917 }
918 else if ( strcmp( argPtr, "errorstop" ) == 0 ) {
919 errorStop = TRUE;
920 }
921 else if ( strcmp( argPtr, "forever" ) == 0 ) {
922 testCases_setLevel( 2 );
923 forever = TRUE;
924 }
925 #ifdef FLOATX80
926 else if ( strcmp( argPtr, "precision32" ) == 0 ) {
927 roundingPrecision = 32;
928 }
929 else if ( strcmp( argPtr, "precision64" ) == 0 ) {
930 roundingPrecision = 64;
931 }
932 else if ( strcmp( argPtr, "precision80" ) == 0 ) {
933 roundingPrecision = 80;
934 }
935 #endif
936 else if ( ( strcmp( argPtr, "nearesteven" ) == 0 )
937 || ( strcmp( argPtr, "nearest_even" ) == 0 ) ) {
938 roundingMode = ROUND_NEAREST_EVEN;
939 }
940 else if ( ( strcmp( argPtr, "tozero" ) == 0 )
941 || ( strcmp( argPtr, "to_zero" ) == 0 ) ) {
942 roundingMode = ROUND_TO_ZERO;
943 }
944 else if ( strcmp( argPtr, "down" ) == 0 ) {
945 roundingMode = ROUND_DOWN;
946 }
947 else if ( strcmp( argPtr, "up" ) == 0 ) {
948 roundingMode = ROUND_UP;
949 }
950 else if ( strcmp( argPtr, "tininessbefore" ) == 0 ) {
951 tininessMode = TININESS_BEFORE_ROUNDING;
952 }
953 else if ( strcmp( argPtr, "tininessafter" ) == 0 ) {
954 tininessMode = TININESS_AFTER_ROUNDING;
955 }
956 else if ( strcmp( argPtr, "all1" ) == 0 ) {
957 functionArgument = TRUE;
958 functionCode = 0;
959 operands = 1;
960 }
961 else if ( strcmp( argPtr, "all2" ) == 0 ) {
962 functionArgument = TRUE;
963 functionCode = 0;
964 operands = 2;
965 }
966 else if ( strcmp( argPtr, "all" ) == 0 ) {
967 functionArgument = TRUE;
968 functionCode = 0;
969 operands = 0;
970 }
971 else {
972 for ( functionCode = 1;
973 functionCode < NUM_FUNCTIONS;
974 ++functionCode
975 ) {
976 if ( strcmp( argPtr, functions[ functionCode ].name ) == 0 ) {
977 break;
978 }
979 }
980 if ( functionCode == NUM_FUNCTIONS ) {
981 fail( "Invalid option or function `%s'", argv[ 0 ] );
982 }
983 functionArgument = TRUE;
984 }
985 --argc;
986 ++argv;
987 }
988 if ( ! functionArgument ) fail( "Function argument required" );
989 (void) signal( SIGINT, catchSIGINT );
990 (void) signal( SIGTERM, catchSIGINT );
991 if ( functionCode ) {
992 if ( forever ) {
993 if ( ! roundingPrecision ) roundingPrecision = 80;
994 if ( ! roundingMode ) roundingMode = ROUND_NEAREST_EVEN;
995 }
996 testFunction(
997 functionCode, roundingPrecision, roundingMode, tininessMode );
998 }
999 else {
1000 if ( operands == 1 ) {
1001 for ( functionCode = 1;
1002 functionCode < NUM_FUNCTIONS;
1003 ++functionCode
1004 ) {
1005 if ( functions[ functionCode ].numInputs == 1 ) {
1006 testFunction(
1007 functionCode,
1008 roundingPrecision,
1009 roundingMode,
1010 tininessMode
1011 );
1012 }
1013 }
1014 }
1015 else if ( operands == 2 ) {
1016 for ( functionCode = 1;
1017 functionCode < NUM_FUNCTIONS;
1018 ++functionCode
1019 ) {
1020 if ( functions[ functionCode ].numInputs == 2 ) {
1021 testFunction(
1022 functionCode,
1023 roundingPrecision,
1024 roundingMode,
1025 tininessMode
1026 );
1027 }
1028 }
1029 }
1030 else {
1031 for ( functionCode = 1;
1032 functionCode < NUM_FUNCTIONS;
1033 ++functionCode
1034 ) {
1035 testFunction(
1036 functionCode, roundingPrecision, roundingMode, tininessMode
1037 );
1038 }
1039 }
1040 }
1041 exitWithStatus();
1042
1043 }
1044
1045