Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UAVCAN UAVCAN_Subscriber
comparison.cpp
00001 /* 00002 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #include <gtest/gtest.h> 00006 #include <uavcan/util/comparison.hpp> 00007 00008 TEST(Comparison, Basic) 00009 { 00010 // Basic same type floats 00011 ASSERT_TRUE(uavcan::areClose(0.1, 0.1)); 00012 ASSERT_TRUE(uavcan::areClose(0.1F, 0.1F)); 00013 ASSERT_TRUE(uavcan::areClose(0.1L, 0.1L)); 00014 00015 // Basic mixed type floats 00016 ASSERT_TRUE(uavcan::areClose(0.1F, 0.1)); 00017 ASSERT_TRUE(uavcan::areClose(0.1, 0.1F)); 00018 ASSERT_TRUE(uavcan::areClose(0.1F, 0.1L)); 00019 ASSERT_TRUE(uavcan::areClose(0.1L, 0.1F)); 00020 ASSERT_TRUE(uavcan::areClose(0.1, 0.1L)); 00021 ASSERT_TRUE(uavcan::areClose(0.1L, 0.1)); 00022 00023 // Basic floats 00024 ASSERT_TRUE(uavcan::areClose(0x07, '\x07')); 00025 ASSERT_TRUE(uavcan::areClose(123456789LL, 123456789)); 00026 ASSERT_TRUE(uavcan::areClose("123", std::string("123"))); 00027 00028 // Non-equality 00029 ASSERT_FALSE(uavcan::areClose(-0.1, 0.1)); 00030 ASSERT_FALSE(uavcan::areClose(-0.1F, 0.0L)); 00031 ASSERT_FALSE(uavcan::areClose("123", std::string("12"))); 00032 ASSERT_FALSE(uavcan::areClose(0x07L, '\0')); 00033 } 00034 00035 TEST(Comparison, FloatSpecialCase) 00036 { 00037 ASSERT_FALSE(uavcan::areClose(0.1, std::numeric_limits<double>::infinity())); 00038 00039 ASSERT_TRUE(uavcan::areClose(std::numeric_limits<float>::infinity(), 00040 std::numeric_limits<long double>::infinity())); 00041 00042 ASSERT_FALSE(uavcan::areClose(std::numeric_limits<float>::infinity(), -std::numeric_limits<float>::infinity())); 00043 00044 ASSERT_FALSE(uavcan::areClose(std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN())); 00045 } 00046 00047 TEST(Comparison, FloatULP) 00048 { 00049 ASSERT_FALSE(uavcan::areClose(0.100000000000000001L, 0.1L)); 00050 ASSERT_TRUE( uavcan::areClose(0.100000000000000001, 0.1L)); 00051 ASSERT_TRUE( uavcan::areClose(0.100000000000000001F, 0.1L)); 00052 00053 // Near zero 00054 ASSERT_TRUE( uavcan::areClose(0.0F, std::numeric_limits<float>::epsilon())); 00055 ASSERT_TRUE( uavcan::areClose(0.0F, -std::numeric_limits<float>::epsilon())); 00056 ASSERT_FALSE(uavcan::areClose(0.0F, std::numeric_limits<float>::epsilon() * 2)); 00057 } 00058 00059 TEST(Comparison, BruteforceValidation) 00060 { 00061 const std::streamsize default_precision = std::cout.precision(); 00062 std::cout.precision(20); 00063 00064 float x = -uavcan::NumericTraits<float>::max(); 00065 00066 while (x < uavcan::NumericTraits<float>::max()) 00067 { 00068 const float y1 = x + std::abs(x) * (uavcan::NumericTraits<float>::epsilon() * 2); // Still equal 00069 const float y2 = x + uavcan::max(std::abs(x), 1.F) * (uavcan::NumericTraits<float>::epsilon() * 20); // Nope 00070 00071 if (!uavcan::areClose(y1, x)) 00072 { 00073 std::cout << "y1=" << y1 << " y2=" << y2 << " x=" << x << std::endl; 00074 ASSERT_TRUE(false); 00075 } 00076 if (uavcan::areClose(y2, x)) 00077 { 00078 std::cout << "y1=" << y1 << " y2=" << y2 << " x=" << x << std::endl; 00079 ASSERT_TRUE(false); 00080 } 00081 00082 x = y2; 00083 } 00084 00085 std::cout.precision(default_precision); 00086 } 00087 00088 00089 struct B 00090 { 00091 long double b; 00092 B(long double val = 0.0L) : b(val) { } 00093 }; 00094 00095 struct A 00096 { 00097 float a; 00098 explicit A(float val = 0.0F) : a(val) { } 00099 00100 bool isClose(A rhs) const 00101 { 00102 std::cout << "bool A::isClose(A) --> " << rhs.a << std::endl; 00103 return uavcan::areClose(a, rhs.a); 00104 } 00105 00106 bool isClose(const B& rhs) const 00107 { 00108 std::cout << "bool A::isClose(const B&) --> " << rhs.b << std::endl; 00109 return uavcan::areClose(a, rhs.b); 00110 } 00111 }; 00112 00113 struct C 00114 { 00115 long long c; 00116 explicit C(long long val = 0.0L) : c(val) { } 00117 00118 bool operator==(B rhs) const 00119 { 00120 std::cout << "bool C::operator==(B) --> " << rhs.b << std::endl; 00121 return c == static_cast<long long>(rhs.b); 00122 } 00123 }; 00124 00125 TEST(Comparison, IsCloseMethod) 00126 { 00127 B b; 00128 A a; 00129 C c; 00130 00131 std::cout << 1 << std::endl; 00132 ASSERT_TRUE(uavcan::areClose(a, b)); // Fuzzy 00133 ASSERT_TRUE(uavcan::areClose(a, A())); // Fuzzy 00134 ASSERT_TRUE(uavcan::areClose(b, a)); // Fuzzy, reverse application 00135 ASSERT_TRUE(uavcan::areClose(c, b)); // Exact 00136 00137 std::cout << 2 << std::endl; 00138 00139 a.a = uavcan::NumericTraits<float>::epsilon(); 00140 00141 ASSERT_TRUE(uavcan::areClose(a, b)); 00142 ASSERT_TRUE(uavcan::areClose(b, a)); 00143 ASSERT_TRUE(a.isClose(b)); 00144 ASSERT_TRUE(a.isClose(A())); 00145 ASSERT_TRUE(uavcan::areClose(A(), a)); 00146 00147 std::cout << 3 << std::endl; 00148 00149 a.a = 1e-5F; 00150 00151 ASSERT_FALSE(uavcan::areClose(a, b)); 00152 ASSERT_FALSE(uavcan::areClose(b, a)); 00153 ASSERT_FALSE(uavcan::areClose(A(), a)); 00154 00155 std::cout << 4 << std::endl; 00156 00157 b.b = 1.1L; 00158 c.c = 1; 00159 00160 ASSERT_TRUE(uavcan::areClose(c, b)); // Round to integer 00161 ASSERT_TRUE(uavcan::areClose(c, 1.0L)); // Implicit cast to B 00162 ASSERT_FALSE(uavcan::areClose(c, 0.0L)); 00163 }
Generated on Tue Jul 12 2022 17:17:30 by
1.7.2