• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //////////////////////////////////////////////////////////////////
2 // example94.cpp
3 //
4 // Copyright (c) 2015 Robert Ramey
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See
7 // accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 
10 // illustrate usage of safe<int> as drop-in replacement for int in
11 // a more complex library.  Use an example from the boost.rational
12 // library with modifications to use safe<int> rather than int
13 
14 //  rational number example program  ----------------------------------------//
15 
16 //  (C) Copyright Paul Moore 1999. Permission to copy, use, modify, sell
17 //  and distribute this software is granted provided this copyright notice
18 //  appears in all copies. This software is provided "as is" without express or
19 //  implied warranty, and with no claim as to its suitability for any purpose.
20 
21 // boostinspect:nolicense (don't complain about the lack of a Boost license)
22 // (Paul Moore hasn't been in contact for years, so there's no way to change the
23 // license.)
24 
25 //  Revision History
26 //  14 Dec 99  Initial version
27 
28 #include <iostream>
29 #include <cassert>
30 #include <cstdlib>
31 #include <boost/config.hpp>
32 #include <limits>
33 #include <exception>
34 #include <boost/rational.hpp>
35 
36 #include <boost/safe_numerics/safe_integer.hpp>
37 
38 using std::cout;
39 using std::endl;
40 using boost::rational;
41 using namespace boost::safe_numerics;
42 
43 using int_type = safe<int>;
44 
main()45 int main ()
46 {
47     rational<int_type> half(1,2);
48     rational<int_type> one(1);
49     rational<int_type> two(2);
50 
51     // Some basic checks
52     assert(half.numerator() == 1);
53     assert(half.denominator() == 2);
54 //    assert(boost::rational_cast<double>(half) == 0.5);
55 
56     static_assert(
57         ! boost::safe_numerics::is_safe<rational<int_type>>::value,
58         "rational<int_type> is safe"
59     );
60 
61     // Arithmetic
62     assert(half + half == one);
63     assert(one - half == half);
64     assert(two * half == one);
65     assert(one / half == two);
66 
67     // With conversions to integer
68     assert(half+half == 1);
69     assert(2 * half == one);
70     assert(2 * half == 1);
71     assert(one / half == 2);
72     assert(1 / half == 2);
73 
74     // Sign handling
75     rational<int_type> minus_half(-1,2);
76     assert(-half == minus_half);
77     assert(abs(minus_half) == half);
78 
79     // Do we avoid overflow?
80     int maxint = (std::numeric_limits<int>::max)();
81     rational<int_type> big(maxint, 2);
82     assert(2 * big == maxint);
83 
84     // Print some of the above results
85     cout << half << "+" << half << "=" << one << endl;
86     cout << one << "-" << half << "=" << half << endl;
87     cout << two << "*" << half << "=" << one << endl;
88     cout << one << "/" << half << "=" << two << endl;
89     cout << "abs(" << minus_half << ")=" << half << endl;
90     cout << "2 * " << big << "=" << maxint
91          << " (rational: " << rational<int>(maxint) << ")" << endl;
92 
93     // Some extras
94 //    rational<int_type> pi(22,7);
95 //    cout << "pi = " << boost::rational_cast<double>(pi) << " (nearly)" << endl;
96 
97     // Exception handling
98     try {
99         rational<int_type> r;        // Forgot to initialise - set to 0
100         r = 1/r;                // Boom!
101     }
102     catch (const boost::bad_rational &e) {
103         cout << "Bad rational, as expected: " << e.what() << endl;
104     }
105     catch (...) {
106         cout << "Wrong exception raised!" << endl;
107     }
108     return 0;
109 }
110