| ## Safe Numerics

### Composition with Other Libraries

For many years, Boost has included a library to represent and operate on rational numbers. Its well crafted, has good documentation and is well maintained. Using the rational library is as easy as construction an instance with the expression `rational r(n, d)` where n and d are integers of the same type. From then on it can be used pretty much as any other number. Reading the documentation with safe integers in mind one finds

> Limited-precision integer types [such as `int`] may raise issues with the range sizes of their allowable negative values and positive values. If the negative range is larger, then the extremely-negative numbers will not have an additive inverse in the positive range, making them unusable as denominator values since they cannot be normalized to positive values (unless the user is lucky enough that the input components are not relatively prime pre-normalization).

Which hints of trouble. Examination of the code reveals which suggest that care has been taken implement operations so as to avoid overflows, catch divide by zero, etc. But the code itself doesn't seem to consistently implement this idea. So we make a small demo program:

    //  Copyright (c) 2018 Robert Ramey
    //
    // Distributed under the Boost Software License, Version 1.0. (See
    // accompanying file LICENSE_1_0.txt or copy at
    // http://www.boost.org/LICENSE_1_0.txt)

    #include <iostream>
    #include <limits>

    #include <boost/rational.hpp>
    #include <boost/safe_numerics/safe_integer.hpp>

    int main(int, const char *[]){
        // simple demo of rational library
        const boost::rational<int> r {1, 2};
        std::cout << "r = " << r << std::endl;
        const boost::rational<int> q {-2, 4};
        std::cout << "q = " << q << std::endl;
        // display the product
        std::cout << "r * q = " << r * q << std::endl;

        // problem: rational doesn't handle integer overflow well
        const boost::rational<int> c {1, INT_MAX};
        std::cout << "c = " << c << std::endl;
        const boost::rational<int> d {1, 2};
        std::cout << "d = " << d << std::endl;
        // display the product - wrong answer
        std::cout << "c * d = " << c * d << std::endl;

        // solution: use safe integer in rational definition
        using safe_rational = boost::rational<
            boost::safe_numerics::safe<int>
        >;

        // use rationals created with safe_t
        const safe_rational sc {1, std::numeric_limits<int>::max()};

        std::cout << "c = " << sc << std::endl;
        const safe_rational sd {1, 2};
        std::cout << "d = " << sd << std::endl;
        std::cout << "c * d = ";
        try {
            // multiply them. This will overflow
            std::cout << (sc * sd) << std::endl;
        }
        catch (std::exception const& e) {
            // catch exception due to multiplication overflow
            std::cout << e.what() << std::endl;
        }

        return 0;
    }

which produces the following output

    r = 1/2
    q = -1/2
    r * q = -1/4
    c = 1/2147483647
    d = 1/2
    c * d = 1/-2
    c = 1/2147483647
    d = 1/2
    c * d = multiplication overflow: positive overflow error

The rational library documentation is quite specific as to the type requirements placed on the underlying type. Turns out the our own definition of an integer type fulfills (actually surpasses) these requirements. So we have reason to hope that we can use `safe<int>` as the underlying type to create what we might call a "`safe_rational`". This we have done in the above example where we demonstrate how to compose the rational library with the safe numerics library in order to create what amounts to a safe_rational library - all without writing a line of code! Still, things are not perfect. Since the rational numbers library implements its own checking for divide by zero by throwing an exception, the safe numerics code for handling this - included exception policy will not be respected. To summarize:

- In some cases safe types can be used as template parameters to other types to inject the concept of "no erroneous results" into the target type.

- Such composition is not guaranteed to work. The target type must be reviewed in some detail.