 General Utility Library for C++14  2.9
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...

## ◆ abs()

template<typename ValueT >
 constexpr auto gul14::abs ( ValueT n ) -> std::enable_if_t::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
 n The number whose absolute value should be determined.
Returns
the absolute value of n.

## ◆ 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
 NumT Type of the objects to compare. Needs to have `operator<()` defined.
Parameters
 v The value to clamp lo The lower boundary to clamp `v` to hi The 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
 NumT Type of the objects to compare. Needs to have `operator<()` defined. Compare Type of the comparison function. See notes below.
Parameters
 v The value to clamp lo The lower boundary to clamp `v` to hi The upper boundary to clamp `v` to comp Comparison 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
 a The first number to compare b The second number to compare tol The 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
 a The first number to compare b The second number to compare (same type as `a`) orders The 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
 a The first number to compare b The second number to compare ulp Allowed number of floating point steps in between
Returns
true if a and b are equal within the given number of ULPs.

References gul14::abs().