# Safe Numerics

Robert
Ramey
2012-2021
Robert Ramey

Subject to Boost Software License

Safe integer operations
Numerics

# Case Studies

# Type Requirements

# Types

## Promotion Policies

# Exception Safety

All operations in this library are exception safe and meet the strong guarantee.

# Library Implementation

This library should compile and run correctly on any conforming C++14 compiler.

The Safe Numerics library is implemented in terms of some more fundamental software components described here. It is not necessary to know about these components to use the library. This information has been included to help those who want to understand how the library works so they can extend it, correct bugs in it, or understand its limitations. These components are also interesting and likely useful in their own right. For all these reasons, they are documented here.

In general terms, the library works in the following manner:

At compile time:

- The library defines "safe" versions of C++ primitive arithmetic types such as `int`, `unsigned int`, etc.

- Arithmetic operators are defined for these "safe" types. These operators are enhanced versions of the standard C/C++ implementations. These operators are declared and implemented in the files "safe_base.hpp" and "safe_base_operations.hpp".

- For binary operators, verify that both operands have the same promotion and and exception handling policies. If they don't, invoke compilation error.

- Invoke the promotion policy to determine the result type R of the operation.

- For each operand of type T retrieve the range of values from `std::numeric_limits<T>::min()` and `std::numeric_limits<T>::max()`. A range is a pair of values representing a closed interval with a minimum and maximum value.

- These ranges are cast to equivalent values of the result type, R. It's possible that values cannot be cast to the result type so the result of the cast is returned as a variant type, `checked_result<R>`. `checked_result<R>` may hold either a value of type R or a `safe_numerics_error` value indicating why the cast could not be accomplished. Ranges are represented as a pair of values of the type `checked_result<R>`.

- `checked_result<R>` can be considered enhanced versions of the underlying type R. Operations which are legal on values of type R such as +, -, ... are also legal on values of `checked_result<R>`. The difference is that the latter can record operation failures and propagate such failures to subsequent operations.`checked_result<R>` is implemented in the header file "checked_result.hpp". Operations on such types are implemented in "checked_result_operations.hpp".

- Given the ranges of the operands, determine the range of the result of the operation using compile-time interval arithmetic. The `constexpr` facility of C++14 permits the range of the result to be calculated at compile time. Interval arithmetic is implemented in the header file "interval.hpp". The range of the result is also represented as a pair of values of the type `checked_result<R>`.

- Operations on primitives are implemented via free standing functions described as checked arithmetic. These operations will return instances of `checked_result<R>` .

At run time:

- If the range of the result type includes only arithmetically valid values, the operation is guaranteed to produce an arithmetically correct result and no runtime checking is necessary. The operation invokes the original built-in C/C++ operation and returns the result value.

- Otherwise, operands are cast to the result type, R, according to the selected promotion policy. These "checked" cast operations return values of type `checked_result<R>`.

- If either of the casting operations fails, an exception is handled in accordance with the exception policy.

- Otherwise, the operation is performed using "checked arithmetic". These free functions mirror the normal operators +, -, *, ... except that rather than returning values of type R, they return values of the type `checked_result<R>`. They are defined in files "checked_default.hpp", "checked_integer.hpp" ,"checked_float.hpp".

- If the operation is not successful, the designated exception policy function is invoked.

- Otherwise, the result value is returned as a `safe<R>` type with the above calculated result range.

The following components realize the design described here.

# Performance Tests

Our goal is to create facilities which make it possible to write programs known to be correct. But we also want programmers to actually use the facilities we provide here. This won't happen if using these facilities impacts performance to a significant degree. Although we've taken precautions to avoid doing this, the only real way to know is to create and run some tests.

So far we've only run one explicit performance test - `test_performance.cpp`. This runs a test from the Boost Multiprecision library to count prime numbers and makes extensive usage of integer arithmetic. We've run the tests with `unsigned` integers and with `safe<unsigned>` on two different compilers.. No other change was made to the program. We list the results without further comment.

    g++ (GCC) 6.2.0
    Testing type unsigned:
    time = 17.6215
    count = 1857858
    Testing type safe<unsigned>:
    time = 22.4226
    count = 1857858

    clang-802.0.41
    Testing type unsigned:
    time = 16.9174
    count = 1857858
    Testing type safe<unsigned>:
    time = 36.5166
    count = 1857858

# Release Log

This is the third version.

1.69 29 September 2018

First Boost Release

1.70 9 March 2019

Fixed Exception Policies for `trap` and `ignore`.