mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-05-17 05:37:35 +08:00
Make wrap() work with integer types (#145)
* Make wrap() work with integers
This commit is contained in:
committed by
GitHub
parent
25c0455348
commit
cd8ad1584c
+50
-11
@@ -39,25 +39,64 @@ bool isEqualF(const Type x, const Type y, const Type eps = 1e-4f)
|
||||
|| (isinf(x) && isinf(y) && isnan(x - y));
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename Floating>
|
||||
Floating wrap_floating(Floating x, Floating low, Floating high) {
|
||||
// already in range
|
||||
if (low <= x && x < high) {
|
||||
return x;
|
||||
}
|
||||
|
||||
const auto range = high - low;
|
||||
const auto inv_range = Floating(1) / range; // should evaluate at compile time, multiplies below at runtime
|
||||
const auto num_wraps = floor((x - low) * inv_range);
|
||||
return x - range * num_wraps;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Wrap value to stay in range [low, high)
|
||||
* Wrap single precision floating point value to stay in range [low, high)
|
||||
*
|
||||
* @param x input possibly outside of the range
|
||||
* @param low lower limit of the allowed range
|
||||
* @param high upper limit of the allowed range
|
||||
* @return wrapped value inside the range
|
||||
*/
|
||||
template<typename Type>
|
||||
Type wrap(Type x, Type low, Type high) {
|
||||
// already in range
|
||||
if (low <= x && x < high) {
|
||||
return x;
|
||||
}
|
||||
float wrap(float x, float low, float high) {
|
||||
return matrix::detail::wrap_floating(x, low, high);
|
||||
}
|
||||
|
||||
const Type range = high - low;
|
||||
const Type inv_range = Type(1) / range; // should evaluate at compile time, multiplies below at runtime
|
||||
const Type num_wraps = floor((x - low) * inv_range);
|
||||
return x - range * num_wraps;
|
||||
/**
|
||||
* Wrap double precision floating point value to stay in range [low, high)
|
||||
*
|
||||
* @param x input possibly outside of the range
|
||||
* @param low lower limit of the allowed range
|
||||
* @param high upper limit of the allowed range
|
||||
* @return wrapped value inside the range
|
||||
*/
|
||||
double wrap(double x, double low, double high) {
|
||||
return matrix::detail::wrap_floating(x, low, high);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap integer value to stay in range [low, high)
|
||||
*
|
||||
* @param x input possibly outside of the range
|
||||
* @param low lower limit of the allowed range
|
||||
* @param high upper limit of the allowed range
|
||||
* @return wrapped value inside the range
|
||||
*/
|
||||
template<typename Integer>
|
||||
Integer wrap(Integer x, Integer low, Integer high) {
|
||||
const auto range = high - low;
|
||||
|
||||
if (x < low)
|
||||
x += range * ((low - x) / range + 1);
|
||||
|
||||
return low + (x - low) % range;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,13 @@ int main()
|
||||
TEST(fabs(wrap(360. - FLT_EPSILON, 0., 360.) - (360. - FLT_EPSILON)) < FLT_EPSILON);
|
||||
TEST(fabs(wrap(360. + FLT_EPSILON, 0., 360.) - FLT_EPSILON) < FLT_EPSILON);
|
||||
|
||||
// integer wraps
|
||||
TEST(wrap(-10, 0, 10) == 0);
|
||||
TEST(wrap(-4, 0, 10) == 6);
|
||||
TEST(wrap(0, 0, 10) == 0)
|
||||
TEST(wrap(4, 0, 10) == 4);
|
||||
TEST(wrap(10, 0, 10) == 0);
|
||||
|
||||
// wrap pi
|
||||
TEST(fabs(wrap_pi(0.)) < FLT_EPSILON);
|
||||
TEST(fabs(wrap_pi(4.) - (4. - M_TWOPI)) < FLT_EPSILON);
|
||||
|
||||
Reference in New Issue
Block a user