pow10_helper_test.cc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright 2018 The Abseil Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "absl/strings/internal/pow10_helper.h"
  15. #include <cmath>
  16. #include "gtest/gtest.h"
  17. #include "absl/strings/str_format.h"
  18. namespace absl {
  19. ABSL_NAMESPACE_BEGIN
  20. namespace strings_internal {
  21. namespace {
  22. struct TestCase {
  23. int power; // Testing Pow10(power)
  24. uint64_t significand; // Raw bits of the expected value
  25. int radix; // significand is adjusted by 2^radix
  26. };
  27. TEST(Pow10HelperTest, Works) {
  28. // The logic in pow10_helper.cc is so simple that theoretically we don't even
  29. // need a test. However, we're paranoid and believe that there may be
  30. // compilers that don't round floating-point literals correctly, even though
  31. // it is specified by the standard. We check various edge cases, just to be
  32. // sure.
  33. constexpr TestCase kTestCases[] = {
  34. // Subnormals
  35. {-323, 0x2, -1074},
  36. {-322, 0x14, -1074},
  37. {-321, 0xca, -1074},
  38. {-320, 0x7e8, -1074},
  39. {-319, 0x4f10, -1074},
  40. {-318, 0x316a2, -1074},
  41. {-317, 0x1ee257, -1074},
  42. {-316, 0x134d761, -1074},
  43. {-315, 0xc1069cd, -1074},
  44. {-314, 0x78a42205, -1074},
  45. {-313, 0x4b6695433, -1074},
  46. {-312, 0x2f201d49fb, -1074},
  47. {-311, 0x1d74124e3d1, -1074},
  48. {-310, 0x12688b70e62b, -1074},
  49. {-309, 0xb8157268fdaf, -1074},
  50. {-308, 0x730d67819e8d2, -1074},
  51. // Values that are very close to rounding the other way.
  52. // Comment shows difference of significand from the true value.
  53. {-307, 0x11fa182c40c60d, -1072}, // -.4588
  54. {-290, 0x18f2b061aea072, -1016}, // .4854
  55. {-276, 0x11BA03F5B21000, -969}, // .4709
  56. {-259, 0x1899C2F6732210, -913}, // .4830
  57. {-252, 0x1D53844EE47DD1, -890}, // -.4743
  58. {-227, 0x1E5297287C2F45, -807}, // -.4708
  59. {-198, 0x1322E220A5B17E, -710}, // -.4714
  60. {-195, 0x12B010D3E1CF56, -700}, // .4928
  61. {-192, 0x123FF06EEA847A, -690}, // .4968
  62. {-163, 0x1708D0F84D3DE7, -594}, // -.4977
  63. {-145, 0x13FAAC3E3FA1F3, -534}, // -.4785
  64. {-111, 0x133D4032C2C7F5, -421}, // .4774
  65. {-106, 0x1D5B561574765B, -405}, // -.4869
  66. {-104, 0x16EF5B40C2FC77, -398}, // -.4741
  67. {-88, 0x197683DF2F268D, -345}, // -.4738
  68. {-86, 0x13E497065CD61F, -338}, // .4736
  69. {-76, 0x17288E1271F513, -305}, // -.4761
  70. {-63, 0x1A53FC9631D10D, -262}, // .4929
  71. {-30, 0x14484BFEEBC2A0, -152}, // .4758
  72. {-21, 0x12E3B40A0E9B4F, -122}, // -.4916
  73. {-5, 0x14F8B588E368F1, -69}, // .4829
  74. {23, 0x152D02C7E14AF6, 24}, // -.5000 (exactly, round-to-even)
  75. {29, 0x1431E0FAE6D721, 44}, // -.4870
  76. {34, 0x1ED09BEAD87C03, 60}, // -.4721
  77. {70, 0x172EBAD6DDC73D, 180}, // .4733
  78. {105, 0x1BE7ABD3781ECA, 296}, // -.4850
  79. {126, 0x17A2ECC414A03F, 366}, // -.4999
  80. {130, 0x1CDA62055B2D9E, 379}, // .4855
  81. {165, 0x115D847AD00087, 496}, // -.4913
  82. {172, 0x14B378469B6732, 519}, // .4818
  83. {187, 0x1262DFEEBBB0F9, 569}, // -.4805
  84. {210, 0x18557F31326BBB, 645}, // -.4992
  85. {212, 0x1302CB5E6F642A, 652}, // -.4838
  86. {215, 0x1290BA9A38C7D1, 662}, // -.4881
  87. {236, 0x1F736F9B3494E9, 731}, // .4707
  88. {244, 0x176EC98994F489, 758}, // .4924
  89. {250, 0x1658E3AB795204, 778}, // -.4963
  90. {252, 0x117571DDF6C814, 785}, // .4873
  91. {254, 0x1B4781EAD1989E, 791}, // -.4887
  92. {260, 0x1A03FDE214CAF1, 811}, // .4784
  93. {284, 0x1585041B2C477F, 891}, // .4798
  94. {304, 0x1D2A1BE4048F90, 957}, // -.4987
  95. // Out-of-range values
  96. {-324, 0x0, 0},
  97. {-325, 0x0, 0},
  98. {-326, 0x0, 0},
  99. {309, 1, 2000},
  100. {310, 1, 2000},
  101. {311, 1, 2000},
  102. };
  103. for (const TestCase& test_case : kTestCases) {
  104. EXPECT_EQ(Pow10(test_case.power),
  105. std::ldexp(test_case.significand, test_case.radix))
  106. << absl::StrFormat("Failure for Pow10(%d): %a vs %a", test_case.power,
  107. Pow10(test_case.power),
  108. std::ldexp(test_case.significand, test_case.radix));
  109. }
  110. }
  111. } // namespace
  112. } // namespace strings_internal
  113. ABSL_NAMESPACE_END
  114. } // namespace absl