common.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // Copyright 2018 Ulf Adams
  2. //
  3. // The contents of this file may be used under the terms of the Apache License,
  4. // Version 2.0.
  5. //
  6. // (See accompanying file LICENSE-Apache or copy at
  7. // http://www.apache.org/licenses/LICENSE-2.0)
  8. //
  9. // Alternatively, the contents of this file may be used under the terms of
  10. // the Boost Software License, Version 1.0.
  11. // (See accompanying file LICENSE-Boost or copy at
  12. // https://www.boost.org/LICENSE_1_0.txt)
  13. //
  14. // Unless required by applicable law or agreed to in writing, this software
  15. // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. // KIND, either express or implied.
  17. /*
  18. This is a derivative work
  19. */
  20. #ifndef BOOST_JSON_DETAIL_RYU_DETAIL_COMMON_HPP
  21. #define BOOST_JSON_DETAIL_RYU_DETAIL_COMMON_HPP
  22. #include <boost/json/detail/config.hpp>
  23. #include <string.h>
  24. namespace boost {
  25. namespace json {
  26. namespace detail {
  27. namespace ryu {
  28. namespace detail {
  29. constexpr int DOUBLE_MANTISSA_BITS = 52;
  30. constexpr int DOUBLE_EXPONENT_BITS = 11;
  31. constexpr int DOUBLE_BIAS = 1023;
  32. #if defined(_M_IX86) || defined(_M_ARM)
  33. #define BOOST_JSON_RYU_32_BIT_PLATFORM
  34. #endif
  35. inline uint32_t decimalLength9(const uint32_t v) {
  36. // Function precondition: v is not a 10-digit number.
  37. // (f2s: 9 digits are sufficient for round-tripping.)
  38. // (d2fixed: We print 9-digit blocks.)
  39. BOOST_ASSERT(v < 1000000000);
  40. if (v >= 100000000) { return 9; }
  41. if (v >= 10000000) { return 8; }
  42. if (v >= 1000000) { return 7; }
  43. if (v >= 100000) { return 6; }
  44. if (v >= 10000) { return 5; }
  45. if (v >= 1000) { return 4; }
  46. if (v >= 100) { return 3; }
  47. if (v >= 10) { return 2; }
  48. return 1;
  49. }
  50. // Returns e == 0 ? 1 : ceil(log_2(5^e)).
  51. inline int32_t pow5bits(const int32_t e) {
  52. // This approximation works up to the point that the multiplication overflows at e = 3529.
  53. // If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater
  54. // than 2^9297.
  55. BOOST_ASSERT(e >= 0);
  56. BOOST_ASSERT(e <= 3528);
  57. return (int32_t) (((((uint32_t) e) * 1217359) >> 19) + 1);
  58. }
  59. // Returns floor(log_10(2^e)).
  60. inline uint32_t log10Pow2(const int32_t e) {
  61. // The first value this approximation fails for is 2^1651 which is just greater than 10^297.
  62. BOOST_ASSERT(e >= 0);
  63. BOOST_ASSERT(e <= 1650);
  64. return (((uint32_t) e) * 78913) >> 18;
  65. }
  66. // Returns floor(log_10(5^e)).
  67. inline uint32_t log10Pow5(const int32_t e) {
  68. // The first value this approximation fails for is 5^2621 which is just greater than 10^1832.
  69. BOOST_ASSERT(e >= 0);
  70. BOOST_ASSERT(e <= 2620);
  71. return (((uint32_t) e) * 732923) >> 20;
  72. }
  73. inline int copy_special_str(char * const result, const bool sign, const bool exponent, const bool mantissa) {
  74. if (mantissa) {
  75. memcpy(result, "NaN", 3);
  76. return 3;
  77. }
  78. if (sign) {
  79. result[0] = '-';
  80. }
  81. if (exponent) {
  82. memcpy(result + sign, "Infinity", 8);
  83. return sign + 8;
  84. }
  85. memcpy(result + sign, "0E0", 3);
  86. return sign + 3;
  87. }
  88. inline
  89. int
  90. copy_special_str_conforming(
  91. char* const result, bool sign, bool exponent, bool mantissa)
  92. {
  93. if (mantissa)
  94. {
  95. memcpy(result, "null", 4);
  96. return 4;
  97. }
  98. if (sign)
  99. result[0] = '-';
  100. if (exponent)
  101. {
  102. memcpy(result + sign, "1e99999", 7);
  103. return sign + 7;
  104. }
  105. memcpy(result + sign, "0E0", 3);
  106. return sign + 3;
  107. }
  108. inline uint32_t float_to_bits(const float f) {
  109. uint32_t bits = 0;
  110. memcpy(&bits, &f, sizeof(float));
  111. return bits;
  112. }
  113. inline uint64_t double_to_bits(const double d) {
  114. uint64_t bits = 0;
  115. memcpy(&bits, &d, sizeof(double));
  116. return bits;
  117. }
  118. } // detail
  119. } // ryu
  120. } // detail
  121. } // namespace json
  122. } // namespace boost
  123. #endif