1 
2 /*============================================================================
3 
4 This C source file is part of TestFloat, Release 3e, a package of programs for
5 testing the correctness of floating-point arithmetic complying with the IEEE
6 Standard for Floating-Point, by John R. Hauser.
7 
8 Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
9 All rights reserved.
10 
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions are met:
13 
14  1. Redistributions of source code must retain the above copyright notice,
15     this list of conditions, and the following disclaimer.
16 
17  2. Redistributions in binary form must reproduce the above copyright notice,
18     this list of conditions, and the following disclaimer in the documentation
19     and/or other materials provided with the distribution.
20 
21  3. Neither the name of the University nor the names of its contributors may
22     be used to endorse or promote products derived from this software without
23     specific prior written permission.
24 
25 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
26 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
28 DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
29 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 
36 =============================================================================*/
37 
38 #include <stdbool.h>
39 #include <stdint.h>
40 #include "platform.h"
41 #include "random.h"
42 #include "softfloat.h"
43 #include "genCases.h"
44 
45 struct sequence {
46     int expNum, term1Num, term2Num;
47     bool done;
48 };
49 
50 union ui32_f32 { uint32_t ui; float32_t f; };
51 
52 enum {
53     f32NumQIn  = 22,
54     f32NumQOut = 50,
55     f32NumP1   =  4,
56     f32NumP2   = 88
57 };
58 static const uint32_t f32QIn[f32NumQIn] = {
59     0x00000000,    /* positive, subnormal       */
60     0x00800000,    /* positive, -126            */
61     0x33800000,    /* positive,  -24            */
62     0x3E800000,    /* positive,   -2            */
63     0x3F000000,    /* positive,   -1            */
64     0x3F800000,    /* positive,    0            */
65     0x40000000,    /* positive,    1            */
66     0x40800000,    /* positive,    2            */
67     0x4B800000,    /* positive,   24            */
68     0x7F000000,    /* positive,  127            */
69     0x7F800000,    /* positive, infinity or NaN */
70     0x80000000,    /* negative, subnormal       */
71     0x80800000,    /* negative, -126            */
72     0xB3800000,    /* negative,  -24            */
73     0xBE800000,    /* negative,   -2            */
74     0xBF000000,    /* negative,   -1            */
75     0xBF800000,    /* negative,    0            */
76     0xC0000000,    /* negative,    1            */
77     0xC0800000,    /* negative,    2            */
78     0xCB800000,    /* negative,   24            */
79     0xFE800000,    /* negative,  126            */
80     0xFF800000     /* negative, infinity or NaN */
81 };
82 static const uint32_t f32QOut[f32NumQOut] = {
83     0x00000000,    /* positive, subnormal       */
84     0x00800000,    /* positive, -126            */
85     0x01000000,    /* positive, -125            */
86     0x33800000,    /* positive,  -24            */
87     0x3D800000,    /* positive,   -4            */
88     0x3E000000,    /* positive,   -3            */
89     0x3E800000,    /* positive,   -2            */
90     0x3F000000,    /* positive,   -1            */
91     0x3F800000,    /* positive,    0            */
92     0x40000000,    /* positive,    1            */
93     0x40800000,    /* positive,    2            */
94     0x41000000,    /* positive,    3            */
95     0x41800000,    /* positive,    4            */
96     0x4B800000,    /* positive,   24            */
97     0x4E000000,    /* positive,   29            */
98     0x4E800000,    /* positive,   30            */
99     0x4F000000,    /* positive,   31            */
100     0x4F800000,    /* positive,   32            */
101     0x5E000000,    /* positive,   61            */
102     0x5E800000,    /* positive,   62            */
103     0x5F000000,    /* positive,   63            */
104     0x5F800000,    /* positive,   64            */
105     0x7E800000,    /* positive,  126            */
106     0x7F000000,    /* positive,  127            */
107     0x7F800000,    /* positive, infinity or NaN */
108     0x80000000,    /* negative, subnormal       */
109     0x80800000,    /* negative, -126            */
110     0x81000000,    /* negative, -125            */
111     0xB3800000,    /* negative,  -24            */
112     0xBD800000,    /* negative,   -4            */
113     0xBE000000,    /* negative,   -3            */
114     0xBE800000,    /* negative,   -2            */
115     0xBF000000,    /* negative,   -1            */
116     0xBF800000,    /* negative,    0            */
117     0xC0000000,    /* negative,    1            */
118     0xC0800000,    /* negative,    2            */
119     0xC1000000,    /* negative,    3            */
120     0xC1800000,    /* negative,    4            */
121     0xCB800000,    /* negative,   24            */
122     0xCE000000,    /* negative,   29            */
123     0xCE800000,    /* negative,   30            */
124     0xCF000000,    /* negative,   31            */
125     0xCF800000,    /* negative,   32            */
126     0xDE000000,    /* negative,   61            */
127     0xDE800000,    /* negative,   62            */
128     0xDF000000,    /* negative,   63            */
129     0xDF800000,    /* negative,   64            */
130     0xFE800000,    /* negative,  126            */
131     0xFF000000,    /* negative,  127            */
132     0xFF800000     /* negative, infinity or NaN */
133 };
134 static const uint32_t f32P1[f32NumP1] = {
135     0x00000000,
136     0x00000001,
137     0x007FFFFF,
138     0x007FFFFE
139 };
140 static const uint32_t f32P2[f32NumP2] = {
141     0x00000000,
142     0x00000001,
143     0x00000002,
144     0x00000004,
145     0x00000008,
146     0x00000010,
147     0x00000020,
148     0x00000040,
149     0x00000080,
150     0x00000100,
151     0x00000200,
152     0x00000400,
153     0x00000800,
154     0x00001000,
155     0x00002000,
156     0x00004000,
157     0x00008000,
158     0x00010000,
159     0x00020000,
160     0x00040000,
161     0x00080000,
162     0x00100000,
163     0x00200000,
164     0x00400000,
165     0x00600000,
166     0x00700000,
167     0x00780000,
168     0x007C0000,
169     0x007E0000,
170     0x007F0000,
171     0x007F8000,
172     0x007FC000,
173     0x007FE000,
174     0x007FF000,
175     0x007FF800,
176     0x007FFC00,
177     0x007FFE00,
178     0x007FFF00,
179     0x007FFF80,
180     0x007FFFC0,
181     0x007FFFE0,
182     0x007FFFF0,
183     0x007FFFF8,
184     0x007FFFFC,
185     0x007FFFFE,
186     0x007FFFFF,
187     0x007FFFFD,
188     0x007FFFFB,
189     0x007FFFF7,
190     0x007FFFEF,
191     0x007FFFDF,
192     0x007FFFBF,
193     0x007FFF7F,
194     0x007FFEFF,
195     0x007FFDFF,
196     0x007FFBFF,
197     0x007FF7FF,
198     0x007FEFFF,
199     0x007FDFFF,
200     0x007FBFFF,
201     0x007F7FFF,
202     0x007EFFFF,
203     0x007DFFFF,
204     0x007BFFFF,
205     0x0077FFFF,
206     0x006FFFFF,
207     0x005FFFFF,
208     0x003FFFFF,
209     0x001FFFFF,
210     0x000FFFFF,
211     0x0007FFFF,
212     0x0003FFFF,
213     0x0001FFFF,
214     0x0000FFFF,
215     0x00007FFF,
216     0x00003FFF,
217     0x00001FFF,
218     0x00000FFF,
219     0x000007FF,
220     0x000003FF,
221     0x000001FF,
222     0x000000FF,
223     0x0000007F,
224     0x0000003F,
225     0x0000001F,
226     0x0000000F,
227     0x00000007,
228     0x00000003
229 };
230 
231 static const uint_fast64_t f32NumQInP1 = f32NumQIn * f32NumP1;
232 static const uint_fast64_t f32NumQOutP1 = f32NumQOut * f32NumP1;
233 
f32NextQInP1(struct sequence * sequencePtr)234 static float32_t f32NextQInP1( struct sequence *sequencePtr )
235 {
236     int expNum, sigNum;
237     union ui32_f32 uZ;
238 
239     expNum = sequencePtr->expNum;
240     sigNum = sequencePtr->term1Num;
241     uZ.ui = f32QIn[expNum] | f32P1[sigNum];
242     ++sigNum;
243     if ( f32NumP1 <= sigNum ) {
244         sigNum = 0;
245         ++expNum;
246         if ( f32NumQIn <= expNum ) {
247             expNum = 0;
248             sequencePtr->done = true;
249         }
250         sequencePtr->expNum = expNum;
251     }
252     sequencePtr->term1Num = sigNum;
253     return uZ.f;
254 
255 }
256 
f32NextQOutP1(struct sequence * sequencePtr)257 static float32_t f32NextQOutP1( struct sequence *sequencePtr )
258 {
259     int expNum, sigNum;
260     union ui32_f32 uZ;
261 
262     expNum = sequencePtr->expNum;
263     sigNum = sequencePtr->term1Num;
264     uZ.ui = f32QOut[expNum] | f32P1[sigNum];
265     ++sigNum;
266     if ( f32NumP1 <= sigNum ) {
267         sigNum = 0;
268         ++expNum;
269         if ( f32NumQOut <= expNum ) {
270             expNum = 0;
271             sequencePtr->done = true;
272         }
273         sequencePtr->expNum = expNum;
274     }
275     sequencePtr->term1Num = sigNum;
276     return uZ.f;
277 
278 }
279 
280 static const uint_fast64_t f32NumQInP2 = f32NumQIn * f32NumP2;
281 static const uint_fast64_t f32NumQOutP2 = f32NumQOut * f32NumP2;
282 
f32NextQInP2(struct sequence * sequencePtr)283 static float32_t f32NextQInP2( struct sequence *sequencePtr )
284 {
285     int expNum, sigNum;
286     union ui32_f32 uZ;
287 
288     expNum = sequencePtr->expNum;
289     sigNum = sequencePtr->term1Num;
290     uZ.ui = f32QIn[expNum] | f32P2[sigNum];
291     ++sigNum;
292     if ( f32NumP2 <= sigNum ) {
293         sigNum = 0;
294         ++expNum;
295         if ( f32NumQIn <= expNum ) {
296             expNum = 0;
297             sequencePtr->done = true;
298         }
299         sequencePtr->expNum = expNum;
300     }
301     sequencePtr->term1Num = sigNum;
302     return uZ.f;
303 
304 }
305 
f32NextQOutP2(struct sequence * sequencePtr)306 static float32_t f32NextQOutP2( struct sequence *sequencePtr )
307 {
308     int expNum, sigNum;
309     union ui32_f32 uZ;
310 
311     expNum = sequencePtr->expNum;
312     sigNum = sequencePtr->term1Num;
313     uZ.ui = f32QOut[expNum] | f32P2[sigNum];
314     ++sigNum;
315     if ( f32NumP2 <= sigNum ) {
316         sigNum = 0;
317         ++expNum;
318         if ( f32NumQOut <= expNum ) {
319             expNum = 0;
320             sequencePtr->done = true;
321         }
322         sequencePtr->expNum = expNum;
323     }
324     sequencePtr->term1Num = sigNum;
325     return uZ.f;
326 
327 }
328 
f32RandomQOutP3(void)329 static float32_t f32RandomQOutP3( void )
330 {
331     union ui32_f32 uZ;
332 
333     uZ.ui =
334           f32QOut[randomN_ui8( f32NumQOut )]
335         | ((f32P2[randomN_ui8( f32NumP2 )] + f32P2[randomN_ui8( f32NumP2 )])
336                & 0x007FFFFF);
337     return uZ.f;
338 
339 }
340 
f32RandomQOutPInf(void)341 static float32_t f32RandomQOutPInf( void )
342 {
343     union ui32_f32 uZ;
344 
345     uZ.ui = f32QOut[randomN_ui8( f32NumQOut )] | (random_ui32() & 0x007FFFFF);
346     return uZ.f;
347 
348 }
349 
350 enum { f32NumQInfWeightMasks = 7 };
351 static const uint32_t f32QInfWeightMasks[f32NumQInfWeightMasks] = {
352     0xFF800000,
353     0xFF800000,
354     0xBF800000,
355     0x9F800000,
356     0x8F800000,
357     0x87800000,
358     0x83800000
359 };
360 static const uint32_t f32QInfWeightOffsets[f32NumQInfWeightMasks] = {
361     0x00000000,
362     0x00000000,
363     0x20000000,
364     0x30000000,
365     0x38000000,
366     0x3C000000,
367     0x3E000000
368 };
369 
f32RandomQInfP3(void)370 static float32_t f32RandomQInfP3( void )
371 {
372     int weightMaskNum;
373     union ui32_f32 uZ;
374 
375     weightMaskNum = randomN_ui8( f32NumQInfWeightMasks );
376     uZ.ui =
377           (((uint_fast32_t) random_ui16()<<16
378                 & f32QInfWeightMasks[weightMaskNum])
379                + f32QInfWeightOffsets[weightMaskNum])
380         | ((f32P2[randomN_ui8( f32NumP2 )] + f32P2[randomN_ui8( f32NumP2 )])
381                & 0x007FFFFF);
382     return uZ.f;
383 
384 }
385 
f32RandomQInfPInf(void)386 static float32_t f32RandomQInfPInf( void )
387 {
388     int weightMaskNum;
389     union ui32_f32 uZ;
390 
391     weightMaskNum = randomN_ui8( f32NumQInfWeightMasks );
392     uZ.ui =
393         (random_ui32() & (f32QInfWeightMasks[weightMaskNum] | 0x007FFFFF))
394             + f32QInfWeightOffsets[weightMaskNum];
395     return uZ.f;
396 
397 }
398 
f32Random(void)399 static float32_t f32Random( void )
400 {
401 
402     switch ( random_ui8() & 7 ) {
403      case 0:
404      case 1:
405      case 2:
406         return f32RandomQOutP3();
407      case 3:
408         return f32RandomQOutPInf();
409      case 4:
410      case 5:
411      case 6:
412         return f32RandomQInfP3();
413      case 7:
414         return f32RandomQInfPInf();
415     }
416 
417 }
418 
419 static struct sequence sequenceA, sequenceB, sequenceC;
420 static float32_t currentA, currentB, currentC;
421 static int subcase;
422 
423 float32_t genCases_f32_a, genCases_f32_b, genCases_f32_c;
424 
genCases_f32_a_init(void)425 void genCases_f32_a_init( void )
426 {
427 
428     sequenceA.expNum = 0;
429     sequenceA.term1Num = 0;
430     sequenceA.term2Num = 0;
431     sequenceA.done = false;
432     subcase = 0;
433     genCases_total =
434         (genCases_level == 1) ? 3 * f32NumQOutP1 : 2 * f32NumQOutP2;
435     genCases_done = false;
436 
437 }
438 
genCases_f32_a_next(void)439 void genCases_f32_a_next( void )
440 {
441 
442     if ( genCases_level == 1 ) {
443         switch ( subcase ) {
444          case 0:
445          case 1:
446             genCases_f32_a = f32Random();
447             break;
448          case 2:
449             genCases_f32_a = f32NextQOutP1( &sequenceA );
450             genCases_done = sequenceA.done;
451             subcase = -1;
452             break;
453         }
454     } else {
455         switch ( subcase ) {
456          case 0:
457             genCases_f32_a = f32Random();
458             break;
459          case 1:
460             genCases_f32_a = f32NextQOutP2( &sequenceA );
461             genCases_done = sequenceA.done;
462             subcase = -1;
463             break;
464         }
465     }
466     ++subcase;
467 
468 }
469 
genCases_f32_ab_init(void)470 void genCases_f32_ab_init( void )
471 {
472 
473     sequenceA.expNum = 0;
474     sequenceA.term1Num = 0;
475     sequenceA.term2Num = 0;
476     sequenceA.done = false;
477     sequenceB.expNum = 0;
478     sequenceB.term1Num = 0;
479     sequenceB.term2Num = 0;
480     sequenceB.done = false;
481     subcase = 0;
482     if ( genCases_level == 1 ) {
483         genCases_total = 6 * f32NumQInP1 * f32NumQInP1;
484         currentA = f32NextQInP1( &sequenceA );
485     } else {
486         genCases_total = 2 * f32NumQInP2 * f32NumQInP2;
487         currentA = f32NextQInP2( &sequenceA );
488     }
489     genCases_done = false;
490 
491 }
492 
genCases_f32_ab_next(void)493 void genCases_f32_ab_next( void )
494 {
495 
496     if ( genCases_level == 1 ) {
497         switch ( subcase ) {
498          case 0:
499             if ( sequenceB.done ) {
500                 sequenceB.done = false;
501                 currentA = f32NextQInP1( &sequenceA );
502             }
503             currentB = f32NextQInP1( &sequenceB );
504          case 2:
505          case 4:
506             genCases_f32_a = f32Random();
507             genCases_f32_b = f32Random();
508             break;
509          case 1:
510             genCases_f32_a = currentA;
511             genCases_f32_b = f32Random();
512             break;
513          case 3:
514             genCases_f32_a = f32Random();
515             genCases_f32_b = currentB;
516             break;
517          case 5:
518             genCases_f32_a = currentA;
519             genCases_f32_b = currentB;
520             genCases_done = sequenceA.done & sequenceB.done;
521             subcase = -1;
522             break;
523         }
524     } else {
525         switch ( subcase ) {
526          case 0:
527             genCases_f32_a = f32Random();
528             genCases_f32_b = f32Random();
529             break;
530          case 1:
531             if ( sequenceB.done ) {
532                 sequenceB.done = false;
533                 currentA = f32NextQInP2( &sequenceA );
534             }
535             genCases_f32_a = currentA;
536             genCases_f32_b = f32NextQInP2( &sequenceB );
537             genCases_done = sequenceA.done & sequenceB.done;
538             subcase = -1;
539             break;
540         }
541     }
542     ++subcase;
543 
544 }
545 
genCases_f32_abc_init(void)546 void genCases_f32_abc_init( void )
547 {
548 
549     sequenceA.expNum = 0;
550     sequenceA.term1Num = 0;
551     sequenceA.term2Num = 0;
552     sequenceA.done = false;
553     sequenceB.expNum = 0;
554     sequenceB.term1Num = 0;
555     sequenceB.term2Num = 0;
556     sequenceB.done = false;
557     sequenceC.expNum = 0;
558     sequenceC.term1Num = 0;
559     sequenceC.term2Num = 0;
560     sequenceC.done = false;
561     subcase = 0;
562     if ( genCases_level == 1 ) {
563         genCases_total = 9 * f32NumQInP1 * f32NumQInP1 * f32NumQInP1;
564         currentA = f32NextQInP1( &sequenceA );
565         currentB = f32NextQInP1( &sequenceB );
566     } else {
567         genCases_total = 2 * f32NumQInP2 * f32NumQInP2 * f32NumQInP2;
568         currentA = f32NextQInP2( &sequenceA );
569         currentB = f32NextQInP2( &sequenceB );
570     }
571     genCases_done = false;
572 
573 }
574 
genCases_f32_abc_next(void)575 void genCases_f32_abc_next( void )
576 {
577 
578     if ( genCases_level == 1 ) {
579         switch ( subcase ) {
580          case 0:
581             if ( sequenceC.done ) {
582                 sequenceC.done = false;
583                 if ( sequenceB.done ) {
584                     sequenceB.done = false;
585                     currentA = f32NextQInP1( &sequenceA );
586                 }
587                 currentB = f32NextQInP1( &sequenceB );
588             }
589             currentC = f32NextQInP1( &sequenceC );
590             genCases_f32_a = f32Random();
591             genCases_f32_b = f32Random();
592             genCases_f32_c = currentC;
593             break;
594          case 1:
595             genCases_f32_a = currentA;
596             genCases_f32_b = currentB;
597             genCases_f32_c = f32Random();
598             break;
599          case 2:
600             genCases_f32_a = f32Random();
601             genCases_f32_b = f32Random();
602             genCases_f32_c = f32Random();
603             break;
604          case 3:
605             genCases_f32_a = f32Random();
606             genCases_f32_b = currentB;
607             genCases_f32_c = currentC;
608             break;
609          case 4:
610             genCases_f32_a = currentA;
611             genCases_f32_b = f32Random();
612             genCases_f32_c = f32Random();
613             break;
614          case 5:
615             genCases_f32_a = f32Random();
616             genCases_f32_b = currentB;
617             genCases_f32_c = f32Random();
618             break;
619          case 6:
620             genCases_f32_a = currentA;
621             genCases_f32_b = f32Random();
622             genCases_f32_c = currentC;
623             break;
624          case 7:
625             genCases_f32_a = f32Random();
626             genCases_f32_b = f32Random();
627             genCases_f32_c = f32Random();
628             break;
629          case 8:
630             genCases_f32_a = currentA;
631             genCases_f32_b = currentB;
632             genCases_f32_c = currentC;
633             genCases_done = sequenceA.done & sequenceB.done & sequenceC.done;
634             subcase = -1;
635             break;
636         }
637     } else {
638         switch ( subcase ) {
639          case 0:
640             genCases_f32_a = f32Random();
641             genCases_f32_b = f32Random();
642             genCases_f32_c = f32Random();
643             break;
644          case 1:
645             if ( sequenceC.done ) {
646                 sequenceC.done = false;
647                 if ( sequenceB.done ) {
648                     sequenceB.done = false;
649                     currentA = f32NextQInP2( &sequenceA );
650                 }
651                 currentB = f32NextQInP2( &sequenceB );
652             }
653             genCases_f32_a = currentA;
654             genCases_f32_b = currentB;
655             genCases_f32_c = f32NextQInP2( &sequenceC );
656             genCases_done = sequenceA.done & sequenceB.done & sequenceC.done;
657             subcase = -1;
658             break;
659         }
660     }
661     ++subcase;
662 
663 }
664 
665