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))));
80 if (
int(sFMT::mbits) >=
int(dFMT::mbits) &&
81 int(sFMT::ebits) >=
int(dFMT::ebits)) {
87 if (std::numeric_limits<dFMT>::has_quiet_NaN) {
88 out = std::numeric_limits<dFMT>::quiet_NaN();
90 if (in.storage & 0x80000000) {
91 out.storage |= 0x80000000;
94 out = std::numeric_limits<dFMT>::max();
96 if (in.storage & 0x80000000) {
97 out.storage |= 0x80000000;
102 if (std::numeric_limits<dFMT>::has_infinity) {
103 out = std::numeric_limits<dFMT>::infinity();
105 if (in.storage & 0x80000000) {
106 out.storage |= 0x80000000;
109 out = std::numeric_limits<dFMT>::max();
111 if (in.storage & 0x80000000) {
112 out.storage |= 0x80000000;
115 }
else if (in.mant == 0 && in.exp == 0) {
122 uint32_t mant = in.mant &
mask(sFMT::mbits);
123 int32_t exp = in.exp - sFMT::bias + dFMT::bias;
128 mant |= (1 << sFMT::mbits);
132 uint32_t saved_mant = mant;
134 mant >>= (sFMT::mbits - dFMT::mbits);
145 mant &=
mask(dFMT::mbits);
165 if (
int(sFMT::mbits) >
int(dFMT::mbits)
167 bool round_up =
false;
173 assert((sFMT::mbits - dFMT::mbits) > 2);
175 int check_shift = sFMT::mbits - dFMT::mbits - 3;
176 uint32_t check_mant = saved_mant;
181 int sticky = (check_mant &
mask(check_shift + 1)) != 0;
183 check_mant >>= check_shift;
186 check_mant >>=
shift;
193 uint32_t check_test = check_mant & 0x7;
196 check_test += sticky;
198 if (check_test > 0x4) {
200 }
else if (check_test == 0x4) {
208 if (check_mant & 0x8) {
214 if (out.mant ==
mask(dFMT::mbits)) {
216 if (out.exp !=
mask(dFMT::ebits)) {
224 }
else if (
int(sFMT::mbits) >
int(dFMT::mbits)
231 uint32_t discarded = in.mant &
mask(sFMT::mbits - dFMT::mbits);
232 uint32_t max_mant =
mask(sFMT::mbits);
234 float round_prob = float(discarded) / float(max_mant);
239 auto srFunc = [](uint32_t in) {
240 uint32_t bit = (in ^ (in >> 1) ^ (in >> 3) ^ (in >> 12));
241 return (in >> 1) | (bit << 15);
246 float draw_prob = float(srFunc(seed))
247 / float(std::numeric_limits<uint32_t>::max());
252 if (round_prob >= draw_prob) {
253 if (out.mant ==
mask(dFMT::mbits)) {
255 if (out.exp !=
mask(dFMT::ebits)) {
265 }
else if (
int(sFMT::mbits) <=
int(dFMT::mbits) &&
266 int(sFMT::ebits) <=
int(dFMT::ebits)) {
272 if (std::numeric_limits<dFMT>::has_quiet_NaN) {
273 out = std::numeric_limits<dFMT>::quiet_NaN();
275 if (in.storage & 0x80000000) {
276 out.storage |= 0x80000000;
279 out = std::numeric_limits<dFMT>::max();
281 if (in.storage & 0x80000000) {
282 out.storage |= 0x80000000;
287 if (std::numeric_limits<dFMT>::has_infinity) {
288 out = std::numeric_limits<dFMT>::infinity();
290 if (in.storage & 0x80000000) {
291 out.storage |= 0x80000000;
294 out = std::numeric_limits<dFMT>::max();
296 if (in.storage & 0x80000000) {
297 out.storage |= 0x80000000;
300 }
else if (in.mant == 0 && in.exp == 0) {
306 out.mant = in.mant << (dFMT::mbits - sFMT::mbits);
307 out.exp = in.exp + dFMT::bias - sFMT::bias;
311 if (!in.exp &&
int(sFMT::ebits) !=
int(dFMT::ebits)) {
312 uint32_t
m = out.mant;
315 while (!(
m >> dFMT::mbits)) {
319 out.mant =
m &
mask(dFMT::mbits);
321 }
else if (!in.exp) {
324 uint32_t
m = out.mant;
326 out.mant =
m &
mask(dFMT::mbits);