1*64ab3302SCarolineConcatto //===-- lib/Decimal/decimal-to-binary.cpp ---------------------------------===//
2*64ab3302SCarolineConcatto //
3*64ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*64ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information.
5*64ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*64ab3302SCarolineConcatto //
7*64ab3302SCarolineConcatto //===----------------------------------------------------------------------===//
8*64ab3302SCarolineConcatto 
9*64ab3302SCarolineConcatto #include "big-radix-floating-point.h"
10*64ab3302SCarolineConcatto #include "flang/Common/bit-population-count.h"
11*64ab3302SCarolineConcatto #include "flang/Common/leading-zero-bit-count.h"
12*64ab3302SCarolineConcatto #include "flang/Decimal/binary-floating-point.h"
13*64ab3302SCarolineConcatto #include "flang/Decimal/decimal.h"
14*64ab3302SCarolineConcatto #include <cinttypes>
15*64ab3302SCarolineConcatto #include <cstring>
16*64ab3302SCarolineConcatto #include <ctype.h>
17*64ab3302SCarolineConcatto 
18*64ab3302SCarolineConcatto namespace Fortran::decimal {
19*64ab3302SCarolineConcatto 
20*64ab3302SCarolineConcatto template<int PREC, int LOG10RADIX>
21*64ab3302SCarolineConcatto bool BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ParseNumber(
22*64ab3302SCarolineConcatto     const char *&p, bool &inexact) {
23*64ab3302SCarolineConcatto   SetToZero();
24*64ab3302SCarolineConcatto   while (*p == ' ') {
25*64ab3302SCarolineConcatto     ++p;
26*64ab3302SCarolineConcatto   }
27*64ab3302SCarolineConcatto   const char *q{p};
28*64ab3302SCarolineConcatto   isNegative_ = *q == '-';
29*64ab3302SCarolineConcatto   if (*q == '-' || *q == '+') {
30*64ab3302SCarolineConcatto     ++q;
31*64ab3302SCarolineConcatto   }
32*64ab3302SCarolineConcatto   const char *start{q};
33*64ab3302SCarolineConcatto   while (*q == '0') {
34*64ab3302SCarolineConcatto     ++q;
35*64ab3302SCarolineConcatto   }
36*64ab3302SCarolineConcatto   const char *first{q};
37*64ab3302SCarolineConcatto   for (; *q >= '0' && *q <= '9'; ++q) {
38*64ab3302SCarolineConcatto   }
39*64ab3302SCarolineConcatto   const char *point{nullptr};
40*64ab3302SCarolineConcatto   if (*q == '.') {
41*64ab3302SCarolineConcatto     point = q;
42*64ab3302SCarolineConcatto     for (++q; *q >= '0' && *q <= '9'; ++q) {
43*64ab3302SCarolineConcatto     }
44*64ab3302SCarolineConcatto   }
45*64ab3302SCarolineConcatto   if (q == start || (q == start + 1 && *start == '.')) {
46*64ab3302SCarolineConcatto     return false;  // require at least one digit
47*64ab3302SCarolineConcatto   }
48*64ab3302SCarolineConcatto   // There's a valid number here; set the reference argument to point to
49*64ab3302SCarolineConcatto   // the first character afterward.
50*64ab3302SCarolineConcatto   p = q;
51*64ab3302SCarolineConcatto   // Strip off trailing zeroes
52*64ab3302SCarolineConcatto   if (point) {
53*64ab3302SCarolineConcatto     while (q[-1] == '0') {
54*64ab3302SCarolineConcatto       --q;
55*64ab3302SCarolineConcatto     }
56*64ab3302SCarolineConcatto     if (q[-1] == '.') {
57*64ab3302SCarolineConcatto       point = nullptr;
58*64ab3302SCarolineConcatto       --q;
59*64ab3302SCarolineConcatto     }
60*64ab3302SCarolineConcatto   }
61*64ab3302SCarolineConcatto   if (!point) {
62*64ab3302SCarolineConcatto     while (q > first && q[-1] == '0') {
63*64ab3302SCarolineConcatto       --q;
64*64ab3302SCarolineConcatto       ++exponent_;
65*64ab3302SCarolineConcatto     }
66*64ab3302SCarolineConcatto   }
67*64ab3302SCarolineConcatto   // Trim any excess digits
68*64ab3302SCarolineConcatto   const char *limit{first + maxDigits * log10Radix + (point != nullptr)};
69*64ab3302SCarolineConcatto   if (q > limit) {
70*64ab3302SCarolineConcatto     inexact = true;
71*64ab3302SCarolineConcatto     if (point >= limit) {
72*64ab3302SCarolineConcatto       q = point;
73*64ab3302SCarolineConcatto       point = nullptr;
74*64ab3302SCarolineConcatto     }
75*64ab3302SCarolineConcatto     if (!point) {
76*64ab3302SCarolineConcatto       exponent_ += q - limit;
77*64ab3302SCarolineConcatto     }
78*64ab3302SCarolineConcatto     q = limit;
79*64ab3302SCarolineConcatto   }
80*64ab3302SCarolineConcatto   if (point) {
81*64ab3302SCarolineConcatto     exponent_ -= static_cast<int>(q - point - 1);
82*64ab3302SCarolineConcatto   }
83*64ab3302SCarolineConcatto   if (q == first) {
84*64ab3302SCarolineConcatto     exponent_ = 0;  // all zeros
85*64ab3302SCarolineConcatto   }
86*64ab3302SCarolineConcatto   // Rack the decimal digits up into big Digits.
87*64ab3302SCarolineConcatto   for (auto times{radix}; q-- > first;) {
88*64ab3302SCarolineConcatto     if (*q != '.') {
89*64ab3302SCarolineConcatto       if (times == radix) {
90*64ab3302SCarolineConcatto         digit_[digits_++] = *q - '0';
91*64ab3302SCarolineConcatto         times = 10;
92*64ab3302SCarolineConcatto       } else {
93*64ab3302SCarolineConcatto         digit_[digits_ - 1] += times * (*q - '0');
94*64ab3302SCarolineConcatto         times *= 10;
95*64ab3302SCarolineConcatto       }
96*64ab3302SCarolineConcatto     }
97*64ab3302SCarolineConcatto   }
98*64ab3302SCarolineConcatto   // Look for an optional exponent field.
99*64ab3302SCarolineConcatto   q = p;
100*64ab3302SCarolineConcatto   switch (*q) {
101*64ab3302SCarolineConcatto   case 'e':
102*64ab3302SCarolineConcatto   case 'E':
103*64ab3302SCarolineConcatto   case 'd':
104*64ab3302SCarolineConcatto   case 'D':
105*64ab3302SCarolineConcatto   case 'q':
106*64ab3302SCarolineConcatto   case 'Q': {
107*64ab3302SCarolineConcatto     bool negExpo{*++q == '-'};
108*64ab3302SCarolineConcatto     if (*q == '-' || *q == '+') {
109*64ab3302SCarolineConcatto       ++q;
110*64ab3302SCarolineConcatto     }
111*64ab3302SCarolineConcatto     if (*q >= '0' && *q <= '9') {
112*64ab3302SCarolineConcatto       int expo{0};
113*64ab3302SCarolineConcatto       while (*q == '0') {
114*64ab3302SCarolineConcatto         ++q;
115*64ab3302SCarolineConcatto       }
116*64ab3302SCarolineConcatto       const char *expDig{q};
117*64ab3302SCarolineConcatto       while (*q >= '0' && *q <= '9') {
118*64ab3302SCarolineConcatto         expo = 10 * expo + *q++ - '0';
119*64ab3302SCarolineConcatto       }
120*64ab3302SCarolineConcatto       if (q >= expDig + 8) {
121*64ab3302SCarolineConcatto         // There's a ridiculous number of nonzero exponent digits.
122*64ab3302SCarolineConcatto         // The decimal->binary conversion routine will cope with
123*64ab3302SCarolineConcatto         // returning 0 or Inf, but we must ensure that "expo" didn't
124*64ab3302SCarolineConcatto         // overflow back around to something legal.
125*64ab3302SCarolineConcatto         expo = 10 * Real::decimalRange;
126*64ab3302SCarolineConcatto         exponent_ = 0;
127*64ab3302SCarolineConcatto       }
128*64ab3302SCarolineConcatto       p = q;  // exponent was valid
129*64ab3302SCarolineConcatto       if (negExpo) {
130*64ab3302SCarolineConcatto         exponent_ -= expo;
131*64ab3302SCarolineConcatto       } else {
132*64ab3302SCarolineConcatto         exponent_ += expo;
133*64ab3302SCarolineConcatto       }
134*64ab3302SCarolineConcatto     }
135*64ab3302SCarolineConcatto   } break;
136*64ab3302SCarolineConcatto   default: break;
137*64ab3302SCarolineConcatto   }
138*64ab3302SCarolineConcatto   return true;
139*64ab3302SCarolineConcatto }
140*64ab3302SCarolineConcatto 
141*64ab3302SCarolineConcatto // This local utility class represents an unrounded nonnegative
142*64ab3302SCarolineConcatto // binary floating-point value with an unbiased (i.e., signed)
143*64ab3302SCarolineConcatto // binary exponent, an integer value (not a fraction) with an implied
144*64ab3302SCarolineConcatto // binary point to its *right*, and some guard bits for rounding.
145*64ab3302SCarolineConcatto template<int PREC> class IntermediateFloat {
146*64ab3302SCarolineConcatto public:
147*64ab3302SCarolineConcatto   static constexpr int precision{PREC};
148*64ab3302SCarolineConcatto   using IntType = common::HostUnsignedIntType<precision>;
149*64ab3302SCarolineConcatto   static constexpr IntType topBit{IntType{1} << (precision - 1)};
150*64ab3302SCarolineConcatto   static constexpr IntType mask{topBit + (topBit - 1)};
151*64ab3302SCarolineConcatto 
152*64ab3302SCarolineConcatto   IntermediateFloat() {}
153*64ab3302SCarolineConcatto   IntermediateFloat(const IntermediateFloat &) = default;
154*64ab3302SCarolineConcatto 
155*64ab3302SCarolineConcatto   // Assumes that exponent_ is valid on entry, and may increment it.
156*64ab3302SCarolineConcatto   // Returns the number of guard_ bits that have been determined.
157*64ab3302SCarolineConcatto   template<typename UINT> bool SetTo(UINT n) {
158*64ab3302SCarolineConcatto     static constexpr int nBits{CHAR_BIT * sizeof n};
159*64ab3302SCarolineConcatto     if constexpr (precision >= nBits) {
160*64ab3302SCarolineConcatto       value_ = n;
161*64ab3302SCarolineConcatto       guard_ = 0;
162*64ab3302SCarolineConcatto       return 0;
163*64ab3302SCarolineConcatto     } else {
164*64ab3302SCarolineConcatto       int shift{common::BitsNeededFor(n) - precision};
165*64ab3302SCarolineConcatto       if (shift <= 0) {
166*64ab3302SCarolineConcatto         value_ = n;
167*64ab3302SCarolineConcatto         guard_ = 0;
168*64ab3302SCarolineConcatto         return 0;
169*64ab3302SCarolineConcatto       } else {
170*64ab3302SCarolineConcatto         value_ = n >> shift;
171*64ab3302SCarolineConcatto         exponent_ += shift;
172*64ab3302SCarolineConcatto         n <<= nBits - shift;
173*64ab3302SCarolineConcatto         guard_ = (n >> (nBits - guardBits)) | ((n << guardBits) != 0);
174*64ab3302SCarolineConcatto         return shift;
175*64ab3302SCarolineConcatto       }
176*64ab3302SCarolineConcatto     }
177*64ab3302SCarolineConcatto   }
178*64ab3302SCarolineConcatto 
179*64ab3302SCarolineConcatto   void ShiftIn(int bit = 0) { value_ = value_ + value_ + bit; }
180*64ab3302SCarolineConcatto   bool IsFull() const { return value_ >= topBit; }
181*64ab3302SCarolineConcatto   void AdjustExponent(int by) { exponent_ += by; }
182*64ab3302SCarolineConcatto   void SetGuard(int g) {
183*64ab3302SCarolineConcatto     guard_ |= (static_cast<GuardType>(g & 6) << (guardBits - 3)) | (g & 1);
184*64ab3302SCarolineConcatto   }
185*64ab3302SCarolineConcatto 
186*64ab3302SCarolineConcatto   ConversionToBinaryResult<PREC> ToBinary(
187*64ab3302SCarolineConcatto       bool isNegative, FortranRounding) const;
188*64ab3302SCarolineConcatto 
189*64ab3302SCarolineConcatto private:
190*64ab3302SCarolineConcatto   static constexpr int guardBits{3};  // guard, round, sticky
191*64ab3302SCarolineConcatto   using GuardType = int;
192*64ab3302SCarolineConcatto   static constexpr GuardType oneHalf{GuardType{1} << (guardBits - 1)};
193*64ab3302SCarolineConcatto 
194*64ab3302SCarolineConcatto   IntType value_{0};
195*64ab3302SCarolineConcatto   GuardType guard_{0};
196*64ab3302SCarolineConcatto   int exponent_{0};
197*64ab3302SCarolineConcatto };
198*64ab3302SCarolineConcatto 
199*64ab3302SCarolineConcatto template<int PREC>
200*64ab3302SCarolineConcatto ConversionToBinaryResult<PREC> IntermediateFloat<PREC>::ToBinary(
201*64ab3302SCarolineConcatto     bool isNegative, FortranRounding rounding) const {
202*64ab3302SCarolineConcatto   using Binary = BinaryFloatingPointNumber<PREC>;
203*64ab3302SCarolineConcatto   // Create a fraction with a binary point to the left of the integer
204*64ab3302SCarolineConcatto   // value_, and bias the exponent.
205*64ab3302SCarolineConcatto   IntType fraction{value_};
206*64ab3302SCarolineConcatto   GuardType guard{guard_};
207*64ab3302SCarolineConcatto   int expo{exponent_ + Binary::exponentBias + (precision - 1)};
208*64ab3302SCarolineConcatto   while (expo < 1 && (fraction > 0 || guard > oneHalf)) {
209*64ab3302SCarolineConcatto     guard = (guard & 1) | (guard >> 1) |
210*64ab3302SCarolineConcatto         ((static_cast<GuardType>(fraction) & 1) << (guardBits - 1));
211*64ab3302SCarolineConcatto     fraction >>= 1;
212*64ab3302SCarolineConcatto     ++expo;
213*64ab3302SCarolineConcatto   }
214*64ab3302SCarolineConcatto   int flags{Exact};
215*64ab3302SCarolineConcatto   if (guard != 0) {
216*64ab3302SCarolineConcatto     flags |= Inexact;
217*64ab3302SCarolineConcatto   }
218*64ab3302SCarolineConcatto   if (fraction == 0 && guard <= oneHalf) {
219*64ab3302SCarolineConcatto     return {Binary{}, static_cast<enum ConversionResultFlags>(flags)};
220*64ab3302SCarolineConcatto   }
221*64ab3302SCarolineConcatto   // The value is nonzero; normalize it.
222*64ab3302SCarolineConcatto   while (fraction < topBit && expo > 1) {
223*64ab3302SCarolineConcatto     --expo;
224*64ab3302SCarolineConcatto     fraction = fraction * 2 + (guard >> (guardBits - 2));
225*64ab3302SCarolineConcatto     guard = (((guard >> (guardBits - 2)) & 1) << (guardBits - 1)) | (guard & 1);
226*64ab3302SCarolineConcatto   }
227*64ab3302SCarolineConcatto   // Apply rounding
228*64ab3302SCarolineConcatto   bool incr{false};
229*64ab3302SCarolineConcatto   switch (rounding) {
230*64ab3302SCarolineConcatto   case RoundNearest:
231*64ab3302SCarolineConcatto   case RoundDefault:
232*64ab3302SCarolineConcatto     incr = guard > oneHalf || (guard == oneHalf && (fraction & 1));
233*64ab3302SCarolineConcatto     break;
234*64ab3302SCarolineConcatto   case RoundUp: incr = guard != 0 && !isNegative; break;
235*64ab3302SCarolineConcatto   case RoundDown: incr = guard != 0 && isNegative; break;
236*64ab3302SCarolineConcatto   case RoundToZero: break;
237*64ab3302SCarolineConcatto   case RoundCompatible: incr = guard >= oneHalf; break;
238*64ab3302SCarolineConcatto   }
239*64ab3302SCarolineConcatto   if (incr) {
240*64ab3302SCarolineConcatto     if (fraction == mask) {
241*64ab3302SCarolineConcatto       // rounding causes a carry
242*64ab3302SCarolineConcatto       ++expo;
243*64ab3302SCarolineConcatto       fraction = topBit;
244*64ab3302SCarolineConcatto     } else {
245*64ab3302SCarolineConcatto       ++fraction;
246*64ab3302SCarolineConcatto     }
247*64ab3302SCarolineConcatto   }
248*64ab3302SCarolineConcatto   if (expo == 1 && fraction < topBit) {
249*64ab3302SCarolineConcatto     expo = 0;  // subnormal
250*64ab3302SCarolineConcatto   }
251*64ab3302SCarolineConcatto   if (expo >= Binary::maxExponent) {
252*64ab3302SCarolineConcatto     expo = Binary::maxExponent;  // Inf
253*64ab3302SCarolineConcatto     flags |= Overflow;
254*64ab3302SCarolineConcatto     fraction = 0;
255*64ab3302SCarolineConcatto   }
256*64ab3302SCarolineConcatto   using Raw = typename Binary::RawType;
257*64ab3302SCarolineConcatto   Raw raw = static_cast<Raw>(isNegative) << (Binary::bits - 1);
258*64ab3302SCarolineConcatto   raw |= static_cast<Raw>(expo) << Binary::significandBits;
259*64ab3302SCarolineConcatto   if constexpr (Binary::isImplicitMSB) {
260*64ab3302SCarolineConcatto     fraction &= ~topBit;
261*64ab3302SCarolineConcatto   }
262*64ab3302SCarolineConcatto   raw |= fraction;
263*64ab3302SCarolineConcatto   return {Binary(raw), static_cast<enum ConversionResultFlags>(flags)};
264*64ab3302SCarolineConcatto }
265*64ab3302SCarolineConcatto 
266*64ab3302SCarolineConcatto template<int PREC, int LOG10RADIX>
267*64ab3302SCarolineConcatto ConversionToBinaryResult<PREC>
268*64ab3302SCarolineConcatto BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToBinary() {
269*64ab3302SCarolineConcatto   // On entry, *this holds a multi-precision integer value in a radix of a
270*64ab3302SCarolineConcatto   // large power of ten.  Its radix point is defined to be to the right of its
271*64ab3302SCarolineConcatto   // digits, and "exponent_" is the power of ten by which it is to be scaled.
272*64ab3302SCarolineConcatto   Normalize();
273*64ab3302SCarolineConcatto   if (digits_ == 0) {  // zero value
274*64ab3302SCarolineConcatto     return {Real{SignBit()}};
275*64ab3302SCarolineConcatto   }
276*64ab3302SCarolineConcatto   // The value is not zero:  x = D. * 10.**E
277*64ab3302SCarolineConcatto   // Shift our perspective on the radix (& decimal) point so that
278*64ab3302SCarolineConcatto   // it sits to the *left* of the digits: i.e., x = .D * 10.**E
279*64ab3302SCarolineConcatto   exponent_ += digits_ * log10Radix;
280*64ab3302SCarolineConcatto   // Sanity checks for ridiculous exponents
281*64ab3302SCarolineConcatto   static constexpr int crazy{2 * Real::decimalRange + log10Radix};
282*64ab3302SCarolineConcatto   if (exponent_ < -crazy) {  // underflow to +/-0.
283*64ab3302SCarolineConcatto     return {Real{SignBit()}, Inexact};
284*64ab3302SCarolineConcatto   } else if (exponent_ > crazy) {  // overflow to +/-Inf.
285*64ab3302SCarolineConcatto     return {Real{Infinity()}, Overflow};
286*64ab3302SCarolineConcatto   }
287*64ab3302SCarolineConcatto   // Apply any negative decimal exponent by multiplication
288*64ab3302SCarolineConcatto   // by a power of two, adjusting the binary exponent to compensate.
289*64ab3302SCarolineConcatto   IntermediateFloat<PREC> f;
290*64ab3302SCarolineConcatto   while (exponent_ < log10Radix) {
291*64ab3302SCarolineConcatto     // x = 0.D * 10.**E * 2.**(f.ex) -> 512 * 0.D * 10.**E * 2.**(f.ex-9)
292*64ab3302SCarolineConcatto     f.AdjustExponent(-9);
293*64ab3302SCarolineConcatto     digitLimit_ = digits_;
294*64ab3302SCarolineConcatto     if (int carry{MultiplyWithoutNormalization<512>()}) {
295*64ab3302SCarolineConcatto       // x = c.D * 10.**E * 2.**(f.ex) -> .cD * 10.**(E+16) * 2.**(f.ex)
296*64ab3302SCarolineConcatto       PushCarry(carry);
297*64ab3302SCarolineConcatto       exponent_ += log10Radix;
298*64ab3302SCarolineConcatto     }
299*64ab3302SCarolineConcatto   }
300*64ab3302SCarolineConcatto   // Apply any positive decimal exponent greater than
301*64ab3302SCarolineConcatto   // is needed to treat the topmost digit as an integer
302*64ab3302SCarolineConcatto   // part by multiplying by 10 or 10000 repeatedly.
303*64ab3302SCarolineConcatto   while (exponent_ > log10Radix) {
304*64ab3302SCarolineConcatto     digitLimit_ = digits_;
305*64ab3302SCarolineConcatto     int carry;
306*64ab3302SCarolineConcatto     if (exponent_ >= log10Radix + 4) {
307*64ab3302SCarolineConcatto       // x = 0.D * 10.**E * 2.**(f.ex) -> 625 * .D * 10.**(E-4) * 2.**(f.ex+4)
308*64ab3302SCarolineConcatto       exponent_ -= 4;
309*64ab3302SCarolineConcatto       carry = MultiplyWithoutNormalization<(5 * 5 * 5 * 5)>();
310*64ab3302SCarolineConcatto       f.AdjustExponent(4);
311*64ab3302SCarolineConcatto     } else {
312*64ab3302SCarolineConcatto       // x = 0.D * 10.**E * 2.**(f.ex) -> 5 * .D * 10.**(E-1) * 2.**(f.ex+1)
313*64ab3302SCarolineConcatto       --exponent_;
314*64ab3302SCarolineConcatto       carry = MultiplyWithoutNormalization<5>();
315*64ab3302SCarolineConcatto       f.AdjustExponent(1);
316*64ab3302SCarolineConcatto     }
317*64ab3302SCarolineConcatto     if (carry != 0) {
318*64ab3302SCarolineConcatto       // x = c.D * 10.**E * 2.**(f.ex) -> .cD * 10.**(E+16) * 2.**(f.ex)
319*64ab3302SCarolineConcatto       PushCarry(carry);
320*64ab3302SCarolineConcatto       exponent_ += log10Radix;
321*64ab3302SCarolineConcatto     }
322*64ab3302SCarolineConcatto   }
323*64ab3302SCarolineConcatto   // So exponent_ is now log10Radix, meaning that the
324*64ab3302SCarolineConcatto   // MSD can be taken as an integer part and transferred
325*64ab3302SCarolineConcatto   // to the binary result.
326*64ab3302SCarolineConcatto   // x = .jD * 10.**16 * 2.**(f.ex) -> .D * j * 2.**(f.ex)
327*64ab3302SCarolineConcatto   int guardShift{f.SetTo(digit_[--digits_])};
328*64ab3302SCarolineConcatto   // Transfer additional bits until the result is normal.
329*64ab3302SCarolineConcatto   digitLimit_ = digits_;
330*64ab3302SCarolineConcatto   while (!f.IsFull()) {
331*64ab3302SCarolineConcatto     // x = ((b.D)/2) * j * 2.**(f.ex) -> .D * (2j + b) * 2.**(f.ex-1)
332*64ab3302SCarolineConcatto     f.AdjustExponent(-1);
333*64ab3302SCarolineConcatto     std::uint32_t carry = MultiplyWithoutNormalization<2>();
334*64ab3302SCarolineConcatto     f.ShiftIn(carry);
335*64ab3302SCarolineConcatto   }
336*64ab3302SCarolineConcatto   // Get the next few bits for rounding.  Allow for some guard bits
337*64ab3302SCarolineConcatto   // that may have already been set in f.SetTo() above.
338*64ab3302SCarolineConcatto   int guard{0};
339*64ab3302SCarolineConcatto   if (guardShift == 0) {
340*64ab3302SCarolineConcatto     guard = MultiplyWithoutNormalization<4>();
341*64ab3302SCarolineConcatto   } else if (guardShift == 1) {
342*64ab3302SCarolineConcatto     guard = MultiplyWithoutNormalization<2>();
343*64ab3302SCarolineConcatto   }
344*64ab3302SCarolineConcatto   guard = guard + guard + !IsZero();
345*64ab3302SCarolineConcatto   f.SetGuard(guard);
346*64ab3302SCarolineConcatto   return f.ToBinary(isNegative_, rounding_);
347*64ab3302SCarolineConcatto }
348*64ab3302SCarolineConcatto 
349*64ab3302SCarolineConcatto template<int PREC, int LOG10RADIX>
350*64ab3302SCarolineConcatto ConversionToBinaryResult<PREC>
351*64ab3302SCarolineConcatto BigRadixFloatingPointNumber<PREC, LOG10RADIX>::ConvertToBinary(const char *&p) {
352*64ab3302SCarolineConcatto   bool inexact{false};
353*64ab3302SCarolineConcatto   if (ParseNumber(p, inexact)) {
354*64ab3302SCarolineConcatto     auto result{ConvertToBinary()};
355*64ab3302SCarolineConcatto     if (inexact) {
356*64ab3302SCarolineConcatto       result.flags =
357*64ab3302SCarolineConcatto           static_cast<enum ConversionResultFlags>(result.flags | Inexact);
358*64ab3302SCarolineConcatto     }
359*64ab3302SCarolineConcatto     return result;
360*64ab3302SCarolineConcatto   } else {
361*64ab3302SCarolineConcatto     // Could not parse a decimal floating-point number.  p has been
362*64ab3302SCarolineConcatto     // advanced over any leading spaces.
363*64ab3302SCarolineConcatto     if (toupper(p[0]) == 'N' && toupper(p[1]) == 'A' && toupper(p[2]) == 'N') {
364*64ab3302SCarolineConcatto       // NaN
365*64ab3302SCarolineConcatto       p += 3;
366*64ab3302SCarolineConcatto       return {Real{NaN()}};
367*64ab3302SCarolineConcatto     } else {
368*64ab3302SCarolineConcatto       // Try to parse Inf, maybe with a sign
369*64ab3302SCarolineConcatto       const char *q{p};
370*64ab3302SCarolineConcatto       isNegative_ = *q == '-';
371*64ab3302SCarolineConcatto       if (*q == '-' || *q == '+') {
372*64ab3302SCarolineConcatto         ++q;
373*64ab3302SCarolineConcatto       }
374*64ab3302SCarolineConcatto       if (toupper(q[0]) == 'I' && toupper(q[1]) == 'N' &&
375*64ab3302SCarolineConcatto           toupper(q[2]) == 'F') {
376*64ab3302SCarolineConcatto         p = q + 3;
377*64ab3302SCarolineConcatto         return {Real{Infinity()}};
378*64ab3302SCarolineConcatto       } else {
379*64ab3302SCarolineConcatto         // Invalid input
380*64ab3302SCarolineConcatto         return {Real{NaN()}, Invalid};
381*64ab3302SCarolineConcatto       }
382*64ab3302SCarolineConcatto     }
383*64ab3302SCarolineConcatto   }
384*64ab3302SCarolineConcatto }
385*64ab3302SCarolineConcatto 
386*64ab3302SCarolineConcatto template<int PREC>
387*64ab3302SCarolineConcatto ConversionToBinaryResult<PREC> ConvertToBinary(
388*64ab3302SCarolineConcatto     const char *&p, enum FortranRounding rounding) {
389*64ab3302SCarolineConcatto   return BigRadixFloatingPointNumber<PREC>{rounding}.ConvertToBinary(p);
390*64ab3302SCarolineConcatto }
391*64ab3302SCarolineConcatto 
392*64ab3302SCarolineConcatto template ConversionToBinaryResult<8> ConvertToBinary<8>(
393*64ab3302SCarolineConcatto     const char *&, enum FortranRounding);
394*64ab3302SCarolineConcatto template ConversionToBinaryResult<11> ConvertToBinary<11>(
395*64ab3302SCarolineConcatto     const char *&, enum FortranRounding);
396*64ab3302SCarolineConcatto template ConversionToBinaryResult<24> ConvertToBinary<24>(
397*64ab3302SCarolineConcatto     const char *&, enum FortranRounding);
398*64ab3302SCarolineConcatto template ConversionToBinaryResult<53> ConvertToBinary<53>(
399*64ab3302SCarolineConcatto     const char *&, enum FortranRounding);
400*64ab3302SCarolineConcatto template ConversionToBinaryResult<64> ConvertToBinary<64>(
401*64ab3302SCarolineConcatto     const char *&, enum FortranRounding);
402*64ab3302SCarolineConcatto template ConversionToBinaryResult<112> ConvertToBinary<112>(
403*64ab3302SCarolineConcatto     const char *&, enum FortranRounding);
404*64ab3302SCarolineConcatto 
405*64ab3302SCarolineConcatto extern "C" {
406*64ab3302SCarolineConcatto enum ConversionResultFlags ConvertDecimalToFloat(
407*64ab3302SCarolineConcatto     const char **p, float *f, enum FortranRounding rounding) {
408*64ab3302SCarolineConcatto   auto result{Fortran::decimal::ConvertToBinary<24>(*p, rounding)};
409*64ab3302SCarolineConcatto   std::memcpy(reinterpret_cast<void *>(f),
410*64ab3302SCarolineConcatto       reinterpret_cast<const void *>(&result.binary), sizeof *f);
411*64ab3302SCarolineConcatto   return result.flags;
412*64ab3302SCarolineConcatto }
413*64ab3302SCarolineConcatto enum ConversionResultFlags ConvertDecimalToDouble(
414*64ab3302SCarolineConcatto     const char **p, double *d, enum FortranRounding rounding) {
415*64ab3302SCarolineConcatto   auto result{Fortran::decimal::ConvertToBinary<53>(*p, rounding)};
416*64ab3302SCarolineConcatto   std::memcpy(reinterpret_cast<void *>(d),
417*64ab3302SCarolineConcatto       reinterpret_cast<const void *>(&result.binary), sizeof *d);
418*64ab3302SCarolineConcatto   return result.flags;
419*64ab3302SCarolineConcatto }
420*64ab3302SCarolineConcatto #if __x86_64__ && !defined(_MSC_VER)
421*64ab3302SCarolineConcatto enum ConversionResultFlags ConvertDecimalToLongDouble(
422*64ab3302SCarolineConcatto     const char **p, long double *ld, enum FortranRounding rounding) {
423*64ab3302SCarolineConcatto   auto result{Fortran::decimal::ConvertToBinary<64>(*p, rounding)};
424*64ab3302SCarolineConcatto   std::memcpy(reinterpret_cast<void *>(ld),
425*64ab3302SCarolineConcatto       reinterpret_cast<const void *>(&result.binary), sizeof *ld);
426*64ab3302SCarolineConcatto   return result.flags;
427*64ab3302SCarolineConcatto }
428*64ab3302SCarolineConcatto #endif
429*64ab3302SCarolineConcatto }
430*64ab3302SCarolineConcatto }
431