catch_approx.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * Created by Phil on 28/04/2011.
  3. * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
  4. *
  5. * Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
  9. #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
  10. #include "catch_tostring.h"
  11. #include <type_traits>
  12. namespace Catch {
  13. namespace Detail {
  14. class Approx {
  15. private:
  16. bool equalityComparisonImpl(double other) const;
  17. // Validates the new margin (margin >= 0)
  18. // out-of-line to avoid including stdexcept in the header
  19. void setMargin(double margin);
  20. // Validates the new epsilon (0 < epsilon < 1)
  21. // out-of-line to avoid including stdexcept in the header
  22. void setEpsilon(double epsilon);
  23. public:
  24. explicit Approx ( double value );
  25. static Approx custom();
  26. Approx operator-() const;
  27. template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  28. Approx operator()( T const& value ) {
  29. Approx approx( static_cast<double>(value) );
  30. approx.m_epsilon = m_epsilon;
  31. approx.m_margin = m_margin;
  32. approx.m_scale = m_scale;
  33. return approx;
  34. }
  35. template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  36. explicit Approx( T const& value ): Approx(static_cast<double>(value))
  37. {}
  38. template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  39. friend bool operator == ( const T& lhs, Approx const& rhs ) {
  40. auto lhs_v = static_cast<double>(lhs);
  41. return rhs.equalityComparisonImpl(lhs_v);
  42. }
  43. template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  44. friend bool operator == ( Approx const& lhs, const T& rhs ) {
  45. return operator==( rhs, lhs );
  46. }
  47. template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  48. friend bool operator != ( T const& lhs, Approx const& rhs ) {
  49. return !operator==( lhs, rhs );
  50. }
  51. template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  52. friend bool operator != ( Approx const& lhs, T const& rhs ) {
  53. return !operator==( rhs, lhs );
  54. }
  55. template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  56. friend bool operator <= ( T const& lhs, Approx const& rhs ) {
  57. return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
  58. }
  59. template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  60. friend bool operator <= ( Approx const& lhs, T const& rhs ) {
  61. return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
  62. }
  63. template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  64. friend bool operator >= ( T const& lhs, Approx const& rhs ) {
  65. return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
  66. }
  67. template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  68. friend bool operator >= ( Approx const& lhs, T const& rhs ) {
  69. return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
  70. }
  71. template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  72. Approx& epsilon( T const& newEpsilon ) {
  73. double epsilonAsDouble = static_cast<double>(newEpsilon);
  74. setEpsilon(epsilonAsDouble);
  75. return *this;
  76. }
  77. template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  78. Approx& margin( T const& newMargin ) {
  79. double marginAsDouble = static_cast<double>(newMargin);
  80. setMargin(marginAsDouble);
  81. return *this;
  82. }
  83. template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
  84. Approx& scale( T const& newScale ) {
  85. m_scale = static_cast<double>(newScale);
  86. return *this;
  87. }
  88. std::string toString() const;
  89. private:
  90. double m_epsilon;
  91. double m_margin;
  92. double m_scale;
  93. double m_value;
  94. };
  95. } // end namespace Detail
  96. namespace literals {
  97. Detail::Approx operator "" _a(long double val);
  98. Detail::Approx operator "" _a(unsigned long long val);
  99. } // end namespace literals
  100. template<>
  101. struct StringMaker<Catch::Detail::Approx> {
  102. static std::string convert(Catch::Detail::Approx const& value);
  103. };
  104. } // end namespace Catch
  105. #endif // TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED