TestStringFloatingPointConversions.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /*
  2. * Copyright (c) 2022, Dan Klishch <danilklishch@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/BitCast.h>
  7. #include <AK/StringFloatingPointConversions.h>
  8. #include <LibTest/TestCase.h>
  9. namespace AK {
  10. static bool operator!=(FloatingPointExponentialForm a, FloatingPointExponentialForm b)
  11. {
  12. return a.sign != b.sign || a.exponent != b.exponent || a.fraction != b.fraction;
  13. }
  14. }
  15. template<>
  16. struct AK::Formatter<AK::FloatingPointExponentialForm> : Formatter<FormatString> {
  17. ErrorOr<void> format(FormatBuilder& builder, AK::FloatingPointExponentialForm value)
  18. {
  19. return Formatter<FormatString>::format(builder, "(s={} f={} e={})"sv, value.sign, value.fraction, value.exponent);
  20. }
  21. };
  22. #define DOES_CONVERT_DOUBLE_TO(value, sign, fraction, exponent) \
  23. do { \
  24. EXPECT_EQ( \
  25. convert_floating_point_to_decimal_exponential_form(static_cast<double>(value)), \
  26. (AK::FloatingPointExponentialForm { sign, fraction, exponent })); \
  27. } while (false)
  28. // Tests here only check basic cases. While writing, I mostly relied on the benchmarks and
  29. // stress tests, which can be found at https://github.com/DanShaders/serenity-arithmetic-benchmark/blob/master/StringFloatingPointConversions.cpp .
  30. TEST_CASE(double_conversion)
  31. {
  32. DOES_CONVERT_DOUBLE_TO(0, 0, 0, 0);
  33. DOES_CONVERT_DOUBLE_TO(-0., 1, 0, 0);
  34. DOES_CONVERT_DOUBLE_TO(1, 0, 1, 0);
  35. DOES_CONVERT_DOUBLE_TO(-1, 1, 1, 0);
  36. DOES_CONVERT_DOUBLE_TO(.1, 0, 1, -1);
  37. DOES_CONVERT_DOUBLE_TO(.2, 0, 2, -1);
  38. DOES_CONVERT_DOUBLE_TO(.3, 0, 3, -1);
  39. DOES_CONVERT_DOUBLE_TO(.12345, 0, 12345, -5);
  40. DOES_CONVERT_DOUBLE_TO(.0012345, 0, 12345, -7);
  41. DOES_CONVERT_DOUBLE_TO(.1 + .2, 0, 30000000000000004, -17);
  42. DOES_CONVERT_DOUBLE_TO(17976931348623157e292, 0, 17976931348623157, 292);
  43. DOES_CONVERT_DOUBLE_TO(-17976931348623157e292, 1, 17976931348623157, 292);
  44. DOES_CONVERT_DOUBLE_TO(22250738585072014e-324, 0, 22250738585072014, -324);
  45. DOES_CONVERT_DOUBLE_TO(-22250738585072014e-324, 1, 22250738585072014, -324);
  46. DOES_CONVERT_DOUBLE_TO(bit_cast<double>(0xc3c04222300db8acULL), 1, 23430728857074627, 2);
  47. }
  48. #define DOES_CONVERT_FLOAT_TO(value, sign, fraction, exponent) \
  49. do { \
  50. EXPECT_EQ( \
  51. convert_floating_point_to_decimal_exponential_form(static_cast<float>(value)), \
  52. (AK::FloatingPointExponentialForm { sign, fraction, exponent })); \
  53. } while (false)
  54. TEST_CASE(float_conversion)
  55. {
  56. DOES_CONVERT_FLOAT_TO(0, 0, 0, 0);
  57. DOES_CONVERT_FLOAT_TO(-0., 1, 0, 0);
  58. DOES_CONVERT_FLOAT_TO(1, 0, 1, 0);
  59. DOES_CONVERT_FLOAT_TO(-1, 1, 1, 0);
  60. DOES_CONVERT_FLOAT_TO(.1, 0, 1, -1);
  61. DOES_CONVERT_FLOAT_TO(.2, 0, 2, -1);
  62. DOES_CONVERT_FLOAT_TO(.3, 0, 3, -1);
  63. DOES_CONVERT_FLOAT_TO(0.025, 0, 25, -3);
  64. DOES_CONVERT_FLOAT_TO(34028235e31, 0, 34028235, 31);
  65. DOES_CONVERT_FLOAT_TO(-34028235e31, 1, 34028235, 31);
  66. DOES_CONVERT_FLOAT_TO(11754944e-45, 0, 11754944, -45);
  67. DOES_CONVERT_FLOAT_TO(-11754944e-45, 1, 11754944, -45);
  68. }