Ejemplo n.º 1
0
        static int to_chars(floating_decimal_64 v, bool sign, Span <char> result)
        {
            // Step 5: Print the decimal representation.
            int index = 0;

            if (sign)
            {
                result[index++] = '-';
            }

            uint64_t output  = v.mantissa;
            int32_t  olength = decimalLength17(output);


            // Print the decimal digits.
            // The following code is equivalent to:
            // for (uint32_t i = 0; i < olength - 1; ++i) {
            //   const uint32_t c = output % 10; output /= 10;
            //   result[index + olength - i] = (char) ('0' + c);
            // }
            // result[index] = '0' + output % 10;

            int32_t i = 0;

            // We prefer 32-bit operations, even on 64-bit platforms.
            // We have at most 17 digits, and uint32_t can store 9 digits.
            // If output doesn't fit into uint32_t, we cut off 8 digits,
            // so the rest will fit into uint32_t.
            if ((output >> 32) != 0)
            {
                // Expensive 64-bit division.
                uint64_t q       = div1e8(output);
                uint32_t output3 = ((uint32_t)output) - (100000000 * ((uint32_t)q));
                output = q;

                output3 = (uint)Math.DivRem((int)output3, 10000, out int32_t c);
                int32_t d  = (int32_t)(output3 % 10000);
                int32_t c1 = Math.DivRem(c, 100, out int c0) << 1;
                c0 <<= 1;
                int32_t d1 = Math.DivRem(d, 100, out int d0) << 1;
                d0 <<= 1;
                DIGIT_TABLE.AsSpan(c0, 2).CopyTo(result.Slice(index + olength - i - 1));
                DIGIT_TABLE.AsSpan(c1, 2).CopyTo(result.Slice(index + olength - i - 3));
                DIGIT_TABLE.AsSpan(d0, 2).CopyTo(result.Slice(index + olength - i - 5));
                DIGIT_TABLE.AsSpan(d1, 2).CopyTo(result.Slice(index + olength - i - 7));
                i += 8;
            }
            uint32_t output2 = (uint32_t)output;

            while (output2 >= 10000)
            {
                output2 = (uint32_t)Math.DivRem((int32_t)output2, 10000, out int32_t c);
                int32_t c1 = Math.DivRem(c, 100, out int c0) << 1;
                c0 <<= 1;
                DIGIT_TABLE.AsSpan(c0, 2).CopyTo(result.Slice(index + olength - i - 1));
                DIGIT_TABLE.AsSpan(c1, 2).CopyTo(result.Slice(index + olength - i - 3));
                i += 4;
            }
            if (output2 >= 100)
            {
                output2 = (uint32_t)Math.DivRem((int32_t)output2, 100, out int32_t c);
                c     <<= 1;
                DIGIT_TABLE.AsSpan(c, 2).CopyTo(result.Slice(index + olength - i - 1));
                i += 2;
            }
            if (output2 >= 10)
            {
                uint32_t c = output2 << 1;
                // We can't use memcpy here: the decimal dot goes between these two digits.
                result[index + olength - i] = DIGIT_TABLE[c + 1];
                result[index] = DIGIT_TABLE[c];
            }
            else
            {
                result[index] = (char)('0' + output2);
            }

            // Print decimal point if needed.
            if (olength > 1)
            {
                result[index + 1] = '.';
                index            += olength + 1;
            }
            else
            {
                ++index;
            }

            // Print the exponent.
            result[index++] = 'E';
            int32_t exp = v.exponent + olength - 1;

            if (exp < 0)
            {
                result[index++] = '-';
                exp             = -exp;
            }

            if (exp >= 100)
            {
                DIGIT_TABLE.AsSpan(2 * Math.DivRem(exp, 10, out var c), 2).CopyTo(result.Slice(index));
                result[index + 2] = (char)('0' + c);
                index            += 3;
            }
            else if (exp >= 10)
            {
                DIGIT_TABLE.AsSpan(2 * exp, 2).CopyTo(result.Slice(index));
                index += 2;
            }
            else
            {
                result[index++] = (char)('0' + exp);
            }

            return(index);
        }
Ejemplo n.º 2
0
        static int to_chars(floating_decimal_32 v, bool sign, Span <char> result)
        {
            // Step 5: Print the decimal representation.
            int index = 0;

            if (sign)
            {
                result[index++] = '-';
            }

            int32_t output  = (int)v.mantissa;
            int32_t olength = decimalLength9((uint)output);


            // Print the decimal digits.
            // The following code is equivalent to:
            // for (uint32_t i = 0; i < olength - 1; ++i) {
            //   const uint32_t c = output % 10; output /= 10;
            //   result[index + olength - i] = (char) ('0' + c);
            // }
            // result[index] = '0' + output % 10;
            int32_t i = 0;

            while (output >= 10000)
            {
                output = Math.DivRem(output, 10000, out int32_t c);

                int32_t c1 = Math.DivRem(c, 100, out int32_t c0) << 1;
                c0 <<= 1;
                DIGIT_TABLE.AsSpan(c0, 2).CopyTo(result.Slice(index + olength - i - 1));
                DIGIT_TABLE.AsSpan(c1, 2).CopyTo(result.Slice(index + olength - i - 3));
                i += 4;
            }
            if (output >= 100)
            {
                output = Math.DivRem(output, 100, out int32_t c);
                c    <<= 1;
                DIGIT_TABLE.AsSpan(c, 2).CopyTo(result.Slice(index + olength - i - 1));
                i += 2;
            }
            if (output >= 10)
            {
                int32_t c = output << 1;
                // We can't use memcpy here: the decimal dot goes between these two digits.
                result[(int32_t)((uint32_t)index + olength - i)] = DIGIT_TABLE[c + 1];
                result[index] = DIGIT_TABLE[c];
            }
            else
            {
                result[index] = (char)('0' + output);
            }

            // Print decimal point if needed.
            if (olength > 1)
            {
                result[index + 1] = '.';
                index            += olength + 1;
            }
            else
            {
                ++index;
            }

            // Print the exponent.
            result[index++] = 'E';
            int32_t exp = v.exponent + olength - 1;

            if (exp < 0)
            {
                result[index++] = '-';
                exp             = -exp;
            }

            if (exp >= 10)
            {
                DIGIT_TABLE.AsSpan(2 * exp, 2).CopyTo(result.Slice(index));
                index += 2;
            }
            else
            {
                result[index++] = (char)('0' + exp);
            }

            return(index);
        }