1 #include <math.h> // isnormal
5 /* Conversion based on IEEE half-precision, as described in the IEEE 754-2008
6 standard and Arm Reference Manual 'A1.4.2 Half-precision floating-point
7 formats' where hardware capability supports __fp16 (VEX_HWCAPS_ARM64_FP16
8 and VEX_HWCAPS_ARM64_VFP16 set).
10 UInt
halfToSingleFPAsInt(UShort y
)
12 int s
= (y
>> 15) & 0x00000001; // Sign bit
13 int e
= (y
>> 10) & 0x0000001f; // Exponent
14 int f
= y
& 0x000003ff; // Fraction
16 // Handle +/- INF (7c00 and fc00 -INF) and +/-0
21 while (!(f
& 0x00000400)) {
30 return (s
<< 31) | 0x7f800000;
32 return (s
<< 31) | 0x7f800000 | (f
<< 13);
38 return ((s
<< 31) | (e
<< 23) | f
);
41 UChar
randUChar ( void )
43 static UInt seed
= 80021;
44 seed
= 1103515245 * seed
+ 12345;
45 return (seed
>> 17) & 0xFF;
48 /* Generates a random V128. Ensures that that it contains normalised FP numbers
49 when viewed as either F16x8, F32x4 or F64x2, so that it is reasonable to use
51 void randV128 ( /*OUT*/V128
* v
, LaneTy ty
)
53 static UInt nCalls
= 0, nIters
= 0;
58 for (i
= 0; i
< 16; i
++) {
59 v
->u8
[i
] = randUChar();
61 if (isnormal(v
->f32
[0]) && isnormal(v
->f32
[1]) && isnormal(v
->f32
[2])
62 && isnormal(v
->f32
[3]) && isnormal(v
->f64
[0]) && isnormal(v
->f64
[1])
63 && isnormal(shortToSingle(v
->f16
[0])) && isnormal(shortToSingle(v
->f16
[1]))
64 && isnormal(shortToSingle(v
->f16
[2])) && isnormal(shortToSingle(v
->f16
[3]))
65 && isnormal(shortToSingle(v
->f16
[4])) && isnormal(shortToSingle(v
->f16
[5]))
66 && isnormal(shortToSingle(v
->f16
[6])) && isnormal(shortToSingle(v
->f16
[7]))) {
70 if (0 == (nCalls
& 0xFF))
71 printf("randV128: %u calls, %u iters\n", nCalls
, nIters
);
74 static Double special_values
[10];
75 static Bool special_values_initted
= False
;
77 static __attribute__((noinline
))
78 Double
negate ( Double d
) { return -d
; }
79 static __attribute__((noinline
))
80 Double
divf64 ( Double x
, Double y
) { return x
/y
; }
82 static __attribute__((noinline
))
83 Double
plusZero ( void ) { return 0.0; }
84 static __attribute__((noinline
))
85 Double
minusZero ( void ) { return negate(plusZero()); }
87 static __attribute__((noinline
))
88 Double
plusOne ( void ) { return 1.0; }
89 static __attribute__((noinline
))
90 Double
minusOne ( void ) { return negate(plusOne()); }
92 static __attribute__((noinline
))
93 Double
plusInf ( void ) { return 1.0 / 0.0; }
94 static __attribute__((noinline
))
95 Double
minusInf ( void ) { return negate(plusInf()); }
97 static __attribute__((noinline
))
98 Double
plusNaN ( void ) { return divf64(plusInf(),plusInf()); }
99 static __attribute__((noinline
))
100 Double
minusNaN ( void ) { return negate(plusNaN()); }
102 static __attribute__((noinline
))
103 Double
plusDenorm ( void ) { return 1.23e-315 / 1e3
; }
104 static __attribute__((noinline
))
105 Double
minusDenorm ( void ) { return negate(plusDenorm()); }
108 static void ensure_special_values_initted ( void )
110 if (special_values_initted
) return;
111 special_values
[0] = plusZero();
112 special_values
[1] = minusZero();
113 special_values
[2] = plusOne();
114 special_values
[3] = minusOne();
115 special_values
[4] = plusInf();
116 special_values
[5] = minusInf();
117 special_values
[6] = plusNaN();
118 special_values
[7] = minusNaN();
119 special_values
[8] = plusDenorm();
120 special_values
[9] = minusDenorm();
121 special_values_initted
= True
;
124 for (i
= 0; i
< 10; i
++) {
125 printf("special value %d = %e\n", i
, special_values
[i
]);
130 Double
randDouble ( void )
132 ensure_special_values_initted();
133 UChar c
= randUChar();
135 // return a normal number about half of the time.
137 ULong u64
= randULong(TyDF
);
139 Long s64
= (Long
)u64
;
142 // and now as a float
145 c
= randUChar() % 10;
146 return special_values
[c
];
149 Float
randFloat ( void )
151 ensure_special_values_initted();
152 UChar c
= randUChar();
154 // return a normal number about half of the time.
156 ULong u64
= randULong(TyDF
);
158 Long s64
= (Long
)u64
;
161 // and now as a float
164 c
= randUChar() % 10;
165 return special_values
[c
];
168 void randBlock_Doubles ( V128
* block
, Int nBlock
)
171 for (i
= 0; i
< nBlock
; i
++) {
172 block
[i
].f64
[0] = randDouble();
173 block
[i
].f64
[1] = randDouble();
177 void randBlock_Floats ( V128
* block
, Int nBlock
)
180 for (i
= 0; i
< nBlock
; i
++) {
181 block
[i
].f32
[0] = randFloat();
182 block
[i
].f32
[1] = randFloat();
183 block
[i
].f32
[2] = randFloat();
184 block
[i
].f32
[3] = randFloat();