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 66 /////////////////////////////////////////////////////////////////////////////// 67 TEST_CASE( "Approximate comparisons with different epsilons", "[Approx]" ) { 68 double d = 1.23; 69 70 REQUIRE( d != Approx( 1.231 ) ); 71 REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) ); 72 } 73 74 /////////////////////////////////////////////////////////////////////////////// 75 TEST_CASE( "Less-than inequalities with different epsilons", "[Approx]" ) { 76 double d = 1.23; 77 78 REQUIRE( d <= Approx( 1.24 ) ); 79 REQUIRE( d <= Approx( 1.23 ) ); 80 REQUIRE_FALSE( d <= Approx( 1.22 ) ); 81 REQUIRE( d <= Approx( 1.22 ).epsilon(0.1) ); 82 } 83 84 /////////////////////////////////////////////////////////////////////////////// 85 TEST_CASE( "Greater-than inequalities with different epsilons", "[Approx]" ) { 86 double d = 1.23; 87 88 REQUIRE( d >= Approx( 1.22 ) ); 89 REQUIRE( d >= Approx( 1.23 ) ); 90 REQUIRE_FALSE( d >= Approx( 1.24 ) ); 91 REQUIRE( d >= Approx( 1.24 ).epsilon(0.1) ); 92 } 93 94 /////////////////////////////////////////////////////////////////////////////// 95 TEST_CASE( "Approximate comparisons with floats", "[Approx]" ) { 96 REQUIRE( 1.23f == Approx( 1.23f ) ); 97 REQUIRE( 0.0f == Approx( 0.0f ) ); 98 } 99 100 /////////////////////////////////////////////////////////////////////////////// 101 TEST_CASE( "Approximate comparisons with ints", "[Approx]" ) { 102 REQUIRE( 1 == Approx( 1 ) ); 103 REQUIRE( 0 == Approx( 0 ) ); 104 } 105 106 /////////////////////////////////////////////////////////////////////////////// 107 TEST_CASE( "Approximate comparisons with mixed numeric types", "[Approx]" ) { 108 const double dZero = 0; 109 const double dSmall = 0.00001; 110 const double dMedium = 1.234; 111 112 REQUIRE( 1.0f == Approx( 1 ) ); 113 REQUIRE( 0 == Approx( dZero) ); 114 REQUIRE( 0 == Approx( dSmall ).margin( 0.001 ) ); 115 REQUIRE( 1.234f == Approx( dMedium ) ); 116 REQUIRE( dMedium == Approx( 1.234f ) ); 117 } 118 119 /////////////////////////////////////////////////////////////////////////////// 120 TEST_CASE( "Use a custom approx", "[Approx][custom]" ) { 121 double d = 1.23; 122 123 Approx approx = Approx::custom().epsilon( 0.01 ); 124 125 REQUIRE( d == approx( 1.23 ) ); 126 REQUIRE( d == approx( 1.22 ) ); 127 REQUIRE( d == approx( 1.24 ) ); 128 REQUIRE( d != approx( 1.25 ) ); 129 130 REQUIRE( approx( d ) == 1.23 ); 131 REQUIRE( approx( d ) == 1.22 ); 132 REQUIRE( approx( d ) == 1.24 ); 133 REQUIRE( approx( d ) != 1.25 ); 134 } 135 136 TEST_CASE( "Approximate PI", "[Approx][PI]" ) { 137 REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) ); 138 REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) ); 139 } 140 141 /////////////////////////////////////////////////////////////////////////////// 142 143 TEST_CASE( "Absolute margin", "[Approx]" ) { 144 REQUIRE( 104.0 != Approx(100.0) ); 145 REQUIRE( 104.0 == Approx(100.0).margin(5) ); 146 REQUIRE( 104.0 == Approx(100.0).margin(4) ); 147 REQUIRE( 104.0 != Approx(100.0).margin(3) ); 148 REQUIRE( 100.3 != Approx(100.0) ); 149 REQUIRE( 100.3 == Approx(100.0).margin(0.5) ); 150 } 151 152 TEST_CASE("Approx with exactly-representable margin", "[Approx]") { 153 CHECK( 0.25f == Approx(0.0f).margin(0.25f) ); 154 155 CHECK( 0.0f == Approx(0.25f).margin(0.25f) ); 156 CHECK( 0.5f == Approx(0.25f).margin(0.25f) ); 157 158 CHECK( 245.0f == Approx(245.25f).margin(0.25f) ); 159 CHECK( 245.5f == Approx(245.25f).margin(0.25f) ); 160 } 161 162 TEST_CASE("Approx setters validate their arguments", "[Approx]") { 163 REQUIRE_NOTHROW(Approx(0).margin(0)); 164 REQUIRE_NOTHROW(Approx(0).margin(1234656)); 165 166 REQUIRE_THROWS_AS(Approx(0).margin(-2), std::domain_error); 167 168 REQUIRE_NOTHROW(Approx(0).epsilon(0)); 169 REQUIRE_NOTHROW(Approx(0).epsilon(1)); 170 171 REQUIRE_THROWS_AS(Approx(0).epsilon(-0.001), std::domain_error); 172 REQUIRE_THROWS_AS(Approx(0).epsilon(1.0001), std::domain_error); 173 } 174 175 TEST_CASE("Default scale is invisible to comparison", "[Approx]") { 176 REQUIRE(101.000001 != Approx(100).epsilon(0.01)); 177 REQUIRE(std::pow(10, -5) != Approx(std::pow(10, -7))); 178 } 179 180 TEST_CASE("Epsilon only applies to Approx's value", "[Approx]") { 181 REQUIRE(101.01 != Approx(100).epsilon(0.01)); 182 } 183 184 TEST_CASE("Assorted miscellaneous tests", "[Approx][approvals]") { 185 REQUIRE(INFINITY == Approx(INFINITY)); 186 REQUIRE(-INFINITY != Approx(INFINITY)); 187 REQUIRE(1 != Approx(INFINITY)); 188 REQUIRE(INFINITY != Approx(1)); 189 REQUIRE(NAN != Approx(NAN)); 190 REQUIRE_FALSE(NAN == Approx(NAN)); 191 } 192 193 TEST_CASE( "Comparison with explicitly convertible types", "[Approx]" ) 194 { 195 StrongDoubleTypedef td(10.0); 196 197 REQUIRE(td == Approx(10.0)); 198 REQUIRE(Approx(10.0) == td); 199 200 REQUIRE(td != Approx(11.0)); 201 REQUIRE(Approx(11.0) != td); 202 203 REQUIRE(td <= Approx(10.0)); 204 REQUIRE(td <= Approx(11.0)); 205 REQUIRE(Approx(10.0) <= td); 206 REQUIRE(Approx(9.0) <= td); 207 208 REQUIRE(td >= Approx(9.0)); 209 REQUIRE(td >= Approx(td)); 210 REQUIRE(Approx(td) >= td); 211 REQUIRE(Approx(11.0) >= td); 212 213 } 214 215 }} // namespace ApproxTests 216