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