| 1 | /* | 
|---|
| 2 |  *  A test program for boost/rational.hpp. | 
|---|
| 3 |  *  Change the typedef at the beginning of run_tests() to try out different | 
|---|
| 4 |  *  integer types.  (These tests are designed only for signed integer | 
|---|
| 5 |  *  types.  They should work for short, int and long.) | 
|---|
| 6 |  * | 
|---|
| 7 |  *  (C) Copyright Stephen Silver, 2001. Permission to copy, use, modify, sell | 
|---|
| 8 |  *  and distribute this software is granted provided this copyright notice | 
|---|
| 9 |  *  appears in all copies. This software is provided "as is" without express or | 
|---|
| 10 |  *  implied warranty, and with no claim as to its suitability for any purpose. | 
|---|
| 11 |  * | 
|---|
| 12 |  *  Incorporated into the boost rational number library, and modified and | 
|---|
| 13 |  *  extended, by Paul Moore, with permission. | 
|---|
| 14 |  */ | 
|---|
| 15 |  | 
|---|
| 16 | // Revision History | 
|---|
| 17 | // 04 Mar 01  Patches for Intel C++ and GCC (David Abrahams) | 
|---|
| 18 |  | 
|---|
| 19 | #include "boost/rational.hpp" | 
|---|
| 20 | #include "boost/operators.hpp" | 
|---|
| 21 | #include <cstdlib> | 
|---|
| 22 | #include <iomanip> | 
|---|
| 23 | #include <iostream> | 
|---|
| 24 | #include <cstring> | 
|---|
| 25 |  | 
|---|
| 26 | #ifndef BOOST_NO_STRINGSTREAM | 
|---|
| 27 | # include <sstream> | 
|---|
| 28 | #else | 
|---|
| 29 | # include <strstream> | 
|---|
| 30 | namespace { | 
|---|
| 31 |   class unfreezer { | 
|---|
| 32 |    public: | 
|---|
| 33 |       unfreezer(std::ostrstream& s) : m_stream(s) {} | 
|---|
| 34 |       ~unfreezer() { m_stream.freeze(false); } | 
|---|
| 35 |    private: | 
|---|
| 36 |       std::ostrstream& m_stream; | 
|---|
| 37 |   }; | 
|---|
| 38 | } | 
|---|
| 39 | #endif | 
|---|
| 40 |  | 
|---|
| 41 | // We can override this on the compile, as -DINT_TYPE=short or whatever. | 
|---|
| 42 | // The default test is against rational<long>. | 
|---|
| 43 | #ifndef INT_TYPE | 
|---|
| 44 | #define INT_TYPE long | 
|---|
| 45 | #endif | 
|---|
| 46 |  | 
|---|
| 47 | namespace { | 
|---|
| 48 |  | 
|---|
| 49 | // This is a trivial user-defined wrapper around the built in int type. | 
|---|
| 50 | // It can be used as a test type for rational<> | 
|---|
| 51 | class MyInt : boost::operators<MyInt> | 
|---|
| 52 | { | 
|---|
| 53 |     int val; | 
|---|
| 54 | public: | 
|---|
| 55 |     MyInt(int n = 0) : val(n) {} | 
|---|
| 56 |     friend MyInt operator+ (const MyInt&); | 
|---|
| 57 |     friend MyInt operator- (const MyInt&); | 
|---|
| 58 |     MyInt& operator+= (const MyInt& rhs) { val += rhs.val; return *this; } | 
|---|
| 59 |     MyInt& operator-= (const MyInt& rhs) { val -= rhs.val; return *this; } | 
|---|
| 60 |     MyInt& operator*= (const MyInt& rhs) { val *= rhs.val; return *this; } | 
|---|
| 61 |     MyInt& operator/= (const MyInt& rhs) { val /= rhs.val; return *this; } | 
|---|
| 62 |     MyInt& operator%= (const MyInt& rhs) { val %= rhs.val; return *this; } | 
|---|
| 63 |     MyInt& operator|= (const MyInt& rhs) { val |= rhs.val; return *this; } | 
|---|
| 64 |     MyInt& operator&= (const MyInt& rhs) { val &= rhs.val; return *this; } | 
|---|
| 65 |     MyInt& operator^= (const MyInt& rhs) { val ^= rhs.val; return *this; } | 
|---|
| 66 |     const MyInt& operator++() { ++val; return *this; } | 
|---|
| 67 |     const MyInt& operator--() { --val; return *this; } | 
|---|
| 68 |     bool operator< (const MyInt& rhs) const { return val < rhs.val; } | 
|---|
| 69 |     bool operator== (const MyInt& rhs) const { return val == rhs.val; } | 
|---|
| 70 |     bool operator! () const { return !val; } | 
|---|
| 71 |     friend std::istream& operator>>(std::istream&, MyInt&); | 
|---|
| 72 |     friend std::ostream& operator<<(std::ostream&, const MyInt&); | 
|---|
| 73 | }; | 
|---|
| 74 |  | 
|---|
| 75 | inline MyInt operator+(const MyInt& rhs) { return rhs; } | 
|---|
| 76 | inline MyInt operator-(const MyInt& rhs) { return MyInt(-rhs.val); } | 
|---|
| 77 | inline std::istream& operator>>(std::istream& is, MyInt& i) { is >> i.val; return is; } | 
|---|
| 78 | inline std::ostream& operator<<(std::ostream& os, const MyInt& i) { os << i.val; return os; } | 
|---|
| 79 | inline MyInt abs(MyInt rhs) { if (rhs < MyInt()) rhs = -rhs; return rhs; } | 
|---|
| 80 |  | 
|---|
| 81 | // Test statistics | 
|---|
| 82 | static unsigned int total_count; | 
|---|
| 83 | static unsigned int error_count; | 
|---|
| 84 |  | 
|---|
| 85 | // Check a specific assertion | 
|---|
| 86 | void Check(bool ok, const char *s, int line) | 
|---|
| 87 | { | 
|---|
| 88 |     ++total_count; | 
|---|
| 89 |     if (!ok) | 
|---|
| 90 |     { | 
|---|
| 91 |         std::cout << "Failed test " << s << " at line " << line << '\n'; | 
|---|
| 92 |         ++error_count; | 
|---|
| 93 |     } | 
|---|
| 94 | #ifdef SHOW_SUCCESSES | 
|---|
| 95 |     std::cout << "Passed test " << s << '\n'; | 
|---|
| 96 | #endif | 
|---|
| 97 | } | 
|---|
| 98 |  | 
|---|
| 99 | #define CHECK(x) Check((x), #x, __LINE__) | 
|---|
| 100 |  | 
|---|
| 101 | // The basic test suite | 
|---|
| 102 | void run_tests() | 
|---|
| 103 | { | 
|---|
| 104 |     typedef INT_TYPE IntType; | 
|---|
| 105 |     typedef boost::rational<IntType> rat; | 
|---|
| 106 |  | 
|---|
| 107 |     error_count = 0; | 
|---|
| 108 |     total_count = 0; | 
|---|
| 109 |  | 
|---|
| 110 |     /* gcd tests */ | 
|---|
| 111 |     CHECK(( boost::gcd<IntType>(1,-1) == 1     )); | 
|---|
| 112 |     CHECK(( boost::gcd<IntType>(-1,1) == 1     )); | 
|---|
| 113 |     CHECK(( boost::gcd<IntType>(1,1) == 1      )); | 
|---|
| 114 |     CHECK(( boost::gcd<IntType>(-1,-1) == 1    )); | 
|---|
| 115 |     CHECK(( boost::gcd<IntType>(0,0) == 0      )); | 
|---|
| 116 |     CHECK(( boost::gcd<IntType>(7,0) == 7      )); | 
|---|
| 117 |     CHECK(( boost::gcd<IntType>(0,9) == 9      )); | 
|---|
| 118 |     CHECK(( boost::gcd<IntType>(-7,0) == 7     )); | 
|---|
| 119 |     CHECK(( boost::gcd<IntType>(0,-9) == 9     )); | 
|---|
| 120 |     CHECK(( boost::gcd<IntType>(42,30) == 6    )); | 
|---|
| 121 |     CHECK(( boost::gcd<IntType>(6,-9) == 3     )); | 
|---|
| 122 |     CHECK(( boost::gcd<IntType>(-10,-10) == 10 )); | 
|---|
| 123 |     CHECK(( boost::gcd<IntType>(-25,-10) == 5  )); | 
|---|
| 124 |  | 
|---|
| 125 |     /* lcm tests */ | 
|---|
| 126 |     CHECK(( boost::lcm<IntType>(1,-1) == 1     )); | 
|---|
| 127 |     CHECK(( boost::lcm<IntType>(-1,1) == 1     )); | 
|---|
| 128 |     CHECK(( boost::lcm<IntType>(1,1) == 1      )); | 
|---|
| 129 |     CHECK(( boost::lcm<IntType>(-1,-1) == 1    )); | 
|---|
| 130 |     CHECK(( boost::lcm<IntType>(0,0) == 0      )); | 
|---|
| 131 |     CHECK(( boost::lcm<IntType>(6,0) == 0      )); | 
|---|
| 132 |     CHECK(( boost::lcm<IntType>(0,7) == 0      )); | 
|---|
| 133 |     CHECK(( boost::lcm<IntType>(-5,0) == 0     )); | 
|---|
| 134 |     CHECK(( boost::lcm<IntType>(0,-4) == 0     )); | 
|---|
| 135 |     CHECK(( boost::lcm<IntType>(18,30) == 90   )); | 
|---|
| 136 |     CHECK(( boost::lcm<IntType>(-6,9) == 18    )); | 
|---|
| 137 |     CHECK(( boost::lcm<IntType>(-10,-10) == 10 )); | 
|---|
| 138 |     CHECK(( boost::lcm<IntType>(25,-10) == 50  )); | 
|---|
| 139 |  | 
|---|
| 140 |     /* initialization tests */ | 
|---|
| 141 |     rat r1, r2(0), r3(1), r4(-3), r5(7,2), r6(5,15), r7(14,-21), | 
|---|
| 142 |         r8(-4,6), r9(-14,-70); | 
|---|
| 143 |  | 
|---|
| 144 |     CHECK(( r1.numerator() == 0  )); | 
|---|
| 145 |     CHECK(( r2.numerator() == 0  )); | 
|---|
| 146 |     CHECK(( r3.numerator() == 1  )); | 
|---|
| 147 |     CHECK(( r4.numerator() == -3 )); | 
|---|
| 148 |     CHECK(( r5.numerator() == 7  )); | 
|---|
| 149 |     CHECK(( r6.numerator() == 1  )); | 
|---|
| 150 |     CHECK(( r7.numerator() == -2 )); | 
|---|
| 151 |     CHECK(( r8.numerator() == -2 )); | 
|---|
| 152 |     CHECK(( r9.numerator() == 1  )); | 
|---|
| 153 |  | 
|---|
| 154 |     CHECK(( r1.denominator() == 1 )); | 
|---|
| 155 |     CHECK(( r2.denominator() == 1 )); | 
|---|
| 156 |     CHECK(( r3.denominator() == 1 )); | 
|---|
| 157 |     CHECK(( r4.denominator() == 1 )); | 
|---|
| 158 |     CHECK(( r5.denominator() == 2 )); | 
|---|
| 159 |     CHECK(( r6.denominator() == 3 )); | 
|---|
| 160 |     CHECK(( r7.denominator() == 3 )); | 
|---|
| 161 |     CHECK(( r8.denominator() == 3 )); | 
|---|
| 162 |     CHECK(( r9.denominator() == 5 )); | 
|---|
| 163 |  | 
|---|
| 164 |     /* assign() tests */ | 
|---|
| 165 |     r1.assign(6,8); | 
|---|
| 166 |     CHECK(( r1.numerator()   == 3   )); | 
|---|
| 167 |     CHECK(( r1.denominator() == 4   )); | 
|---|
| 168 |     r1.assign(0,-7); | 
|---|
| 169 |     CHECK(( r1.numerator()   == 0   )); | 
|---|
| 170 |     CHECK(( r1.denominator() == 1   )); | 
|---|
| 171 |  | 
|---|
| 172 |     /* comparison tests */ | 
|---|
| 173 |     CHECK(( r1 == r2 )); | 
|---|
| 174 |     CHECK(( r2 != r3 )); | 
|---|
| 175 |     CHECK(( r4 <  r3 )); | 
|---|
| 176 |     CHECK(( r4 <= r5 )); | 
|---|
| 177 |     CHECK(( r1 <= r2 )); | 
|---|
| 178 |     CHECK(( r5 >  r6 )); | 
|---|
| 179 |     CHECK(( r5 >= r6 )); | 
|---|
| 180 |     CHECK(( r7 >= r8 )); | 
|---|
| 181 |  | 
|---|
| 182 |     CHECK(( !(r3 == r2) )); | 
|---|
| 183 |     CHECK(( !(r1 != r2) )); | 
|---|
| 184 |     CHECK(( !(r1 <  r2) )); | 
|---|
| 185 |     CHECK(( !(r5 <  r6) )); | 
|---|
| 186 |     CHECK(( !(r9 <= r2) )); | 
|---|
| 187 |     CHECK(( !(r8 >  r7) )); | 
|---|
| 188 |     CHECK(( !(r8 >  r2) )); | 
|---|
| 189 |     CHECK(( !(r4 >= r6) )); | 
|---|
| 190 |  | 
|---|
| 191 |     CHECK(( r1 == 0  )); | 
|---|
| 192 |     CHECK(( r2 != -1 )); | 
|---|
| 193 |     CHECK(( r3 < 2   )); | 
|---|
| 194 |     CHECK(( r4 <= -3 )); | 
|---|
| 195 |     CHECK(( r5 > 3   )); | 
|---|
| 196 |     CHECK(( r6 >= 0  )); | 
|---|
| 197 |  | 
|---|
| 198 |     CHECK(( 0 == r2  )); | 
|---|
| 199 |     CHECK(( 0 != r7  )); | 
|---|
| 200 |     CHECK(( -1 < r8  )); | 
|---|
| 201 |     CHECK(( -2 <= r9 )); | 
|---|
| 202 |     CHECK(( 1 > r1   )); | 
|---|
| 203 |     CHECK(( 1 >= r3  )); | 
|---|
| 204 |  | 
|---|
| 205 |     /* increment/decrement tests */ | 
|---|
| 206 |     CHECK(( r1++ == r2 )); | 
|---|
| 207 |     CHECK(( r1 != r2   )); | 
|---|
| 208 |     CHECK(( r1 == r3   )); | 
|---|
| 209 |     CHECK(( --r1 == r2 )); | 
|---|
| 210 |     CHECK(( r8-- == r7 )); | 
|---|
| 211 |     CHECK(( r8 != r7   )); | 
|---|
| 212 |     CHECK(( ++r8 == r7 )); | 
|---|
| 213 |  | 
|---|
| 214 |     /* abs tests */ | 
|---|
| 215 | #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP | 
|---|
| 216 | // This is a nasty hack, required because some compilers do not implement | 
|---|
| 217 | // "Koenig Lookup". Basically, if I call abs(r), the C++ standard says that | 
|---|
| 218 | // the compiler should look for a definition of abs in the namespace which | 
|---|
| 219 | // contains r's class (in this case boost) - among other places. | 
|---|
| 220 |  | 
|---|
| 221 | using boost::abs; | 
|---|
| 222 | #endif | 
|---|
| 223 |  | 
|---|
| 224 |     CHECK(( abs(r2) == r2       )); | 
|---|
| 225 |     CHECK(( abs(r5) == r5       )); | 
|---|
| 226 |     CHECK(( abs(r8) == rat(2,3) )); | 
|---|
| 227 |  | 
|---|
| 228 |     /* addition/subtraction tests */ | 
|---|
| 229 |     CHECK(( rat(1,2) + rat(1,2)  == 1                   )); | 
|---|
| 230 |     CHECK(( rat(11,3) + rat(1,2) == rat(25,6)           )); | 
|---|
| 231 |     CHECK(( rat(-8,3) + rat(1,5) == rat(-37,15)         )); | 
|---|
| 232 |     CHECK(( rat(-7,6) + rat(1,7) == rat(1,7) - rat(7,6) )); | 
|---|
| 233 |     CHECK(( rat(13,5) - rat(1,2) == rat(21,10)          )); | 
|---|
| 234 |     CHECK(( rat(22,3) + 1        == rat(25,3)           )); | 
|---|
| 235 |     CHECK(( rat(12,7) - 2        == rat(-2,7)           )); | 
|---|
| 236 |     CHECK(( 3 + rat(4,5)         == rat(19,5)           )); | 
|---|
| 237 |     CHECK(( 4 - rat(9,2)         == rat(-1,2)           )); | 
|---|
| 238 |     rat r0(11); | 
|---|
| 239 |     r0 -= rat(20,3); | 
|---|
| 240 |     CHECK(( r0 == rat(13,3)  )); | 
|---|
| 241 |     r0 += rat(1,2); | 
|---|
| 242 |     CHECK(( r0 == rat(29,6)  )); | 
|---|
| 243 |     r0 -= 5; | 
|---|
| 244 |     CHECK(( r0 == rat(1,-6)  )); | 
|---|
| 245 |     r0 += rat(1,5); | 
|---|
| 246 |     CHECK(( r0 == rat(1,30)  )); | 
|---|
| 247 |     r0 += 2; | 
|---|
| 248 |     CHECK(( r0 == rat(61,30) )); | 
|---|
| 249 |  | 
|---|
| 250 |     /* assignment tests */ | 
|---|
| 251 |     r0 = rat(1,10); | 
|---|
| 252 |     CHECK(( r0 == rat(1,10) )); | 
|---|
| 253 |     r0 = -9; | 
|---|
| 254 |     CHECK(( r0 == rat(-9,1) )); | 
|---|
| 255 |  | 
|---|
| 256 |     /* unary operator tests */ | 
|---|
| 257 |     CHECK(( +r5 == r5    )); | 
|---|
| 258 |     CHECK(( -r3 != r3    )); | 
|---|
| 259 |     CHECK(( -(-r3) == r3 )); | 
|---|
| 260 |     CHECK(( -r4 == 3     )); | 
|---|
| 261 |     CHECK(( !r2          )); | 
|---|
| 262 |     CHECK(( !!r3         )); | 
|---|
| 263 |  | 
|---|
| 264 |     /* multiplication tests */ | 
|---|
| 265 |     CHECK(( rat(1,3) * rat(-3,4) == rat(-1,4) )); | 
|---|
| 266 |     CHECK(( rat(2,5) * 7         == rat(14,5) )); | 
|---|
| 267 |     CHECK(( -2 * rat(1,6)        == rat(-1,3) )); | 
|---|
| 268 |     r0 = rat(3,7); | 
|---|
| 269 |     r0 *= 14; | 
|---|
| 270 |     CHECK(( r0 == 6 )); | 
|---|
| 271 |     r0 *= rat(3,8); | 
|---|
| 272 |     CHECK(( r0 == rat(9,4) )); | 
|---|
| 273 |  | 
|---|
| 274 |     /* division tests */ | 
|---|
| 275 |     CHECK(( rat(-1,20) / rat(4,5) == rat(-1,16) )); | 
|---|
| 276 |     CHECK(( rat(5,6) / 7          == rat(5,42)  )); | 
|---|
| 277 |     CHECK(( 8 / rat(2,7)          == 28         )); | 
|---|
| 278 |     r0 = rat(4,3); | 
|---|
| 279 |     r0 /= rat(5,4); | 
|---|
| 280 |     CHECK(( r0 == rat(16,15) )); | 
|---|
| 281 |     r0 /= 4; | 
|---|
| 282 |     CHECK(( r0 == rat(4,15) )); | 
|---|
| 283 |     CHECK(( rat(-1)/rat(-3) == rat(1,3) )); | 
|---|
| 284 |  | 
|---|
| 285 |     /* tests for operations on self */ | 
|---|
| 286 |     r0 = rat(4,3); | 
|---|
| 287 |     r0 += r0; | 
|---|
| 288 |     CHECK(( r0 == rat(8,3) )); | 
|---|
| 289 |     r0 *= r0; | 
|---|
| 290 |     CHECK(( r0 == rat(64,9) )); | 
|---|
| 291 |     r0 /= r0; | 
|---|
| 292 |     CHECK(( r0 == rat(1,1) )); | 
|---|
| 293 |     r0 -= r0; | 
|---|
| 294 |     CHECK(( r0 == rat(0,1) )); | 
|---|
| 295 |  | 
|---|
| 296 |     /* operator<< and operator>> tests */ | 
|---|
| 297 | #ifndef BOOST_NO_STRINGSTREAM | 
|---|
| 298 |     std::ostringstream oss; | 
|---|
| 299 |      | 
|---|
| 300 |     oss << rat(44,14); | 
|---|
| 301 |     CHECK(( oss.str() == "22/7" )); | 
|---|
| 302 |     typedef std::istringstream input_string_stream; | 
|---|
| 303 | #else | 
|---|
| 304 |     std::ostrstream oss; | 
|---|
| 305 |     oss << rat(44,14) << char(); | 
|---|
| 306 |     auto unfreezer unfreeze(oss); | 
|---|
| 307 |     CHECK(( !std::strcmp(oss.str(), "22/7") )); | 
|---|
| 308 |     typedef std::istrstream input_string_stream; | 
|---|
| 309 | #endif | 
|---|
| 310 |     { | 
|---|
| 311 |         input_string_stream iss(""); | 
|---|
| 312 |         iss >> r0; | 
|---|
| 313 |         CHECK(( !iss )); | 
|---|
| 314 |     } | 
|---|
| 315 |     { | 
|---|
| 316 |         input_string_stream iss("42"); | 
|---|
| 317 |         iss >> r0; | 
|---|
| 318 |         CHECK(( !iss )); | 
|---|
| 319 |     } | 
|---|
| 320 |     { | 
|---|
| 321 |         input_string_stream iss("57A"); | 
|---|
| 322 |         iss >> r0; | 
|---|
| 323 |         CHECK(( !iss )); | 
|---|
| 324 |     } | 
|---|
| 325 |     { | 
|---|
| 326 |         input_string_stream iss("20-20"); | 
|---|
| 327 |         iss >> r0; | 
|---|
| 328 |         CHECK(( !iss )); | 
|---|
| 329 |     } | 
|---|
| 330 |     { | 
|---|
| 331 |         input_string_stream iss("1/"); | 
|---|
| 332 |         iss >> r0; | 
|---|
| 333 |         CHECK(( !iss )); | 
|---|
| 334 |     } | 
|---|
| 335 |     { | 
|---|
| 336 |         input_string_stream iss("1/ 2"); | 
|---|
| 337 |         iss >> r0; | 
|---|
| 338 |         CHECK(( !iss )); | 
|---|
| 339 |     } | 
|---|
| 340 |     { | 
|---|
| 341 |         input_string_stream iss("1 /2"); | 
|---|
| 342 |         iss >> r0; | 
|---|
| 343 |         CHECK(( !iss )); | 
|---|
| 344 |     } | 
|---|
| 345 |     { | 
|---|
| 346 |         int n; | 
|---|
| 347 |         input_string_stream iss("1/2 12"); | 
|---|
| 348 |         CHECK(( iss >> r0 >> n )); | 
|---|
| 349 |         CHECK(( r0 == rat(1,2) )); | 
|---|
| 350 |         CHECK(( n == 12 )); | 
|---|
| 351 |     } | 
|---|
| 352 |     { | 
|---|
| 353 |         input_string_stream iss("34/67"); | 
|---|
| 354 |         CHECK(( iss >> r0 )); | 
|---|
| 355 |         CHECK(( r0 == rat(34,67) )); | 
|---|
| 356 |     } | 
|---|
| 357 |     { | 
|---|
| 358 |         input_string_stream iss("-3/-6"); | 
|---|
| 359 |         CHECK(( iss >> r0 )); | 
|---|
| 360 |         CHECK(( r0 == rat(1,2) )); | 
|---|
| 361 |     } | 
|---|
| 362 |  | 
|---|
| 363 |     /* rational cast tests */ | 
|---|
| 364 |     /* Note that these are not generic. The problem is that rational_cast<T> | 
|---|
| 365 |      * requires a conversion from IntType to T. However, for a user-defined | 
|---|
| 366 |      * IntType, it is not possible to define such a conversion except as | 
|---|
| 367 |      * an operator T(). This causes problems with overloading resolution. | 
|---|
| 368 |      */ | 
|---|
| 369 |     { | 
|---|
| 370 |         boost::rational<int> half(1,2); | 
|---|
| 371 |         CHECK(( boost::rational_cast<double>(half) == 0.5 )); | 
|---|
| 372 |         CHECK(( boost::rational_cast<int>(half) == 0 )); | 
|---|
| 373 |     } | 
|---|
| 374 |  | 
|---|
| 375 |     /* End of main tests.  */ | 
|---|
| 376 |  | 
|---|
| 377 |     /* mean number of times a fair 6-sided die must be thrown | 
|---|
| 378 |        until each side has appeared at least once */ | 
|---|
| 379 |     r0 = IntType(0); | 
|---|
| 380 |     for (int i=1; i<=6; ++i) | 
|---|
| 381 |         r0 += rat(1,i); | 
|---|
| 382 |     r0 *= 6; | 
|---|
| 383 |     CHECK(( r0 == rat(147,10) )); | 
|---|
| 384 | } | 
|---|
| 385 |  | 
|---|
| 386 | } // namespace | 
|---|
| 387 |  | 
|---|
| 388 | // Macro hacking: STR(INT_TYPE) gives the integer type defined by the user *as | 
|---|
| 389 | // a string* for reporting below... | 
|---|
| 390 | #define STR(x) STR2(x) | 
|---|
| 391 | #define STR2(x) #x | 
|---|
| 392 |  | 
|---|
| 393 | int main() | 
|---|
| 394 | { | 
|---|
| 395 |     std::cout << "Running tests for boost::rational<" STR(INT_TYPE) ">\n\n"; | 
|---|
| 396 |  | 
|---|
| 397 |     std::cout << "Implementation issue: the minimal size for a rational\n" | 
|---|
| 398 |               << "is twice the size of the underlying integer type.\n\n" | 
|---|
| 399 |               << "Checking to see if space is being wasted.\n"; | 
|---|
| 400 |     std::cout << "    sizeof(" STR(INT_TYPE) ") == " | 
|---|
| 401 |               << sizeof(INT_TYPE) << "\n"; | 
|---|
| 402 |     std::cout << "    sizeof(boost::rational<" STR(INT_TYPE) ">) == " | 
|---|
| 403 |               << sizeof(boost::rational<INT_TYPE>) << "\n\n"; | 
|---|
| 404 |     if (sizeof(boost::rational<INT_TYPE>) > 2 * sizeof(INT_TYPE)) | 
|---|
| 405 |         std::cout << "Implementation has included padding bytes\n\n"; | 
|---|
| 406 |     else | 
|---|
| 407 |         std::cout << "Implementation has minimal size\n\n"; | 
|---|
| 408 |  | 
|---|
| 409 |     try | 
|---|
| 410 |     { | 
|---|
| 411 |         run_tests(); | 
|---|
| 412 |     } | 
|---|
| 413 |     catch ( ... ) | 
|---|
| 414 |     { | 
|---|
| 415 |         std::cout << "Unexpected exception!\n"; | 
|---|
| 416 |         return EXIT_FAILURE; | 
|---|
| 417 |     } | 
|---|
| 418 |  | 
|---|
| 419 |     unsigned int success_count = total_count - error_count; | 
|---|
| 420 |     unsigned int pct = 100 * success_count / total_count; | 
|---|
| 421 |     std::cout << success_count << "/" << total_count << " tests succeeded (" | 
|---|
| 422 |               << pct << "%). \n"; | 
|---|
| 423 |     return error_count; | 
|---|
| 424 | } | 
|---|