arithmetic.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #include "simple/support/arithmetic.hpp"
  2. #include <cassert>
  3. #include <limits>
  4. using namespace simple::support;
  5. using Largest = unsigned long long;
  6. template <typename Unsigned>
  7. void checkUnsigned()
  8. {
  9. Unsigned result;
  10. const auto max = std::numeric_limits<Unsigned>::max();
  11. const auto min = std::numeric_limits<Unsigned>::min();
  12. const Unsigned half = max/2;
  13. const Unsigned quart = max/4;
  14. assert(add_overflow(result, max, Unsigned(1)));
  15. assert(min == result);
  16. assert(!add_overflow(result, half, quart));
  17. assert(Largest(half) + Largest(quart) == result);
  18. assert(sub_overflow(result, min, Unsigned(1)));
  19. assert(max == result);
  20. assert(!sub_overflow(result, half, quart));
  21. assert(Largest(half) - Largest(quart) == result);
  22. assert(mul_overflow(result, quart, Unsigned(6)));
  23. assert(Unsigned(Largest(quart) * 6ull) == result);
  24. assert(!mul_overflow(result, quart, Unsigned(3)));
  25. assert(Largest(quart) * 3ull == result);
  26. }
  27. template <typename Signed>
  28. void checkSigned()
  29. {
  30. checkUnsigned<Signed>();
  31. Signed result;
  32. const auto max = std::numeric_limits<Signed>::max();
  33. const auto min = std::numeric_limits<Signed>::min();
  34. const Signed half = max/2;
  35. const Signed quart = max/4;
  36. // complementary negative number tests
  37. assert(add_overflow(result, min, Signed(-1)));
  38. assert(max == result);
  39. assert(sub_overflow(result, max, Signed(-1)));
  40. assert(min == result);
  41. assert(!add_overflow(result, Signed(-half), Signed(-quart)));
  42. assert(Largest(half) + Largest(quart) == Signed(-result));
  43. assert(!sub_overflow(result, Signed(-half), Signed(-quart)));
  44. assert(Largest(half) - Largest(quart) == Signed(-result));
  45. assert(mul_overflow(result, Signed(-quart), Signed(6)));
  46. assert(Signed(Largest(-quart) * Largest(6)) == result);
  47. assert(mul_overflow(result, quart, Signed(-6)));
  48. assert(Signed(Largest(quart) * Largest(-6)) == result);
  49. // crossing zero tests
  50. assert(!add_overflow(result, Signed(-quart), half));
  51. assert(half - quart == result);
  52. assert(!add_overflow(result, quart, Signed(-half)));
  53. assert(quart - half == result);
  54. assert(!sub_overflow(result, Signed(-quart), Signed(-half)));
  55. assert(half - quart == result);
  56. assert(!sub_overflow(result, quart, half));
  57. assert(quart - half == result);
  58. assert(!mul_overflow(result, Signed(-quart), Signed(-2)));
  59. assert(Signed(Largest(-quart) * Largest(-2)) == result);
  60. assert(!mul_overflow(result, Signed(quart), Signed(-2)));
  61. assert(Signed(Largest(quart) * Largest(-2)) == result);
  62. }
  63. void Overflow()
  64. {
  65. checkUnsigned<unsigned char>();
  66. checkUnsigned<unsigned short>();
  67. checkUnsigned<unsigned int>();
  68. checkUnsigned<unsigned long>();
  69. checkUnsigned<unsigned long long>();
  70. #if defined SIMPLE_ASSUME_SIGNED_OVERFLOW_DEFINED
  71. checkSigned<signed char>();
  72. checkSigned<signed short>();
  73. checkSigned<signed int>();
  74. checkSigned<signed long>();
  75. checkSigned<signed long long>();
  76. #endif
  77. }
  78. int main()
  79. {
  80. Overflow();
  81. return 0;
  82. }