1 /* 2 * Created by Phil on 28/04/2011. 3 * Copyright 2011 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 9 #include "catch.hpp" 10 11 #include <cmath> 12 13 namespace { namespace ApproxTests { 14 15 #ifndef APPROX_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU 16 #define APPROX_TEST_HELPERS_INCLUDED 17 divide(double a,double b)18 inline double divide( double a, double b ) { 19 return a/b; 20 } 21 22 class StrongDoubleTypedef { 23 double d_ = 0.0; 24 25 public: StrongDoubleTypedef(double d)26 explicit StrongDoubleTypedef(double d) : d_(d) {} operator double() const27 explicit operator double() const { return d_; } 28 }; 29 operator <<(std::ostream & os,StrongDoubleTypedef td)30 inline std::ostream& operator<<( std::ostream& os, StrongDoubleTypedef td ) { 31 return os << "StrongDoubleTypedef(" << static_cast<double>(td) << ")"; 32 } 33 34 #endif 35 36 using namespace Catch::literals; 37 38 /////////////////////////////////////////////////////////////////////////////// 39 TEST_CASE( "A comparison that uses literals instead of the normal constructor", "[Approx]" ) { 40 double d = 1.23; 41 42 REQUIRE( d == 1.23_a ); 43 REQUIRE( d != 1.22_a ); 44 REQUIRE( -d == -1.23_a ); 45 46 REQUIRE( d == 1.2_a .epsilon(.1) ); 47 REQUIRE( d != 1.2_a .epsilon(.001) ); 48 REQUIRE( d == 1_a .epsilon(.3) ); 49 } 50 51 TEST_CASE( "Some simple comparisons between doubles", "[Approx]" ) { 52 double d = 1.23; 53 54 REQUIRE( d == Approx( 1.23 ) ); 55 REQUIRE( d != Approx( 1.22 ) ); 56 REQUIRE( d != Approx( 1.24 ) ); 57 58 REQUIRE( d == 1.23_a ); 59 REQUIRE( d != 1.22_a ); 60 61 REQUIRE( Approx( d ) == 1.23 ); 62 REQUIRE( Approx( d ) != 1.22 ); 63 REQUIRE( Approx( d ) != 1.24 ); 64 65 REQUIRE(INFINITY == Approx(INFINITY)); 66 } 67 68 /////////////////////////////////////////////////////////////////////////////// 69 TEST_CASE( "Approximate comparisons with different epsilons", "[Approx]" ) { 70 double d = 1.23; 71 72 REQUIRE( d != Approx( 1.231 ) ); 73 REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) ); 74 } 75 76 /////////////////////////////////////////////////////////////////////////////// 77 TEST_CASE( "Less-than inequalities with different epsilons", "[Approx]" ) { 78 double d = 1.23; 79 80 REQUIRE( d <= Approx( 1.24 ) ); 81 REQUIRE( d <= Approx( 1.23 ) ); 82 REQUIRE_FALSE( d <= Approx( 1.22 ) ); 83 REQUIRE( d <= Approx( 1.22 ).epsilon(0.1) ); 84 } 85 86 /////////////////////////////////////////////////////////////////////////////// 87 TEST_CASE( "Greater-than inequalities with different epsilons", "[Approx]" ) { 88 double d = 1.23; 89 90 REQUIRE( d >= Approx( 1.22 ) ); 91 REQUIRE( d >= Approx( 1.23 ) ); 92 REQUIRE_FALSE( d >= Approx( 1.24 ) ); 93 REQUIRE( d >= Approx( 1.24 ).epsilon(0.1) ); 94 } 95 96 /////////////////////////////////////////////////////////////////////////////// 97 TEST_CASE( "Approximate comparisons with floats", "[Approx]" ) { 98 REQUIRE( 1.23f == Approx( 1.23f ) ); 99 REQUIRE( 0.0f == Approx( 0.0f ) ); 100 } 101 102 /////////////////////////////////////////////////////////////////////////////// 103 TEST_CASE( "Approximate comparisons with ints", "[Approx]" ) { 104 REQUIRE( 1 == Approx( 1 ) ); 105 REQUIRE( 0 == Approx( 0 ) ); 106 } 107 108 /////////////////////////////////////////////////////////////////////////////// 109 TEST_CASE( "Approximate comparisons with mixed numeric types", "[Approx]" ) { 110 const double dZero = 0; 111 const double dSmall = 0.00001; 112 const double dMedium = 1.234; 113 114 REQUIRE( 1.0f == Approx( 1 ) ); 115 REQUIRE( 0 == Approx( dZero) ); 116 REQUIRE( 0 == Approx( dSmall ).margin( 0.001 ) ); 117 REQUIRE( 1.234f == Approx( dMedium ) ); 118 REQUIRE( dMedium == Approx( 1.234f ) ); 119 } 120 121 /////////////////////////////////////////////////////////////////////////////// 122 TEST_CASE( "Use a custom approx", "[Approx][custom]" ) { 123 double d = 1.23; 124 125 Approx approx = Approx::custom().epsilon( 0.01 ); 126 127 REQUIRE( d == approx( 1.23 ) ); 128 REQUIRE( d == approx( 1.22 ) ); 129 REQUIRE( d == approx( 1.24 ) ); 130 REQUIRE( d != approx( 1.25 ) ); 131 132 REQUIRE( approx( d ) == 1.23 ); 133 REQUIRE( approx( d ) == 1.22 ); 134 REQUIRE( approx( d ) == 1.24 ); 135 REQUIRE( approx( d ) != 1.25 ); 136 } 137 138 TEST_CASE( "Approximate PI", "[Approx][PI]" ) { 139 REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) ); 140 REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) ); 141 } 142 143 /////////////////////////////////////////////////////////////////////////////// 144 145 TEST_CASE( "Absolute margin", "[Approx]" ) { 146 REQUIRE( 104.0 != Approx(100.0) ); 147 REQUIRE( 104.0 == Approx(100.0).margin(5) ); 148 REQUIRE( 104.0 == Approx(100.0).margin(4) ); 149 REQUIRE( 104.0 != Approx(100.0).margin(3) ); 150 REQUIRE( 100.3 != Approx(100.0) ); 151 REQUIRE( 100.3 == Approx(100.0).margin(0.5) ); 152 } 153 154 TEST_CASE("Approx with exactly-representable margin", "[Approx]") { 155 CHECK( 0.25f == Approx(0.0f).margin(0.25f) ); 156 157 CHECK( 0.0f == Approx(0.25f).margin(0.25f) ); 158 CHECK( 0.5f == Approx(0.25f).margin(0.25f) ); 159 160 CHECK( 245.0f == Approx(245.25f).margin(0.25f) ); 161 CHECK( 245.5f == Approx(245.25f).margin(0.25f) ); 162 } 163 164 TEST_CASE("Approx setters validate their arguments", "[Approx]") { 165 REQUIRE_NOTHROW(Approx(0).margin(0)); 166 REQUIRE_NOTHROW(Approx(0).margin(1234656)); 167 168 REQUIRE_THROWS_AS(Approx(0).margin(-2), std::domain_error); 169 170 REQUIRE_NOTHROW(Approx(0).epsilon(0)); 171 REQUIRE_NOTHROW(Approx(0).epsilon(1)); 172 173 REQUIRE_THROWS_AS(Approx(0).epsilon(-0.001), std::domain_error); 174 REQUIRE_THROWS_AS(Approx(0).epsilon(1.0001), std::domain_error); 175 } 176 177 TEST_CASE("Default scale is invisible to comparison", "[Approx]") { 178 REQUIRE(101.000001 != Approx(100).epsilon(0.01)); 179 REQUIRE(std::pow(10, -5) != Approx(std::pow(10, -7))); 180 } 181 182 TEST_CASE("Epsilon only applies to Approx's value", "[Approx]") { 183 REQUIRE(101.01 != Approx(100).epsilon(0.01)); 184 } 185 186 TEST_CASE("Assorted miscellaneous tests", "[Approx]") { 187 REQUIRE(INFINITY == Approx(INFINITY)); 188 REQUIRE(NAN != Approx(NAN)); 189 REQUIRE_FALSE(NAN == Approx(NAN)); 190 } 191 192 TEST_CASE( "Comparison with explicitly convertible types", "[Approx]" ) 193 { 194 StrongDoubleTypedef td(10.0); 195 196 REQUIRE(td == Approx(10.0)); 197 REQUIRE(Approx(10.0) == td); 198 199 REQUIRE(td != Approx(11.0)); 200 REQUIRE(Approx(11.0) != td); 201 202 REQUIRE(td <= Approx(10.0)); 203 REQUIRE(td <= Approx(11.0)); 204 REQUIRE(Approx(10.0) <= td); 205 REQUIRE(Approx(9.0) <= td); 206 207 REQUIRE(td >= Approx(9.0)); 208 REQUIRE(td >= Approx(td)); 209 REQUIRE(Approx(td) >= td); 210 REQUIRE(Approx(11.0) >= td); 211 212 } 213 214 }} // namespace ApproxTests 215