79 static constexpr int sig_bits = SIG_BITS;
80 static constexpr int exp_bits = EXP_BITS;
81 static constexpr int bits = sig_bits + exp_bits + 1;
83 static_assert( std::is_integral_v< raw_type > );
84 static_assert( sig_bits >= 0 );
85 static_assert( exp_bits >= 0 );
86 static_assert( bits <=
sizeof( raw_type ) * CHAR_BIT );
88 static constexpr int exp_max = ( 1 << exp_bits ) - 1;
89 static constexpr int exp_bias = exp_max >> 1;
91 static constexpr raw_type sign = raw_type( 1 ) << ( bits - 1 );
92 static constexpr raw_type inf = raw_type( exp_max ) << sig_bits;
93 static constexpr raw_type qnan = inf | ( inf >> 1 );
95 static constexpr auto abs( raw_type v ) {
return raw_type( v & ( sign - 1 ) ); }
96 static constexpr bool is_nan( raw_type v ) {
return abs( v ) > inf; }
97 static constexpr bool is_inf( raw_type v ) {
return abs( v ) == inf; }
98 static constexpr bool is_zero( raw_type v ) {
return abs( v ) == 0; }
117 using enc_type =
typename enc::raw_type;
119 template<
bool DO_ROUNDING,
typename F >
120 static auto encode( F value )
123 using raw_type =
typename flt::raw_type;
124 static constexpr auto sig_diff = flt::sig_bits - enc::sig_bits;
125 static constexpr auto bit_diff = flt::bits - enc::bits;
126 static constexpr auto do_rounding = DO_ROUNDING && sig_diff > 0;
127 static constexpr auto bias_mul = raw_type( enc::exp_bias ) << flt::sig_bits;
128 if constexpr( !do_rounding ) {
130 value *= detail::bit_cast< F >( bias_mul );
132 auto bits = detail::bit_cast< raw_type >( value );
133 auto sign = bits & flt::sign;
135 auto is_nan = flt::inf < bits;
136 if constexpr( do_rounding ) {
137 static constexpr auto min_norm = raw_type( flt::exp_bias - enc::exp_bias + 1 ) << flt::sig_bits;
138 static constexpr auto sub_rnd = enc::exp_bias < sig_diff
139 ? raw_type( 1 ) << ( flt::sig_bits - 1 + enc::exp_bias - sig_diff )
140 : raw_type( enc::exp_bias - sig_diff ) << flt::sig_bits;
141 static constexpr auto sub_mul = raw_type( flt::exp_bias + sig_diff ) << flt::sig_bits;
142 bool is_sub = bits < min_norm;
143 auto norm = detail::bit_cast< F >( bits );
145 subn *= detail::bit_cast< F >( sub_rnd );
146 subn *= detail::bit_cast< F >( sub_mul );
147 norm *= detail::bit_cast< F >( bias_mul );
148 bits = detail::bit_cast< raw_type >( norm );
149 bits += ( bits >> sig_diff ) & 1;
150 bits += ( raw_type( 1 ) << ( sig_diff - 1 ) ) - 1;
152 bits ^= -is_sub & ( detail::bit_cast< raw_type >( subn ) ^ bits );
156 bits ^= -( enc::inf < bits ) & ( enc::inf ^ bits );
158 bits ^= -is_nan & ( enc::qnan ^ bits );
159 bits |= sign >> bit_diff;
160 return enc_type( bits );
163 template<
typename F >
164 static F decode( enc_type value )
167 using raw_type =
typename flt::raw_type;
168 static constexpr auto sig_diff = flt::sig_bits - enc::sig_bits;
169 static constexpr auto bit_diff = flt::bits - enc::bits;
170 static constexpr auto bias_mul = raw_type( 2 * flt::exp_bias - enc::exp_bias ) << flt::sig_bits;
171 raw_type bits = value;
172 auto sign = bits & enc::sign;
174 auto is_norm = bits < enc::inf;
175 bits = ( sign << bit_diff ) | ( bits << sig_diff );
176 auto val = detail::bit_cast< F >( bits ) * detail::bit_cast< F >( bias_mul );
177 bits = detail::bit_cast< raw_type >( val );
179 bits |= -!is_norm & flt::inf;
180 return detail::bit_cast< F >( bits );