3 #define H_BIAS (UINT16_C(0xf))
4 #define H_F_MASK (UINT16_C(0x03FF))
5 #define H_E_MASK (UINT16_C(0x7C00))
7 #define H_S_MASK (UINT16_C(0x8000))
9 #define H_QNAN (H_F_MASK)
11 #define S_BIAS (UINT32_C(0x7F))
12 #define S_F_MASK (UINT32_C(0x007fffff))
13 #define S_E_MASK (UINT32_C(0x7f800000))
14 #define S_E_SHIFT (23)
15 #define S_S_MASK (UINT32_C(0x80000000))
17 #define S_QNAN (S_F_MASK)
19 #define PAD (S_E_SHIFT - H_E_SHIFT)
21 uint_fast32_t cvt_hs(uint_fast16_t x
)
23 #define MSB (UINT32_C(0x00800000))
24 uint_fast32_t frac
, exp
, sign
;
25 frac
= (x
& H_F_MASK
) << PAD
;
27 sign
= (x
& H_S_MASK
);
31 if (frac
) { /* Denormal */
33 /* Adjust fraction for implicit leading 1-bit */
34 for (; !(frac
& MSB
); frac
<<= 1, exp
--);
40 case H_E_MASK
: /* Infinity and NaN */
42 if (frac
) { /* Set padding bits for NaN */
43 frac
|= (1 << PAD
) - 1;
47 exp
+= (S_BIAS
- H_BIAS
) << H_E_SHIFT
; /* Re-bias */
50 return (sign
<< 16) | exp
| frac
;
55 RNE
= 0, /* Round to nearest; ties to even */
56 RTZ
= 1, /* Round towards zero (truncate) */
57 RDN
= 2, /* Round towards negative infinity (down) */
58 RUP
= 3, /* Round towards positive infinity (up) */
59 RMM
= 4, /* Round to nearest; ties to max magnitude */
64 * Guard bit (G): frac[12]
65 * Round bit (R): frac[11]
66 * Sticky bit (S): OR of frac[10..0]
78 * 100 : tie; round up if LSB is 1
83 uint_fast16_t cvt_sh(uint_fast32_t x
, int rm
)
85 #define MSB UINT16_C(0x0400)
86 uint_fast32_t frac
, exp
, sign
;
88 sign
= (x
& S_S_MASK
) >> 16;
90 if (exp
&& exp
!= S_E_MASK
) {
95 /* Round up if G is set and either R, S,
96 or the bit before G is non-zero */
97 inc
= (x
& 0x1000) && (x
& 0x2fff);
100 inc
= ((x
& 0x1fff) != 0) && (!sign
);
103 inc
= ((x
& 0x1fff) != 0) && sign
;
107 exp
= (x
& S_E_MASK
);
109 frac
= (x
& S_F_MASK
) >> PAD
;
111 e
= (exp
>> S_E_SHIFT
) - S_BIAS
;
112 if (e
< -24) { /* Round to zero */
114 } else if (e
< -14) { /* Denormal */
115 frac
= (frac
| MSB
) >> (-e
- 14);
118 exp
= (e
+ H_BIAS
) << H_E_SHIFT
;
119 } else if (e
< 127) { /* Round to infinity */
123 /* Infinity and NaN */
125 return sign
| exp
| frac
;