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, 2015 The Regents of the University of
9 California.  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 #ifdef FLOAT16
46 
47 struct sequence {
48     int expNum, term1Num, term2Num;
49     bool done;
50 };
51 
52 union ui16_f16 { uint16_t ui; float16_t f; };
53 
54 enum {
55     f16NumQIn  = 22,
56     f16NumQOut = 34,
57     f16NumP1   =  4,
58     f16NumP2   = 36
59 };
60 static const uint16_t f16QIn[f16NumQIn] = {
61     0x0000,    /* positive, subnormal       */
62     0x0400,    /* positive, -14             */
63     0x1000,    /* positive, -11             */
64     0x3400,    /* positive,  -2             */
65     0x3800,    /* positive,  -1             */
66     0x3C00,    /* positive,   0             */
67     0x4000,    /* positive,   1             */
68     0x4400,    /* positive,   2             */
69     0x6800,    /* positive,  11             */
70     0x7800,    /* positive,  15             */
71     0x7C00,    /* positive, infinity or NaN */
72     0x8000,    /* negative, subnormal       */
73     0x8400,    /* negative, -14             */
74     0x9000,    /* negative, -11             */
75     0xB400,    /* negative,  -2             */
76     0xB800,    /* negative,  -1             */
77     0xBC00,    /* negative,   0             */
78     0xC000,    /* negative,   1             */
79     0xC400,    /* negative,   2             */
80     0xE800,    /* negative,  11             */
81     0xF800,    /* negative,  15             */
82     0xFC00     /* negative, infinity or NaN */
83 };
84 static const uint16_t f16QOut[f16NumQOut] = {
85     0x0000,    /* positive, subnormal       */
86     0x0400,    /* positive, -14             */
87     0x0800,    /* positive, -13             */
88     0x1000,    /* positive, -11             */
89     0x2C00,    /* positive,  -4             */
90     0x3000,    /* positive,  -3             */
91     0x3400,    /* positive,  -2             */
92     0x3800,    /* positive,  -1             */
93     0x3C00,    /* positive,   0             */
94     0x4000,    /* positive,   1             */
95     0x4400,    /* positive,   2             */
96     0x4800,    /* positive,   3             */
97     0x4C00,    /* positive,   4             */
98     0x6800,    /* positive,  11             */
99     0x7400,    /* positive,  14             */
100     0x7800,    /* positive,  15             */
101     0x7C00,    /* positive, infinity or NaN */
102     0x8000,    /* negative, subnormal       */
103     0x8400,    /* negative, -14             */
104     0x8800,    /* negative, -13             */
105     0x9000,    /* negative, -11             */
106     0xAC00,    /* negative,  -4             */
107     0xB000,    /* negative,  -3             */
108     0xB400,    /* negative,  -2             */
109     0xB800,    /* negative,  -1             */
110     0xBC00,    /* negative,   0             */
111     0xC000,    /* negative,   1             */
112     0xC400,    /* negative,   2             */
113     0xC800,    /* negative,   3             */
114     0xCC00,    /* negative,   4             */
115     0xE800,    /* negative,  11             */
116     0xF400,    /* negative,  14             */
117     0xF800,    /* negative,  15             */
118     0xFC00     /* negative, infinity or NaN */
119 };
120 static const uint16_t f16P1[f16NumP1] = {
121     0x0000,
122     0x0001,
123     0x03FF,
124     0x03FE
125 };
126 static const uint16_t f16P2[f16NumP2] = {
127     0x0000,
128     0x0001,
129     0x0002,
130     0x0004,
131     0x0008,
132     0x0010,
133     0x0020,
134     0x0040,
135     0x0080,
136     0x0100,
137     0x0200,
138     0x0300,
139     0x0380,
140     0x03C0,
141     0x03E0,
142     0x03F0,
143     0x03F8,
144     0x03FC,
145     0x03FE,
146     0x03FF,
147     0x03FD,
148     0x03FB,
149     0x03F7,
150     0x03EF,
151     0x03DF,
152     0x03BF,
153     0x037F,
154     0x02FF,
155     0x01FF,
156     0x00FF,
157     0x007F,
158     0x003F,
159     0x001F,
160     0x000F,
161     0x0007,
162     0x0003
163 };
164 
165 static const uint_fast64_t f16NumQInP1 = f16NumQIn * f16NumP1;
166 static const uint_fast64_t f16NumQOutP1 = f16NumQOut * f16NumP1;
167 
f16NextQInP1(struct sequence * sequencePtr)168 static float16_t f16NextQInP1( struct sequence *sequencePtr )
169 {
170     int expNum, sigNum;
171     union ui16_f16 uZ;
172 
173     expNum = sequencePtr->expNum;
174     sigNum = sequencePtr->term1Num;
175     uZ.ui = f16QIn[expNum] | f16P1[sigNum];
176     ++sigNum;
177     if ( f16NumP1 <= sigNum ) {
178         sigNum = 0;
179         ++expNum;
180         if ( f16NumQIn <= expNum ) {
181             expNum = 0;
182             sequencePtr->done = true;
183         }
184         sequencePtr->expNum = expNum;
185     }
186     sequencePtr->term1Num = sigNum;
187     return uZ.f;
188 
189 }
190 
f16NextQOutP1(struct sequence * sequencePtr)191 static float16_t f16NextQOutP1( struct sequence *sequencePtr )
192 {
193     int expNum, sigNum;
194     union ui16_f16 uZ;
195 
196     expNum = sequencePtr->expNum;
197     sigNum = sequencePtr->term1Num;
198     uZ.ui = f16QOut[expNum] | f16P1[sigNum];
199     ++sigNum;
200     if ( f16NumP1 <= sigNum ) {
201         sigNum = 0;
202         ++expNum;
203         if ( f16NumQOut <= expNum ) {
204             expNum = 0;
205             sequencePtr->done = true;
206         }
207         sequencePtr->expNum = expNum;
208     }
209     sequencePtr->term1Num = sigNum;
210     return uZ.f;
211 
212 }
213 
214 static const uint_fast64_t f16NumQInP2 = f16NumQIn * f16NumP2;
215 static const uint_fast64_t f16NumQOutP2 = f16NumQOut * f16NumP2;
216 
f16NextQInP2(struct sequence * sequencePtr)217 static float16_t f16NextQInP2( struct sequence *sequencePtr )
218 {
219     int expNum, sigNum;
220     union ui16_f16 uZ;
221 
222     expNum = sequencePtr->expNum;
223     sigNum = sequencePtr->term1Num;
224     uZ.ui = f16QIn[expNum] | f16P2[sigNum];
225     ++sigNum;
226     if ( f16NumP2 <= sigNum ) {
227         sigNum = 0;
228         ++expNum;
229         if ( f16NumQIn <= expNum ) {
230             expNum = 0;
231             sequencePtr->done = true;
232         }
233         sequencePtr->expNum = expNum;
234     }
235     sequencePtr->term1Num = sigNum;
236     return uZ.f;
237 
238 }
239 
f16NextQOutP2(struct sequence * sequencePtr)240 static float16_t f16NextQOutP2( struct sequence *sequencePtr )
241 {
242     int expNum, sigNum;
243     union ui16_f16 uZ;
244 
245     expNum = sequencePtr->expNum;
246     sigNum = sequencePtr->term1Num;
247     uZ.ui = f16QOut[expNum] | f16P2[sigNum];
248     ++sigNum;
249     if ( f16NumP2 <= sigNum ) {
250         sigNum = 0;
251         ++expNum;
252         if ( f16NumQOut <= expNum ) {
253             expNum = 0;
254             sequencePtr->done = true;
255         }
256         sequencePtr->expNum = expNum;
257     }
258     sequencePtr->term1Num = sigNum;
259     return uZ.f;
260 
261 }
262 
f16RandomQOutP3(void)263 static float16_t f16RandomQOutP3( void )
264 {
265     union ui16_f16 uZ;
266 
267     uZ.ui =
268           f16QOut[randomN_ui8( f16NumQOut )]
269         | ((f16P2[randomN_ui8( f16NumP2 )] + f16P2[randomN_ui8( f16NumP2 )])
270                & 0x03FF);
271     return uZ.f;
272 
273 }
274 
f16RandomQOutPInf(void)275 static float16_t f16RandomQOutPInf( void )
276 {
277     union ui16_f16 uZ;
278 
279     uZ.ui = f16QOut[randomN_ui8( f16NumQOut )] | (random_ui16() & 0x03FF);
280     return uZ.f;
281 
282 }
283 
284 enum { f16NumQInfWeightMasks = 4 };
285 static const uint16_t f16QInfWeightMasks[f16NumQInfWeightMasks] =
286     { 0xFC00, 0xFC00, 0xBC00, 0x9C00 };
287 static const uint16_t f16QInfWeightOffsets[f16NumQInfWeightMasks] =
288     { 0x0000, 0x0000, 0x2000, 0x3000 };
289 
f16RandomQInfP3(void)290 static float16_t f16RandomQInfP3( void )
291 {
292     int weightMaskNum;
293     union ui16_f16 uZ;
294 
295     weightMaskNum = randomN_ui8( f16NumQInfWeightMasks );
296     uZ.ui =
297           ((random_ui16() & f16QInfWeightMasks[weightMaskNum])
298                + f16QInfWeightOffsets[weightMaskNum])
299         | ((f16P2[randomN_ui8( f16NumP2 )] + f16P2[randomN_ui8( f16NumP2 )])
300                & 0x03FF);
301     return uZ.f;
302 
303 }
304 
f16RandomQInfPInf(void)305 static float16_t f16RandomQInfPInf( void )
306 {
307     int weightMaskNum;
308     union ui16_f16 uZ;
309 
310     weightMaskNum = randomN_ui8( f16NumQInfWeightMasks );
311     uZ.ui =
312         (random_ui16() & (f16QInfWeightMasks[weightMaskNum] | 0x03FF))
313             + f16QInfWeightOffsets[weightMaskNum];
314     return uZ.f;
315 
316 }
317 
f16Random(void)318 static float16_t f16Random( void )
319 {
320 
321     switch ( random_ui8() & 7 ) {
322      case 0:
323      case 1:
324      case 2:
325         return f16RandomQOutP3();
326      case 3:
327         return f16RandomQOutPInf();
328      case 4:
329      case 5:
330      case 6:
331         return f16RandomQInfP3();
332      case 7:
333         return f16RandomQInfPInf();
334     }
335 
336 }
337 
338 static struct sequence sequenceA, sequenceB, sequenceC;
339 static float16_t currentA, currentB, currentC;
340 static int subcase;
341 
342 float16_t genCases_f16_a, genCases_f16_b, genCases_f16_c;
343 
genCases_f16_a_init(void)344 void genCases_f16_a_init( void )
345 {
346 
347     sequenceA.expNum = 0;
348     sequenceA.term1Num = 0;
349     sequenceA.term2Num = 0;
350     sequenceA.done = false;
351     subcase = 0;
352     genCases_total =
353         (genCases_level == 1) ? 3 * f16NumQOutP1 : 2 * f16NumQOutP2;
354     genCases_done = false;
355 
356 }
357 
genCases_f16_a_next(void)358 void genCases_f16_a_next( void )
359 {
360 
361     if ( genCases_level == 1 ) {
362         switch ( subcase ) {
363          case 0:
364          case 1:
365             genCases_f16_a = f16Random();
366             break;
367          case 2:
368             genCases_f16_a = f16NextQOutP1( &sequenceA );
369             genCases_done = sequenceA.done;
370             subcase = -1;
371             break;
372         }
373     } else {
374         switch ( subcase ) {
375          case 0:
376             genCases_f16_a = f16Random();
377             break;
378          case 1:
379             genCases_f16_a = f16NextQOutP2( &sequenceA );
380             genCases_done = sequenceA.done;
381             subcase = -1;
382             break;
383         }
384     }
385     ++subcase;
386 
387 }
388 
genCases_f16_ab_init(void)389 void genCases_f16_ab_init( void )
390 {
391 
392     sequenceA.expNum = 0;
393     sequenceA.term1Num = 0;
394     sequenceA.term2Num = 0;
395     sequenceA.done = false;
396     sequenceB.expNum = 0;
397     sequenceB.term1Num = 0;
398     sequenceB.term2Num = 0;
399     sequenceB.done = false;
400     subcase = 0;
401     if ( genCases_level == 1 ) {
402         genCases_total = 6 * f16NumQInP1 * f16NumQInP1;
403         currentA = f16NextQInP1( &sequenceA );
404     } else {
405         genCases_total = 2 * f16NumQInP2 * f16NumQInP2;
406         currentA = f16NextQInP2( &sequenceA );
407     }
408     genCases_done = false;
409 
410 }
411 
genCases_f16_ab_next(void)412 void genCases_f16_ab_next( void )
413 {
414 
415     if ( genCases_level == 1 ) {
416         switch ( subcase ) {
417          case 0:
418             if ( sequenceB.done ) {
419                 sequenceB.done = false;
420                 currentA = f16NextQInP1( &sequenceA );
421             }
422             currentB = f16NextQInP1( &sequenceB );
423          case 2:
424          case 4:
425             genCases_f16_a = f16Random();
426             genCases_f16_b = f16Random();
427             break;
428          case 1:
429             genCases_f16_a = currentA;
430             genCases_f16_b = f16Random();
431             break;
432          case 3:
433             genCases_f16_a = f16Random();
434             genCases_f16_b = currentB;
435             break;
436          case 5:
437             genCases_f16_a = currentA;
438             genCases_f16_b = currentB;
439             genCases_done = sequenceA.done & sequenceB.done;
440             subcase = -1;
441             break;
442         }
443     } else {
444         switch ( subcase ) {
445          case 0:
446             genCases_f16_a = f16Random();
447             genCases_f16_b = f16Random();
448             break;
449          case 1:
450             if ( sequenceB.done ) {
451                 sequenceB.done = false;
452                 currentA = f16NextQInP2( &sequenceA );
453             }
454             genCases_f16_a = currentA;
455             genCases_f16_b = f16NextQInP2( &sequenceB );
456             genCases_done = sequenceA.done & sequenceB.done;
457             subcase = -1;
458             break;
459         }
460     }
461     ++subcase;
462 
463 }
464 
genCases_f16_abc_init(void)465 void genCases_f16_abc_init( void )
466 {
467 
468     sequenceA.expNum = 0;
469     sequenceA.term1Num = 0;
470     sequenceA.term2Num = 0;
471     sequenceA.done = false;
472     sequenceB.expNum = 0;
473     sequenceB.term1Num = 0;
474     sequenceB.term2Num = 0;
475     sequenceB.done = false;
476     sequenceC.expNum = 0;
477     sequenceC.term1Num = 0;
478     sequenceC.term2Num = 0;
479     sequenceC.done = false;
480     subcase = 0;
481     if ( genCases_level == 1 ) {
482         genCases_total = 9 * f16NumQInP1 * f16NumQInP1 * f16NumQInP1;
483         currentA = f16NextQInP1( &sequenceA );
484         currentB = f16NextQInP1( &sequenceB );
485     } else {
486         genCases_total = 2 * f16NumQInP2 * f16NumQInP2 * f16NumQInP2;
487         currentA = f16NextQInP2( &sequenceA );
488         currentB = f16NextQInP2( &sequenceB );
489     }
490     genCases_done = false;
491 
492 }
493 
genCases_f16_abc_next(void)494 void genCases_f16_abc_next( void )
495 {
496 
497     if ( genCases_level == 1 ) {
498         switch ( subcase ) {
499          case 0:
500             if ( sequenceC.done ) {
501                 sequenceC.done = false;
502                 if ( sequenceB.done ) {
503                     sequenceB.done = false;
504                     currentA = f16NextQInP1( &sequenceA );
505                 }
506                 currentB = f16NextQInP1( &sequenceB );
507             }
508             currentC = f16NextQInP1( &sequenceC );
509             genCases_f16_a = f16Random();
510             genCases_f16_b = f16Random();
511             genCases_f16_c = currentC;
512             break;
513          case 1:
514             genCases_f16_a = currentA;
515             genCases_f16_b = currentB;
516             genCases_f16_c = f16Random();
517             break;
518          case 2:
519             genCases_f16_a = f16Random();
520             genCases_f16_b = f16Random();
521             genCases_f16_c = f16Random();
522             break;
523          case 3:
524             genCases_f16_a = f16Random();
525             genCases_f16_b = currentB;
526             genCases_f16_c = currentC;
527             break;
528          case 4:
529             genCases_f16_a = currentA;
530             genCases_f16_b = f16Random();
531             genCases_f16_c = f16Random();
532             break;
533          case 5:
534             genCases_f16_a = f16Random();
535             genCases_f16_b = currentB;
536             genCases_f16_c = f16Random();
537             break;
538          case 6:
539             genCases_f16_a = currentA;
540             genCases_f16_b = f16Random();
541             genCases_f16_c = currentC;
542             break;
543          case 7:
544             genCases_f16_a = f16Random();
545             genCases_f16_b = f16Random();
546             genCases_f16_c = f16Random();
547             break;
548          case 8:
549             genCases_f16_a = currentA;
550             genCases_f16_b = currentB;
551             genCases_f16_c = currentC;
552             genCases_done = sequenceA.done & sequenceB.done & sequenceC.done;
553             subcase = -1;
554             break;
555         }
556     } else {
557         switch ( subcase ) {
558          case 0:
559             genCases_f16_a = f16Random();
560             genCases_f16_b = f16Random();
561             genCases_f16_c = f16Random();
562             break;
563          case 1:
564             if ( sequenceC.done ) {
565                 sequenceC.done = false;
566                 if ( sequenceB.done ) {
567                     sequenceB.done = false;
568                     currentA = f16NextQInP2( &sequenceA );
569                 }
570                 currentB = f16NextQInP2( &sequenceB );
571             }
572             genCases_f16_a = currentA;
573             genCases_f16_b = currentB;
574             genCases_f16_c = f16NextQInP2( &sequenceC );
575             genCases_done = sequenceA.done & sequenceB.done & sequenceC.done;
576             subcase = -1;
577             break;
578         }
579     }
580     ++subcase;
581 
582 }
583 
584 #endif
585 
586