ylimits_ut.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include "cast.h"
  2. #include "ylimits.h"
  3. #include <library/cpp/testing/unittest/registar.h>
  4. #include <util/system/valgrind.h>
  5. class TLimitTest: public TTestBase {
  6. UNIT_TEST_SUITE(TLimitTest);
  7. UNIT_TEST(TestLimits);
  8. UNIT_TEST(TestNan);
  9. UNIT_TEST(TestMaxDouble);
  10. UNIT_TEST_SUITE_END();
  11. protected:
  12. void TestLimits();
  13. void TestNan();
  14. void TestMaxDouble();
  15. };
  16. UNIT_TEST_SUITE_REGISTRATION(TLimitTest);
  17. #define CHECK_COND(X) UNIT_ASSERT(X)
  18. static inline bool ValidSignInfo(bool, bool) {
  19. return true;
  20. }
  21. template <class T>
  22. static inline bool ValidSignInfo(bool limitIsSigned, const T&) {
  23. return limitIsSigned && IsNegative(T(-1)) || !limitIsSigned && !IsNegative(T(-1));
  24. }
  25. template <class T>
  26. static inline bool TestIntegralLimits(const T&, bool unknownSign = true, bool isSigned = true) {
  27. using lim = std::numeric_limits<T>;
  28. CHECK_COND(lim::is_specialized);
  29. CHECK_COND(lim::is_integer);
  30. CHECK_COND(lim::min() < lim::max());
  31. CHECK_COND((unknownSign && ((lim::is_signed && (lim::min() != 0)) || (!lim::is_signed && (lim::min() == 0)))) ||
  32. (!unknownSign && ((lim::is_signed && isSigned) || (!lim::is_signed && !isSigned))));
  33. T min = Min();
  34. UNIT_ASSERT_EQUAL(lim::min(), min);
  35. T max = Max();
  36. UNIT_ASSERT_EQUAL(lim::max(), max);
  37. if (unknownSign) {
  38. CHECK_COND(ValidSignInfo(lim::is_signed, T()));
  39. }
  40. return true;
  41. }
  42. template <class T>
  43. static inline bool TestSignedIntegralLimits(const T& val) {
  44. return TestIntegralLimits(val, false, true);
  45. }
  46. template <class T>
  47. static inline bool TestUnsignedIntegralLimits(const T& val) {
  48. return TestIntegralLimits(val, false, false);
  49. }
  50. template <class T>
  51. static inline bool TestFloatLimits(const T&) {
  52. using lim = std::numeric_limits<T>;
  53. CHECK_COND(lim::is_specialized);
  54. CHECK_COND(!lim::is_modulo);
  55. CHECK_COND(!lim::is_integer);
  56. CHECK_COND(lim::is_signed);
  57. CHECK_COND(lim::max() > 1000);
  58. CHECK_COND(lim::min() > 0);
  59. CHECK_COND(lim::min() < 0.001);
  60. CHECK_COND(lim::epsilon() > 0);
  61. if (lim::is_iec559) {
  62. CHECK_COND(lim::has_infinity);
  63. CHECK_COND(lim::has_quiet_NaN);
  64. CHECK_COND(lim::has_signaling_NaN);
  65. }
  66. if (lim::has_infinity) {
  67. const T infinity = lim::infinity();
  68. CHECK_COND(infinity > lim::max());
  69. CHECK_COND(-infinity < -lim::max());
  70. }
  71. return true;
  72. }
  73. template <class T>
  74. static inline bool TestNan(const T&) {
  75. using lim = std::numeric_limits<T>;
  76. if (lim::has_quiet_NaN) {
  77. const T qnan = lim::quiet_NaN();
  78. CHECK_COND(!(qnan == 42));
  79. CHECK_COND(!(qnan == qnan));
  80. CHECK_COND(qnan != 42);
  81. CHECK_COND(qnan != qnan);
  82. }
  83. return true;
  84. }
  85. void TLimitTest::TestLimits() {
  86. UNIT_ASSERT(TestIntegralLimits(bool()));
  87. UNIT_ASSERT(TestIntegralLimits(char()));
  88. using signed_char = signed char;
  89. UNIT_ASSERT(TestSignedIntegralLimits(signed_char()));
  90. using unsigned_char = unsigned char;
  91. UNIT_ASSERT(TestUnsignedIntegralLimits(unsigned_char()));
  92. UNIT_ASSERT(TestSignedIntegralLimits(short()));
  93. using unsigned_short = unsigned short;
  94. UNIT_ASSERT(TestUnsignedIntegralLimits(unsigned_short()));
  95. UNIT_ASSERT(TestSignedIntegralLimits(int()));
  96. using unsigned_int = unsigned int;
  97. UNIT_ASSERT(TestUnsignedIntegralLimits(unsigned_int()));
  98. UNIT_ASSERT(TestSignedIntegralLimits(long()));
  99. using unsigned_long = unsigned long;
  100. UNIT_ASSERT(TestUnsignedIntegralLimits(unsigned_long()));
  101. using long_long = long long;
  102. UNIT_ASSERT(TestSignedIntegralLimits(long_long()));
  103. using unsigned_long_long = unsigned long long;
  104. UNIT_ASSERT(TestUnsignedIntegralLimits(unsigned_long_long()));
  105. UNIT_ASSERT(TestFloatLimits(float()));
  106. UNIT_ASSERT(TestFloatLimits(double()));
  107. using long_double = long double;
  108. UNIT_ASSERT(RUNNING_ON_VALGRIND || TestFloatLimits(long_double()));
  109. }
  110. void TLimitTest::TestNan() {
  111. UNIT_ASSERT(::TestNan(float()));
  112. UNIT_ASSERT(::TestNan(double()));
  113. using long_double = long double;
  114. UNIT_ASSERT(::TestNan(long_double()));
  115. }
  116. void TLimitTest::TestMaxDouble() {
  117. UNIT_ASSERT_VALUES_EQUAL(MaxCeil<i8>(), 127.0);
  118. UNIT_ASSERT_VALUES_EQUAL(MaxFloor<i8>(), 127.0);
  119. UNIT_ASSERT_VALUES_EQUAL(MaxCeil<ui8>(), 255.0);
  120. UNIT_ASSERT_VALUES_EQUAL(MaxFloor<ui8>(), 255.0);
  121. double d = 1ull << 63;
  122. UNIT_ASSERT_VALUES_EQUAL(MaxCeil<i64>(), d);
  123. UNIT_ASSERT_VALUES_EQUAL(MaxFloor<i64>(), nextafter(d, 0));
  124. d *= 2;
  125. UNIT_ASSERT_VALUES_EQUAL(MaxCeil<ui64>(), d);
  126. UNIT_ASSERT_VALUES_EQUAL(MaxFloor<ui64>(), nextafter(d, 0));
  127. }