Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/rational/rational_test.cpp @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

File size: 12.9 KB
Line 
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>
30namespace {
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
47namespace {
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<>
51class MyInt : boost::operators<MyInt>
52{
53    int val;
54public:
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
75inline MyInt operator+(const MyInt& rhs) { return rhs; }
76inline MyInt operator-(const MyInt& rhs) { return MyInt(-rhs.val); }
77inline std::istream& operator>>(std::istream& is, MyInt& i) { is >> i.val; return is; }
78inline std::ostream& operator<<(std::ostream& os, const MyInt& i) { os << i.val; return os; }
79inline MyInt abs(MyInt rhs) { if (rhs < MyInt()) rhs = -rhs; return rhs; }
80
81// Test statistics
82static unsigned int total_count;
83static unsigned int error_count;
84
85// Check a specific assertion
86void 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
102void 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
221using 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
393int 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}
Note: See TracBrowser for help on using the repository browser.