pw_numeric#

Efficient mathematical utilities for embedded

Stable C++

pw_numeric is a collection of mathematical utilities optimized for embedded systems.

What belongs in this module?

Any standalone mathematical, numerical, or statisitical utilities that are optimized for embedded belong in pw_numeric. This encompasses a broad area, but since the C++ standard library provides many mathematical utilities already, this module is not anticipated to be too large. If the module does grow substantially, some features may be moved to other modules (e.g. pw_statistics).

What does NOT belong in this module?

  • Features available in the C++ standard library (<cmath>, <numeric>, <bit>, etc.) should not be duplicated.

  • Pseudo-random number generation belongs in pw_random.

  • Data integrity checking belongs in pw_checksum.

  • Bit / byte manipulation belong in pw_bytes.

C++ API reference#

pw_numeric/checked_arithmetic.h#

template<typename T, typename A, typename B>
constexpr std::optional<T> pw::CheckedAdd(A a, B b)#

Adds two numbers, checking for overflow.

Note

The template argument must be provided, e.g. pw::CheckedAdd<uint32_t>(...).

Template Parameters:
  • T – The type of the result, which is checked for overflow.

  • A – The type of the first addend, a.

  • B – The type of the second addend, b.

Parameters:
  • a[in] The first addend.

  • b[in] The second addend.

Returns:

The sum (a + b) if addition was successful, or nullopt if the addition would overflow.

template<typename T, typename Inc>
constexpr bool pw::CheckedIncrement(T &base, Inc inc)#

Increments a variable by some amount.

Template Parameters:
  • T – The type of the variable to be incremented.

  • Inc – The type of the variable to add.

Parameters:
  • base[in] The variable to be incremented.

  • inc[in] The number to add to base.

Returns:

True if the addition was successful and base was incremented (base += inc); False if the addition would overflow and base is unmodified.

template<typename T, typename A, typename B>
constexpr std::optional<T> pw::CheckedSub(A a, B b)#

Subtracts two numbers, checking for overflow.

Note

The template argument must be provided, e.g. pw::CheckedSub<uint32_t>(...).

Template Parameters:
  • T – The type of the result, which is checked for overflow.

  • A – The type of the minuend, a.

  • B – The type of the subtrahend, b.

Parameters:
  • a[in] The minuend (the number from which b is subtracted).

  • b[in] The subtrahend (the number subtracted from a).

Returns:

The difference (a - b) if subtraction was successful, or nullopt if the subtraction would overflow.

template<typename T, typename Dec>
constexpr bool pw::CheckedDecrement(T &base, Dec dec)#

Decrements a variable by some amount.

Template Parameters:
  • T – The type of the variable to be decremented.

  • Dec – The type of the variable to subtract.

Parameters:
  • base[in] The variable to be decremented.

  • inc[in] The number to subtract from base.

Returns:

True if the subtraction was successful and base was decremented (base -= inc); False if the subtraction would overflow and base is unmodified.

template<typename T, typename A, typename B>
constexpr std::optional<T> pw::CheckedMul(A a, B b)#

Multiplies two numbers, checking for overflow.

Note

The template argument must be provided, e.g. pw::CheckedMul<uint32_t>(...).

Template Parameters:
  • T – The type of the result, which is checked for overflow.

  • A – The type of the first factor, a.

  • B – The type of the second factor, b.

Parameters:
  • a[in] The first factor.

  • b[in] The second factor.

Returns:

The product (a * b) if multiplication was successful, or nullopt if the multiplication would overflow.

pw_numeric/integer_division.h#

template<typename T>
constexpr T pw::IntegerDivisionRoundNearest(T dividend, T divisor)#

Performs integer division and rounds to the nearest integer. Gives the same result as std::round(static_cast<double>(dividend) / static_cast<double>(divisor)), but requires no floating point operations and is constexpr.

Warning

signed or unsigned int, long, or long long operands overflow if:

  • the quotient is positive and dividend + divisor/2 overflows, or

  • the quotient is negative and dividend - divisor/2 overflows.

To avoid overflow, do not use this function with very large operands, or cast int or long to a larger type first. Overflow cannot occur with types smaller than int because C++ implicitly converts them to int.