72 static_assert(((int(sFMT::mbits) >= int(dFMT::mbits)) &&
73 (int(sFMT::ebits) >= int(dFMT::ebits)))
74 || ((int(sFMT::mbits) <= int(dFMT::mbits)) &&
75 (int(sFMT::ebits) <= int(dFMT::ebits))));
81 if (std::is_same_v<sFMT, dFMT>) {
82 out.storage = in.storage;
86 if constexpr (int(sFMT::mbits) >= int(dFMT::mbits) &&
87 int(sFMT::ebits) >= int(dFMT::ebits)) {
93 if (std::numeric_limits<dFMT>::has_quiet_NaN) {
94 out = std::numeric_limits<dFMT>::quiet_NaN();
96 if (in.storage & 0x80000000) {
97 out.storage |= 0x80000000;
100 out = std::numeric_limits<dFMT>::max();
102 if (in.storage & 0x80000000) {
103 out.storage |= 0x80000000;
108 if (std::numeric_limits<dFMT>::has_infinity) {
109 out = std::numeric_limits<dFMT>::infinity();
111 if (in.storage & 0x80000000) {
112 out.storage |= 0x80000000;
115 out = std::numeric_limits<dFMT>::max();
117 if (in.storage & 0x80000000) {
118 out.storage |= 0x80000000;
121 }
else if (in.mant == 0 && in.exp == 0) {
128 uint32_t mant = in.mant &
mask(sFMT::mbits);
129 int32_t exp = in.exp - sFMT::bias + dFMT::bias;
134 mant |= (1 << sFMT::mbits);
138 uint32_t saved_mant = mant;
140 mant >>= (sFMT::mbits - dFMT::mbits);
143 if (exp < 1 && in.exp) {
151 mant &=
mask(dFMT::mbits);
171 if (
int(sFMT::mbits) >
int(dFMT::mbits)
173 bool round_up =
false;
179 assert((sFMT::mbits - dFMT::mbits) > 2);
181 int check_shift = sFMT::mbits - dFMT::mbits - 3;
182 uint32_t check_mant = saved_mant;
187 int sticky = (check_mant &
mask(check_shift + 1)) != 0;
189 check_mant >>= check_shift;
192 check_mant >>=
shift;
199 uint32_t check_test = check_mant & 0x7;
202 check_test += sticky;
204 if (check_test > 0x4) {
209 if (out.mant ==
mask(dFMT::mbits)) {
211 if (out.exp !=
mask(dFMT::ebits)) {
219 }
else if (
int(sFMT::mbits) >
int(dFMT::mbits)
226 uint32_t discarded = in.mant &
mask(sFMT::mbits - dFMT::mbits);
227 uint32_t max_mant =
mask(sFMT::mbits);
229 float round_prob = float(discarded) / float(max_mant);
234 auto srFunc = [](uint32_t in) {
235 uint32_t bit = (in ^ (in >> 1) ^ (in >> 3) ^ (in >> 12));
236 return (in >> 1) | (bit << 15);
241 float draw_prob = float(srFunc(seed))
242 / float(std::numeric_limits<uint32_t>::max());
247 if (round_prob <= draw_prob) {
248 if (out.mant ==
mask(dFMT::mbits)) {
250 if (out.exp !=
mask(dFMT::ebits)) {
260 }
else if constexpr (int(sFMT::mbits) <= int(dFMT::mbits) &&
261 int(sFMT::ebits) <= int(dFMT::ebits)) {
267 if (std::numeric_limits<dFMT>::has_quiet_NaN) {
268 out = std::numeric_limits<dFMT>::quiet_NaN();
270 if (in.storage & 0x80000000) {
271 out.storage |= 0x80000000;
274 out = std::numeric_limits<dFMT>::max();
276 if (in.storage & 0x80000000) {
277 out.storage |= 0x80000000;
282 if (std::numeric_limits<dFMT>::has_infinity) {
283 out = std::numeric_limits<dFMT>::infinity();
285 if (in.storage & 0x80000000) {
286 out.storage |= 0x80000000;
289 out = std::numeric_limits<dFMT>::max();
291 if (in.storage & 0x80000000) {
292 out.storage |= 0x80000000;
295 }
else if (in.mant == 0 && in.exp == 0) {
301 out.mant = in.mant << (dFMT::mbits - sFMT::mbits);
302 out.exp = in.exp + dFMT::bias - sFMT::bias;
308 if (!in.exp &&
int(sFMT::ebits) !=
int(dFMT::ebits)) {
309 uint32_t
m = out.mant;
312 while (!(
m >> dFMT::mbits)) {
316 out.mant =
m &
mask(dFMT::mbits);