mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-04-14 10:07:39 +08:00
areClose() tests and docs
This commit is contained in:
parent
d4019da5ff
commit
8b73a68de8
@ -121,18 +121,24 @@ inline bool areCloseImplFirst(const L& left, const R& right, IntToType<sizeof(No
|
||||
* e.g. float with long double.
|
||||
*
|
||||
* Two objects of types A and B will be fuzzy comparable if either method is defined:
|
||||
* - bool A::isClose(const B&)
|
||||
* - bool A::isClose(B)
|
||||
* - bool B::isClose(const A&)
|
||||
* - bool B::isClose(A)
|
||||
* Alternatively, a custom specialization of this function can be defined.
|
||||
* - bool A::isClose(const B&) const
|
||||
* - bool A::isClose(B) const
|
||||
* - bool B::isClose(const A&) const
|
||||
* - bool B::isClose(A) const
|
||||
*
|
||||
* Note that all floating types and their combinations are fuzzy comparable by default:
|
||||
* - float
|
||||
* - double
|
||||
* - long double
|
||||
* Call areClose(A, B) will be dispatched as follows:
|
||||
*
|
||||
* If the arguments aren't fuzzy comparable, this function will resort to the plain comparison operator ==.
|
||||
* - If A and B are both floating point types (float, double, long double) - possibly different - the call will be
|
||||
* dispatched to @ref areFloatsClose(). If A and B are different types, value of the larger type will be coerced
|
||||
* to the smaller type, e.g. areClose(long double, float) --> areClose(float, float).
|
||||
*
|
||||
* - If A defines isClose() that accepts B, the call will be dispatched there.
|
||||
*
|
||||
* - If B defines isClose() that accepts A, the call will be dispatched there (A/B swapped).
|
||||
*
|
||||
* - Last resort is A == B.
|
||||
*
|
||||
* Alternatively, a custom behavior can be implemented via template specialization.
|
||||
*
|
||||
* See also: @ref UAVCAN_FLOAT_COMPARISON_EPSILON_MULT.
|
||||
*
|
||||
@ -143,7 +149,7 @@ inline bool areCloseImplFirst(const L& left, const R& right, IntToType<sizeof(No
|
||||
* areClose("123", std::string("123")) --> true (using std::string's operator ==)
|
||||
* areClose(inf, inf) --> true
|
||||
* areClose(inf, -inf) --> false
|
||||
* areClose(nan, nan) --> false
|
||||
* areClose(nan, nan) --> false (any comparison with nan returns false)
|
||||
* areClose(123, "123") --> compilation error: operator == is not defined
|
||||
*/
|
||||
template <typename L, typename R>
|
||||
|
||||
@ -84,3 +84,80 @@ TEST(Comparison, BruteforceValidation)
|
||||
|
||||
std::cout.precision(default_precision);
|
||||
}
|
||||
|
||||
|
||||
struct B
|
||||
{
|
||||
long double b;
|
||||
B(long double val = 0.0L) : b(val) { }
|
||||
};
|
||||
|
||||
struct A
|
||||
{
|
||||
float a;
|
||||
explicit A(float val = 0.0F) : a(val) { }
|
||||
|
||||
bool isClose(A rhs) const
|
||||
{
|
||||
std::cout << "bool A::isClose(A) --> " << rhs.a << std::endl;
|
||||
return uavcan::areClose(a, rhs.a);
|
||||
}
|
||||
|
||||
bool isClose(const B& rhs) const
|
||||
{
|
||||
std::cout << "bool A::isClose(const B&) --> " << rhs.b << std::endl;
|
||||
return uavcan::areClose(a, rhs.b);
|
||||
}
|
||||
};
|
||||
|
||||
struct C
|
||||
{
|
||||
long long c;
|
||||
explicit C(long long val = 0.0L) : c(val) { }
|
||||
|
||||
bool operator==(B rhs) const
|
||||
{
|
||||
std::cout << "bool C::operator==(B) --> " << rhs.b << std::endl;
|
||||
return c == static_cast<long long>(rhs.b);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Comparison, IsCloseMethod)
|
||||
{
|
||||
B b;
|
||||
A a;
|
||||
C c;
|
||||
|
||||
std::cout << 1 << std::endl;
|
||||
ASSERT_TRUE(uavcan::areClose(a, b)); // Fuzzy
|
||||
ASSERT_TRUE(uavcan::areClose(a, A())); // Fuzzy
|
||||
ASSERT_TRUE(uavcan::areClose(b, a)); // Fuzzy, reverse application
|
||||
ASSERT_TRUE(uavcan::areClose(c, b)); // Exact
|
||||
|
||||
std::cout << 2 << std::endl;
|
||||
|
||||
a.a = uavcan::NumericTraits<float>::epsilon();
|
||||
|
||||
ASSERT_TRUE(uavcan::areClose(a, b));
|
||||
ASSERT_TRUE(uavcan::areClose(b, a));
|
||||
ASSERT_TRUE(a.isClose(b));
|
||||
ASSERT_TRUE(a.isClose(A()));
|
||||
ASSERT_TRUE(uavcan::areClose(A(), a));
|
||||
|
||||
std::cout << 3 << std::endl;
|
||||
|
||||
a.a = 1e-5F;
|
||||
|
||||
ASSERT_FALSE(uavcan::areClose(a, b));
|
||||
ASSERT_FALSE(uavcan::areClose(b, a));
|
||||
ASSERT_FALSE(uavcan::areClose(A(), a));
|
||||
|
||||
std::cout << 4 << std::endl;
|
||||
|
||||
b.b = 1.1L;
|
||||
c.c = 1;
|
||||
|
||||
ASSERT_TRUE(uavcan::areClose(c, b)); // Round to integer
|
||||
ASSERT_TRUE(uavcan::areClose(c, 1.0L)); // Implicit cast to B
|
||||
ASSERT_FALSE(uavcan::areClose(c, 0.0L));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user