General Utility Library for C++14  2.12
Functions
gul14/num_util.h

Detailed Description

Numerical utility functions.

Functions

template<typename ValueT >
constexpr auto gul14::abs (ValueT n) noexcept -> std::enable_if_t< std::is_unsigned< ValueT >::value, ValueT >
 Compute the absolute value of a number. More...
 
template<typename NumT , typename OrderT , typename = std::enable_if_t< std::is_arithmetic<NumT>::value and std::is_arithmetic<OrderT>::value >>
bool gul14::within_orders (const NumT a, const NumT b, const OrderT orders) noexcept(false)
 Determine if two numbers are almost equal, comparing only some significant digits. More...
 
template<typename NumT >
bool gul14::within_abs (NumT a, NumT b, NumT tol) noexcept
 Determine if two numbers are almost equal, allowing for an absolute difference. More...
 
template<typename NumT , typename = std::enable_if_t<std::is_floating_point<NumT>::value>>
bool gul14::within_ulp (NumT a, NumT b, unsigned int ulp)
 Determine if two numbers are almost equal, allowing for a difference of a given number of units-in-the-last-place (ULPs). More...
 
template<class NumT >
constexpr const NumT & gul14::clamp (const NumT &v, const NumT &lo, const NumT &hi)
 Coerce a value to be within a given range. More...
 
template<class NumT , class Compare >
constexpr const NumT & gul14::clamp (const NumT &v, const NumT &lo, const NumT &hi, Compare comp)
 This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. More...
 

Function Documentation

◆ abs()

template<typename ValueT >
constexpr auto gul14::abs ( ValueT  n) -> std::enable_if_t<std::is_unsigned<ValueT>::value, ValueT>
constexprnoexcept

Compute the absolute value of a number.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

This function is almost equal to std::abs() with the exception of unsigned integral types, which are returned unchanged and in their original type. This is especially useful in templates, where std::abs() cannot be used for all arithmetic types.

Parameters
nThe number whose absolute value should be determined.
Returns
the absolute value of n.

Referenced by gul14::gcd(), gul14::lcm(), gul14::remove_outliers(), gul14::within_abs(), gul14::within_orders(), and gul14::within_ulp().

◆ clamp() [1/2]

template<class NumT >
constexpr const NumT& gul14::clamp ( const NumT &  v,
const NumT &  lo,
const NumT &  hi 
)
constexpr

Coerce a value to be within a given range.

Check if value v is between (including) lo and hi. If it is too low, lo is returned. If it is too high, hi is returned.

lo must not be greater than hi, but they are allowed to be equal.

Only operator<() is used for this, so it has to be defined for NumT.

Note that all parameters need to be of the same type. Add the correct suffix if using a literal as shown in the following example:

char c = ...;
size_t s = ...;
float f = ...;
auto c2 = clamp(c, 'a', 'z');
auto s2 = clamp(s, 0ul, 1000ul);
auto f2 = clamp(f, 0.0f, 99.0f);
constexpr const NumT & clamp(const NumT &v, const NumT &lo, const NumT &hi)
Coerce a value to be within a given range.
Definition: num_util.h:208
Template Parameters
NumTType of the objects to compare. Needs to have operator<() defined.
Parameters
vThe value to clamp
loThe lower boundary to clamp v to
hiThe upper boundary to clamp v to
Returns
a reference to lo if v is less than lo, a reference to hi if hi is less than v, or a reference to v otherwise.

◆ clamp() [2/2]

template<class NumT , class Compare >
constexpr const NumT& gul14::clamp ( const NumT &  v,
const NumT &  lo,
const NumT &  hi,
Compare  comp 
)
constexpr

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Template Parameters
NumTType of the objects to compare. Needs to have operator<() defined.
CompareType of the comparison function. See notes below.
Parameters
vThe value to clamp
loThe lower boundary to clamp v to
hiThe upper boundary to clamp v to
compComparison function object which returns true if the first argument is less than the second.

The signature of the comparison function should be equivalent to the following:

bool cmp(const Type1& a, const Type2& b);

While the signature does not explicitly require passing the arguments by const reference, the function must not modify the objects passed to it and must be able to accept all values of type (possibly const) Type1 and Type2 regardless of value category. This means that neither Type1 & nor Type1 are allowed unless a move is equivalent to a copy for Type1. The types Type1 and Type2 must be such that an object of type T can be implicitly converted to both of them.

◆ within_abs()

template<typename NumT >
bool gul14::within_abs ( NumT  a,
NumT  b,
NumT  tol 
)
noexcept

Determine if two numbers are almost equal, allowing for an absolute difference.

All arguments must be the same numeric type (floating point or integer).

Parameters
aThe first number to compare
bThe second number to compare
tolThe absolute tolerance
Returns
true if the absolute difference between a and b is smaller than tol.

References gul14::abs().

◆ within_orders()

template<typename NumT , typename OrderT , typename = std::enable_if_t< std::is_arithmetic<NumT>::value and std::is_arithmetic<OrderT>::value >>
bool gul14::within_orders ( const NumT  a,
const NumT  b,
const OrderT  orders 
)
noexcept

Determine if two numbers are almost equal, comparing only some significant digits.

The functions compares the specified number of significant decimal digits of the two values and returns true if they are equal within these digits.

a = 23736384; b = 23736228; within_orders(a, b, 5) => true  (first 5 digits equal)
a = 23736384; b = 23735384; within_orders(a, b, 5) => false (digit #5 differs)

Unexpected behavior can result when orders is low (< 3) as the simple concept of orders equals digits does not hold so strict anymore.

Remember that any nonzero number has infinite different significant digits compared with 0.00000000. So if one operand is 0.0 while the other is not 0.0 the result must be false.

Parameters
aThe first number to compare
bThe second number to compare (same type as a)
ordersThe number of digits to take for comparison (any numeric type)
Returns
true if a and b are equal or the difference between a and b is orders orders of magnitude lower than the value of a or b
Since
GUL version 1.4 parameter type NumT can be an integral type (had to be floating point before)
GUL version 2.7.1 return true if a == b == 0.0

References gul14::abs(), and gul14::maximum().

◆ within_ulp()

template<typename NumT , typename = std::enable_if_t<std::is_floating_point<NumT>::value>>
bool gul14::within_ulp ( NumT  a,
NumT  b,
unsigned int  ulp 
)

Determine if two numbers are almost equal, allowing for a difference of a given number of units-in-the-last-place (ULPs).

One ULP is the spacing between two consecutive floating point representations. There are no possible values in between. Roughly speaking, one ULP is for floating point numbers what the 1 is for integral numbers.

All arguments must be of the same floating point type.

Parameters
aThe first number to compare
bThe second number to compare
ulpAllowed number of floating point steps in between
Returns
true if a and b are equal within the given number of ULPs.

References gul14::abs().