00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "BUnit.h"
00011 #include <iostream>
00012 using namespace std;
00013
00014
00015
00016
00017 #if defined(Bosak)
00018 #include "number.h"
00019 typedef Number HugeInt;
00020 #elif defined(Narvaja)
00021 #include "GranNum.h"
00022 typedef BigNum HugeInt;
00023 #else
00024 typedef long HugeInt;
00025 #endif
00026
00027 #include "rational.h"
00028
00029
00030 template <class INT>
00031 class test_rational : public TestCase {
00032 protected:
00033 rational<INT> m_half, m_quarter, m_one;
00034 rational<INT> m_half_neg, m_quarter_neg, m_one_neg;
00035 rational<INT> m_sep, m_sep_neg;
00036 bool m_super_lerdo;
00037 bool m_super_numerotes;
00038 public:
00039 virtual void setUp();
00040
00041 void super_numerotes(bool sl = false) {
00042 m_super_numerotes = sl;
00043 }
00044
00045 void super_lerdo(bool sl = false) {
00046 m_super_lerdo = sl;
00047 if (m_super_lerdo) {
00048 m_super_numerotes = true;
00049 }
00050 }
00051 public:
00052 bool run();
00053 void rat_tst(); void run_rest();
00054 void test_quiebra_Narvaja();
00055 void test_constructor();
00056 void test_destructor();
00057 void test_set();
00058 void test_op_equal();
00059 void test_num_den();
00060 void test_swap();
00061 void test_op_add_equal();
00062 void test_op_add();
00063 void test_op_mult_equal();
00064 void test_op_mult();
00065 void test_op_minus();
00066 void test_fromString();
00067 void test_op_comp();
00068 void test_op_in();
00069 void test_op_out();
00070 void test_simplify();
00071 void test_check_ok();
00072 void test_mcd();
00073 void test_op_cpp();
00074 };
00075
00076
00077
00078 template <class INT>
00079 bool test_rational<INT>::run() {
00080 test_quiebra_Narvaja();
00081 test_constructor();
00082 test_destructor();
00083 test_set();
00084 test_op_equal();
00085 test_num_den();
00086 test_swap();
00087 test_op_add_equal();
00088 test_op_add();
00089 test_op_mult_equal();
00090 test_op_mult();
00091 test_op_minus();
00092 test_fromString();
00093 test_op_comp();
00094 test_op_in();
00095 test_op_out();
00096
00097 test_simplify();
00098 test_check_ok();
00099 test_mcd();
00100 test_op_cpp();
00101 rat_tst(); run_rest();
00102 return TestCase::wasSuccessful();
00103 }
00104
00105 template <class INT>
00106 void test_rational<INT>::setUp() {
00107 m_half.set(1,2);
00108 m_quarter.set(1,4);
00109 m_one.set(1);
00110 m_half_neg.set(-1,2);
00111 m_quarter_neg.set(-1,4);
00112 m_one_neg.set(-1);
00113 m_sep.set(1,7);
00114 m_sep_neg.set(-1,7);
00115 m_super_lerdo = false;
00116 m_super_numerotes = false;
00117 }
00118
00119 template <class INT> INT pow( const INT & r, int n );
00120 template <class INT> void grabador (ostream &COUT, const INT & r);
00121 template <class INT> const char * aHilera(const INT& r);
00122 template <class INT> const char * aHilera(const rational<INT>& r);
00123 template <class INT> rational<INT>& set( rational<INT>& r, const char * num, const char * den = "1" );
00124 template <class INT> INT& set( INT& num, const char * str );
00125
00126
00127
00128 template <class INT>
00129 void test_rational<INT>::test_quiebra_Narvaja() {
00130 {{
00131 rational<INT> r; assertTrue( r.num() == 0 && r.den() == 1 );
00132 r.set( 5*11, 2*11 ); assertTrue( r.num() == 5 && r.den() == 2 );
00133 rational<INT> s(-1,2); assertTrue( s.num() == -1 && s.den() == 2 );
00134 rational<INT> t(1,-2); assertTrue( t.num() == -1 && t.den() == 2 );
00135 assertTrue( r != s );
00136 assertTrue( s == t );
00137 std::basic_ostringstream<char> ost;
00138 {
00139 const char* str = aHilera(r);
00140 ost.str(""); ost << str; assertTrue( ost.str() == "2" );
00141 delete [] str;
00142 ost.str("");
00143 str = aHilera(s.num());
00144 ost << '['<< str;
00145 delete [] str;
00146 str = aHilera( s.den() );
00147 ost << '/' << str << ']';
00148 delete [] str;
00149 assertTrue( ost.str() == "[-1/2]" );
00150 assertFalse( ost.str() == "[-1/0]" );
00151 }
00152 if (1) {
00153 ost.str(""); ost << r;
00154 ost.str(""); ost << s;
00155 ost.str(""); ost << rational<INT>(-1,2);
00156 }
00157 }}
00158 {
00159 }
00160 }
00161
00162
00163 template <class INT>
00164 void test_rational<INT>::test_constructor() {
00165 {{
00166 rational<INT> r,s,t(1,-2);
00167 assertTrue( r == rational<INT>(0) );
00168 assertTrue( s == rational<INT>(0,32) );
00169 assertTrue( t == rational<INT>(-100,200) );
00170 rational<INT> q = t;
00171 assertTrue( q == t );
00172 }}
00173 {
00174 }
00175 }
00176
00177
00178 template <class INT>
00179 void test_rational<INT>::test_destructor() {
00180 return test_constructor();
00181 }
00182
00183
00184 template <class INT>
00185 void test_rational<INT>::test_set() {
00186 {{
00187 rational<INT> r;
00188 assertTrue( r == rational<INT>( 0 ) );
00189 r.set(-3, -4);
00190 assertTrue( r == rational<INT>( 3*11 , 4*11 ) );
00191 }}
00192 {
00193 }
00194 }
00195
00196
00197 template <class INT>
00198 void test_rational<INT>::test_num_den() {
00199 {{
00200 rational<INT> r; assertTrue( r.num() == 0 && r.den() == 1 );
00201 r.set( -1*13, -4*13 ); assertTrue( r.num() == 1 && r.den() == 4 );
00202 r.set( -2*11, 5*11 ); assertTrue( r.num() == -2 && r.den() == 5 );
00203 r.set( 2*17, -6*17 ); assertTrue( r.num() == -1 && r.den() == 3 );
00204 }}
00205 {
00206 }
00207 }
00208
00209
00210 template <class INT>
00211 void test_rational<INT>::test_op_equal() {
00212 {{
00213 rational<INT> r(1), s(18,56); assertTrue( r == rational<INT>(1) );
00214 r = s; assertTrue( r == ( r / ( r / s ) ) );
00215 r = 34; assertTrue( r == rational<INT>(34) );
00216 s = -3; assertTrue( s == rational<INT>(-3) );
00217 }}
00218 {
00219 }
00220 }
00221
00222
00223 template <class INT>
00224 void test_rational<INT>::test_swap() {
00225 {{
00226 rational<INT> r, s(18,56); assertTrue( r == rational<INT>(0) );
00227 r.swap( s ); assertTrue( s == rational<INT>(0) );
00228 assertTrue( r == rational<INT>(18,56) );
00229 }}
00230 {
00231 }
00232 }
00233
00234
00235 template <class INT>
00236 void test_rational<INT>::test_op_add_equal() {
00237 {{
00238 rational<INT> add(0), sub(0);
00239 for ( int i=20; i>=-20; --i ) {
00240 add += rational<INT>(i-i, 20*i+1);
00241 sub -= rational<INT>(i-i, 20*i+1);
00242 }
00243 assertTrue( add == sub );
00244 }}
00245 {
00246 }
00247 }
00248
00249
00250 template <class INT>
00251 void test_rational<INT>::test_op_add() {
00252 {{
00253 rational<INT> add(0), sub(0);
00254 for ( int i=20; i>=-20; --i ) {
00255 add = add + rational<INT>(i-i, 20*i+1);
00256 sub = sub - rational<INT>(i-i, 20*i+1);
00257 }
00258 assertTrue( add == sub );
00259 }}
00260 {
00261 }
00262 }
00263
00264
00265 template <class INT>
00266 void test_rational<INT>::test_op_mult_equal() {
00267 {{
00268 rational<INT> mlt(1), div(1);
00269 for ( int i=15; i>=-15; --i ) {
00270 mlt *= rational<INT>(17*i-1, 13*i+1);
00271 div /= rational<INT>(13*i+1, 17*i-1);
00272 }
00273 assertTrue( mlt == div );
00274 }}
00275 {
00276 }
00277 }
00278
00279
00280 template <class INT>
00281 void test_rational<INT>::test_op_mult() {
00282 {{
00283 rational<INT> mlt(1), div(1);
00284 for ( int i=15; i>=-15; --i ) {
00285 mlt = mlt * rational<INT>(17*i-1, 13*i+1);
00286 div = div / rational<INT>(13*i+1, 17*i-1);
00287 }
00288 assertTrue( mlt == div );
00289 }}
00290 {
00291 }
00292 }
00293
00294
00295 template <class INT>
00296 void test_rational<INT>::test_op_minus() {
00297 {{
00298 rational<INT> half_n(1,-2), quarter_n(-1,4);
00299 assertTrue( - half_n == rational<INT>(-1) * half_n );
00300 assertTrue( half_n * half_n == - quarter_n );
00301 assertTrue( half_n * half_n * half_n == - quarter_n * half_n );
00302 }}
00303 {
00304 }
00305 }
00306
00307
00308 template <class INT>
00309 void test_rational<INT>::test_fromString() {
00310 {{
00311 rational<INT> r, half(1,2), quarter(1,4);
00312 assertTrue( - half == r.fromString( "[---12/24]" ) );
00313 assertTrue( quarter == r.fromString( "[ -03/ -12 ]") );
00314 r.fromString( "[ -+-+-+-+- 4 / -- -+ -- 32 ]" );
00315 assertTrue( r == rational<INT>(1,8) );
00316 }}
00317 {
00318 }
00319 }
00320
00321
00322 template <class INT>
00323 void test_rational<INT>::test_simplify() {
00324 {{
00325 rational<INT> half(1,2);
00326 half.m_num *= 23;
00327 half.m_den *= 23;
00328 assertTrue( half != rational<INT>(23, 23*2) );
00329 half.simplify();
00330 assertTrue( half == rational<INT>(23, 23*2) );
00331 }}
00332 {
00333 }
00334 }
00335
00336
00337 template <class INT>
00338 void test_rational<INT>::test_check_ok() {
00339 {{
00340 rational<INT> r, *nul=0; assertFalse( check_ok(*nul) );
00341 r.m_num = 2; r.m_den = 0; assertFalse( check_ok( r ) );
00342 r.m_num = 2; r.m_den = -1; assertFalse( check_ok( r ) );
00343 r.m_num = 0; r.m_den = 2; assertFalse( check_ok( r ) );
00344 r.m_num = 31; r.m_den = 31; assertFalse( check_ok( r ) );
00345 r.simplify(); assertTrue ( check_ok( r ) );
00346 }}
00347 {
00348 }
00349 }
00350
00351
00352 template <class INT>
00353 void test_rational<INT>::test_op_comp() {
00354 {{
00355 rational<INT> neg_half(-1,2), quarter(1,4);
00356 assertTrue( neg_half == -(-neg_half) );
00357 assertTrue( neg_half < quarter );
00358 assertTrue( quarter > neg_half );
00359 assertTrue( neg_half <= quarter );
00360 assertTrue( quarter >= neg_half );
00361 assertTrue( neg_half != quarter );
00362 }}
00363 {
00364 }
00365 }
00366
00367
00368 template <class INT>
00369 void test_rational<INT>::test_op_out() {
00370 {{
00371 std::basic_ostringstream<char> ost;
00372 ost.str(""); ost << rational<INT>(-1,2); assertTrue( ost.str() == "[-1/2]" );
00373 ost.str(""); ost << rational<INT>(-12); assertTrue( ost.str() == "[-12]" );
00374 ost.str(""); ost << rational<INT>(1-1,8); assertTrue( ost.str() == "[0]" );
00375 ost.str("");
00376 ost << rational<INT>(-1,2) << rational<INT>(-12) << rational<INT>(1-1,8);
00377 assertTrue( ost.str() == "[-1/2][-12][0]" );
00378 }}
00379 {
00380 std::basic_ostringstream<char> r_ost, s_ost, t_ost;
00381 r_ost << rational<INT>(-1,2); assertTrue( r_ost.str() == "[-1/2]" );
00382 s_ost << rational<INT>(-12); assertTrue( s_ost.str() == "[-12]" );
00383 t_ost << rational<INT>(1-1,8); assertTrue( t_ost.str() == "[0]" );
00384 }
00385 {
00386 }
00387 }
00388
00389
00390 template <class INT>
00391 void test_rational<INT>::test_op_in() {
00392 {{
00393 std::basic_istringstream<char> ist( "[-1/2] [-12] [0]" );
00394 rational<INT> r(0); ist >> r; assertTrue( r == rational<INT>(-1,2) );
00395 rational<INT> s(1); ist >> s; assertTrue( s == rational<INT>(-12) );
00396 rational<INT> t(2); ist >> t; assertTrue( t == rational<INT>(0) );
00397
00398 ist.str( "[ -+-+-+-+- 4 / -- -+ -- 32 ]" );
00399 rational<INT> u(3); ist >> u; assertTrue( u == rational<INT>(1,8) );
00400 }}
00401 {
00402 }
00403 }
00404
00405
00406 template <class INT>
00407 void test_rational<INT>::test_mcd() {
00408 {{
00409 assertTrue( 1 == mcd(1,2) );
00410 assertTrue( 2*3*5 == mcd( 2*2*2*2 * 3*3 * 5*5, 2*3*5 ) );
00411 assertTrue( 30 == mcd( -3600, -30 ) );
00412 }}
00413 {
00414 }
00415 }
00416
00417
00418 template <class INT>
00419 void test_rational<INT>::test_op_cpp() {
00420 {{
00421 rational<INT> r(3,2);
00422
00423 assertTrue( r++ == rational<INT>(3,2) );
00424 assertTrue( r == rational<INT>(5,2) );
00425
00426 assertTrue( r-- == rational<INT>(5,2) );
00427 assertTrue( r == rational<INT>(3,2) );
00428
00429 assertTrue( --r == rational<INT>(1,2) );
00430 }}
00431 {
00432 rational<INT> r(4,3);
00433
00434 assertTrue( r++ == rational<INT>(4,3) );
00435 assertTrue( r == rational<INT>(7,3) );
00436
00437 assertTrue( r-- == rational<INT>(7,3) );
00438 assertTrue( r == rational<INT>(4,3) );
00439
00440 assertTrue( --r == rational<INT>(1,3) );
00441 }
00442 { rational<INT> r(4,3);
00443
00444 assertTrue( r-- == rational<INT>(4,3) );
00445 assertTrue( r == rational<INT>(1,3) );
00446
00447 assertTrue( r++ == rational<INT>(1,3) );
00448 assertTrue( r == rational<INT>(4,3) );
00449
00450 assertTrue( --r == rational<INT>(1,3) );
00451 }
00452 }
00453
00454
00455 template <class INT>
00456 void test_rational<INT>::rat_tst() {
00457 rational<INT> r,
00458 s(1),
00459 t = 1,
00460 u(1,2);
00461
00462 assertTrue( r == rational<INT>(0) );
00463 assertTrue( s == rational<INT>(1) );
00464 assertTrue( t == s );
00465 assertTrue( u == rational<INT>(1,2) );
00466
00467 rational<INT> a = t;
00468 assertTrue( a == t );
00469 a = t;
00470 assertTrue( a == t );
00471
00472 (a += s * rational<INT>(2)) += rational<INT>(4);
00473 assertTrue( a == rational<INT>(7) );
00474 assertTrue( s == rational<INT>(1) );
00475 assertTrue( rational<INT>(1) == s );
00476
00477 a = rational<INT>(4, -5);
00478 rational<INT> b(-10, 6);
00479 a *= b;
00480
00481 assertTrue( a == rational<INT>( 4*-10,-5*6) );
00482
00483 a=b;
00484 assertTrue( a == b );
00485 assertTrue( b == a );
00486
00487 a = rational<INT>(4, -5);
00488 a += b;
00489 assertTrue( a == rational<INT>( 4*6 + -5*-10, -5*6 ) );
00490
00491 a -= b;
00492 assertTrue( a == rational<INT>(-4, 5) );
00493
00494 a = b;
00495 assertTrue( a == b );
00496
00497 a -= a;
00498 assertTrue( a == rational<INT>(0) );
00499 assertTrue( rational<INT>(0) == a );
00500
00501 rational<INT> c(15);
00502 assertTrue( rational<INT>(15) == c );
00503
00504 a /= c;
00505 assertTrue( a == rational<INT>(0) );
00506 assertTrue( rational<INT>(0) == a );
00507
00508 a = 1234567l;
00509 assertTrue( a == rational<INT>(1234567l) );
00510
00511 long d = 4;
00512 a = d;
00513 assertTrue( a == rational<INT>(d) );
00514 assertTrue( rational<INT>(d) == a );
00515
00516 a += (b = rational<INT>(5));
00517 assertTrue( a == rational<INT>(d+5) );
00518 assertTrue( b == rational<INT>(5) );
00519
00520 a = rational<INT> (4, -5);
00521 b = rational<INT> (5, -4);
00522 assertTrue( a*b == rational<INT>(1) );
00523 assertTrue( a/b == rational<INT>( -4*4 , -5*5 ) );
00524 assertTrue( b/a == rational<INT>( -5*5 , -4*4 ) );
00525
00526 rational<INT> tot = rational<INT>(0);
00527 for (int i = 0; i <= 50; ++i) {
00528 tot += rational<INT>(i, i+1);
00529 }
00530 {
00531 bool good_sum = false;
00532 good_sum = good_sum || TestCase::toString(tot) == "[2668385009430893323/8818708306321991968]";
00533 good_sum = good_sum || TestCase::toString(tot) == "[64263385/206760032]";
00534 good_sum = good_sum || TestCase::toString(tot) == "[3067/4896]";
00535 assertTrue_Msg( "sum(0==>50 { rational<INT>(i, i+1) }", good_sum );
00536 }
00537
00538 assertTrue( rational<INT>( 1,4) == rational<INT>().fromString("[ 1 / - - 4 ]"));
00539 assertTrue( rational<INT>(-1,4) == rational<INT>().fromString("[-1 / - - 4 ]"));
00540 assertTrue( rational<INT>(-1,4) == rational<INT>().fromString("[ - 1 / -- 4 ]"));
00541 assertTrue( rational<INT>( 1,4) == rational<INT>().fromString("[ - 1 / - 4 ]"));
00542
00543 {
00544
00545 rational<INT> VEC[17];
00546 size_t nVEC = sizeof(VEC) / sizeof(*VEC);
00547
00548 size_t i;
00549 srand( 1492 );
00550 for (i=0; i<nVEC; ++i) {
00551 rational<INT> r(rand(), rand());
00552 VEC[i] = r;
00553 assertTrue( check_ok( VEC[i] ) );
00554 assertTrue( r == VEC[i] );
00555 }
00556
00557 selection_sort(VEC, nVEC);
00558 assertTrue( Ordenado(VEC, nVEC) );
00559 }
00560 }
00561
00562
00563
00564 template <class INT>
00565 rational<INT> rat( const char* num , const char * den = "1" ) {
00566 rational<INT> RES;
00567 return set( RES, num, den );
00568 }
00569
00570
00571
00572 template <class INT>
00573 void test_rational<INT>::run_rest() {
00574 {
00575 assertTrue( rational<INT>(0) * rational<INT>(0,2) == rational<INT>(0,4) );
00576
00577 assertTrue( rat<INT>( "100" , "2" ) * rat<INT>( "2" , "100" ) == rat<INT>( "1" , "1" ) );
00578 assertTrue( rat<INT>( "99" , "99" ) * rat<INT>( "99" , "99" ) == rat<INT>( "1" ) );
00579
00580 assertTrue( m_half / rat<INT>( "1" , "1" ) == rat<INT>( "128" , "256" ) );
00581 assertTrue( rat<INT>( "10" , "40" )/rat<INT>( "10" , "40" ) == rat<INT>( "1" ) );
00582
00583 assertTrue( m_quarter / rat<INT>( "2" ) == rat<INT>( "1" , "8" ) );
00584 assertTrue( m_quarter / m_half == rat<INT>( "2" , "4" ) );
00585
00586 assertTrue( rat<INT>( "75" , "100" ) / rat<INT>( "100" , "75" ) == rat<INT>( "75" , "100" ) * rat<INT>( "75" , "100" ));
00587
00588 assertTrue( ( m_half + m_quarter ) == rat<INT>( "3" , "4" ) );
00589
00590 assertTrue( ( m_one + m_quarter ) == rat<INT>( "5" , "4" ) );
00591 assertTrue( ( rat<INT>( "75" , "100" )+= rat<INT>( "0" ) )== rat<INT>( "75" , "100" ) );
00592
00593 assertTrue( ( m_half + m_quarter) == rational<INT>(3,4) );
00594 assertTrue( ( m_half + rational<INT>(85,40000)) == rational<INT>(40170,80000) );
00595
00596 assertTrue( (m_one + m_quarter) == rational<INT>(5,4) );
00597 assertTrue( (rational<INT>(75,100)+= rational<INT>(0) )== rational<INT>(75,100) );
00598
00599 assertTrue( (m_quarter + rational<INT>(-1)) == rational<INT>(-3,4) );
00600 assertTrue( (rational<INT>(50,37)+rational<INT>(50,37) ) == rational<INT>(2)*rational<INT>(50,37) );
00601
00602 assertTrue(( m_half - m_quarter )== m_quarter );
00603 assertTrue(( rational<INT>(10,40) - rational<INT>(10,40) ) == rational<INT>(0) );
00604
00605 assertTrue( ( -m_half + m_quarter)== rational<INT>(-1,4) );
00606 assertTrue( ( rational<INT>(-75,100) )== m_quarter-m_one );
00607
00608 assertTrue( ( rational<INT>(75,100) - rational<INT>(75)) == -rational<INT>(7425,100) );
00609 assertTrue( ( m_quarter - rational<INT>(1) )== rational<INT>(-3,4) );
00610
00611 assertTrue( m_half * rational<INT>(0,2) == rational<INT>(0,4) );
00612 assertTrue( m_half * rational<INT>(0,2) == rational<INT>(0) );
00613
00614 assertTrue( rational<INT>(0) * rational<INT>(0,2) == rational<INT>(0,4) );
00615 assertEquals( rat<INT>("1", "1") , m_one );
00616 assertEquals( rat<INT>("1", "2") , m_half );
00617 assertEquals( rat<INT>("1", "4") , m_quarter );
00618 assertTrue( m_half / rational<INT>(1,1) == rational<INT>(13,26) );
00619 assertTrue( rational<INT>(10,40)/rational<INT>(10,40) == rational<INT>(1) );
00620
00621 assertTrue( m_quarter / rational<INT>(2) == rational<INT>(1,8) );
00622 assertTrue( m_quarter / m_half == rational<INT>(2,4));
00623
00624 assertTrue( (rational<INT>(75,100) /= rational<INT>(100,75)) == rational<INT>(75*75,100*100) );
00625
00626 assertTrue( (rational<INT>(50,37)+=rational<INT>(50,37) ) == rational<INT>(2)*rational<INT>(50,37) );
00627
00628 assertTrue(( rational<INT>(10,40) -= rational<INT>(10,40) ) == rational<INT>(0) );
00629
00630 assertTrue( ( rational<INT>(-3,4) -= m_quarter )== rational<INT>(-1) );
00631 assertTrue( ( -m_half + m_quarter)== rational<INT>(-1,4) );
00632
00633 assertTrue( ( rational<INT>(75,100) -= rational<INT>(75)) == rational<INT>(75*1-75*100, 1*100) );
00634
00635 assertTrue( (rational<INT>(99,99) *= rational<INT>(0,2)) == rational<INT>(0,4) );
00636
00637 assertTrue( (rational<INT>(100,2) *= rational<INT>(2,100)) == rational<INT>(1,1) );
00