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); }
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); }