summaryrefslogtreecommitdiff
path: root/src/number.cpp
diff options
context:
space:
mode:
authorMike Buland <mike@xagasoft.com>2013-04-19 15:36:29 -0600
committerMike Buland <mike@xagasoft.com>2013-04-19 15:36:29 -0600
commit7260c36973fc0ad7ff24294ff5540d64bf32c334 (patch)
tree72e74744a789d4c1acedfa1afd1a07219cce9931 /src/number.cpp
parent9ad1a65f4dcbc31b031556803d27dc688a16ff4a (diff)
downloadclic-7260c36973fc0ad7ff24294ff5540d64bf32c334.tar.gz
clic-7260c36973fc0ad7ff24294ff5540d64bf32c334.tar.bz2
clic-7260c36973fc0ad7ff24294ff5540d64bf32c334.tar.xz
clic-7260c36973fc0ad7ff24294ff5540d64bf32c334.zip
Fractional divisoin works.
It doesn't round yet, and there's a chance I should be increasing the precision, right now it keeps the precision of the left hand side number.
Diffstat (limited to 'src/number.cpp')
-rw-r--r--src/number.cpp147
1 files changed, 103 insertions, 44 deletions
diff --git a/src/number.cpp b/src/number.cpp
index b923d5f..15cad95 100644
--- a/src/number.cpp
+++ b/src/number.cpp
@@ -244,8 +244,9 @@ bool Number::operator<=( const Number &rhs ) const
244 244
245void Number::set( const Bu::String &sNum ) 245void Number::set( const Bu::String &sNum )
246{ 246{
247 Bu::println("Parsing: '%1'").arg( sNum ); 247// Bu::println("Parsing: '%1'").arg( sNum );
248 aInt.clear(); 248 aInt.clear();
249 aFrac.zero();
249 bPositive = true; 250 bPositive = true;
250 int iPt; 251 int iPt;
251 for( iPt = 0; iPt < sNum.getSize() && sNum[iPt] != '.'; iPt++ ) { } 252 for( iPt = 0; iPt < sNum.getSize() && sNum[iPt] != '.'; iPt++ ) { }
@@ -262,7 +263,7 @@ void Number::set( const Bu::String &sNum )
262 263
263 for( int j = iPt-1; j >= iEnd; j-- ) 264 for( int j = iPt-1; j >= iEnd; j-- )
264 { 265 {
265 Bu::println(" -> '%1'").arg( sNum[j] ); 266// Bu::println(" -> '%1'").arg( sNum[j] );
266 if( sNum[j] == '.' ) 267 if( sNum[j] == '.' )
267 break; 268 break;
268 if( sNum[j] >= '0' && sNum[j] <= '9' ) 269 if( sNum[j] >= '0' && sNum[j] <= '9' )
@@ -276,7 +277,7 @@ void Number::set( const Bu::String &sNum )
276 int iFrac = 0; 277 int iFrac = 0;
277 for( int j = iPt+1; j < sNum.getSize(); j++ ) 278 for( int j = iPt+1; j < sNum.getSize(); j++ )
278 { 279 {
279 Bu::println(" => '%1'").arg( sNum[j] ); 280// Bu::println(" => '%1'").arg( sNum[j] );
280 if( sNum[j] >= '0' && sNum[j] <= '9' ) 281 if( sNum[j] >= '0' && sNum[j] <= '9' )
281 aFrac.set( iFrac++, sNum[j]-'0' ); 282 aFrac.set( iFrac++, sNum[j]-'0' );
282 else 283 else
@@ -286,7 +287,7 @@ void Number::set( const Bu::String &sNum )
286 } 287 }
287 } 288 }
288 289
289 Bu::println("done."); 290// Bu::println("done.");
290} 291}
291 292
292void Number::set( const Number &sNum ) 293void Number::set( const Number &sNum )
@@ -447,25 +448,28 @@ void Number::divide( const Number &rhs, Number &q, Number &r ) const
447 Number newbase = Number( iScale, iRadix ); 448 Number newbase = Number( iScale, iRadix );
448 int iOff; 449 int iOff;
449 for( iOff = -iScale; iOff < 0 && rhs.digit( iOff ) == 0; iOff++ ) { } 450 for( iOff = -iScale; iOff < 0 && rhs.digit( iOff ) == 0; iOff++ ) { }
450 for( int j = iOff; j < rhs.aInt.getSize(); j++ ) 451 if( iOff < 0 )
451 { 452 {
452 newrhs.aInt.append( rhs.digit( j ) ); 453 for( int j = iOff; j < rhs.aInt.getSize(); j++ )
453 newbase.aInt.append( digit( j ) ); 454 {
454 } 455 newrhs.aInt.append( rhs.digit( j ) );
455 for( int j = 0; j < aInt.getSize(); j++ ) 456 newbase.aInt.append( digit( j ) );
456 { 457 }
457 newbase.aInt.append( aInt.get( j ) ); 458 for( int j = 0; j < aInt.getSize(); j++ )
458 } 459 {
459 for( int j = iScale+iOff; j >= -iOff; j-- ) 460 newbase.aInt.append( aInt.get( j ) );
460 { 461 }
461 newbase.aFrac.set( j+iOff, aFrac.get( j ) ); 462 for( int j = iScale+iOff; j >= -iOff; j-- )
462 } 463 {
464 newbase.aFrac.set( j+iOff, aFrac.get( j ) );
465 }
463 466
464 Bu::println("Conv %1 => %2 (iOff = %3)").arg( rhs ).arg( newrhs ).arg( iOff ); 467// Bu::println("Conv %1 => %2 (iOff = %3)").arg( rhs ).arg( newrhs ).arg( iOff );
465 Bu::println("Conv %1 => %2 (iOff = %3)").arg( *this ).arg( newbase ).arg( iOff ); 468// Bu::println("Conv %1 => %2 (iOff = %3)").arg( *this ).arg( newbase ).arg( iOff );
466 469
467 newbase.divide( newrhs, q, r ); 470 newbase.divide( newrhs, q, r );
468 return; 471 return;
472 }
469 } 473 }
470 474
471 q = Number( iScale, iRadix ); 475 q = Number( iScale, iRadix );
@@ -482,60 +486,115 @@ void Number::divide( const Number &rhs, Number &q, Number &r ) const
482 int iSample = iMinWidth; 486 int iSample = iMinWidth;
483 do 487 do
484 { 488 {
485 Bu::println("%1\n-----").arg( r.aInt.toString() ); 489// Bu::println("%1\n-----").arg( r.aInt.toString() );
486 Number sub( iScale, iRadix ); 490 Number sub( 0, iRadix );
491 if( iAnchor < 0 )
492 {
493 sub = r;
494 sub.aInt.insert(0,0);
495 }
487 for(;;) 496 for(;;)
488 { 497 {
489 Bu::println(" -> Anchor: %1, Sample: %2").arg( iAnchor ).arg( iSample ); 498// Bu::println(" -> Anchor: %1, Sample: %2").arg( iAnchor ).arg( iSample );
490 sub.aInt.set( r.aInt, iAnchor, iSample ); 499 if( iAnchor >= 0 )
491 Bu::println("%1\n%2\n----").arg( sub.toString() ).arg( rhs.toString() ); 500 {
501 sub.aInt.set( r.aInt, iAnchor, iSample );
502 }
503 else
504 {
505/* sub.aInt.clear();
506 for( int j = iAnchor; j < r.aInt.getSize(); j++ )
507 {
508 sub.aInt.append( r.digit( j ) );
509 }
510 */
511 }
512// Bu::println("%1\n%2\n----").arg( sub.toString() ).arg( rhs.toString() );
492 if( sub < rhs ) 513 if( sub < rhs )
493 { 514 {
494 iSample++; 515 iSample++;
495 iAnchor--; 516 iAnchor--;
496 if( iAnchor < 0 ) 517 if( iAnchor < 0 )
497 { 518 {
498 Bu::println("[Inner exit] Complete: q = %1, r = %2").arg( q.toString() ).arg( r.toString() ); 519 if( r.isZero() || iAnchor < -iScale )
499 return; 520 {
521// Bu::println("[Inner exit] Complete: q = %1, r = %2").arg( q.toString() ).arg( r.toString() );
522 return;
523 }
524 sub.aInt.insert(0, 0);
500 } 525 }
501 } 526 }
502 else 527 else
503 break; 528 break;
504 } 529 }
505 530
506 Number x( rhs.iScale, iRadix ); 531 Number x( 0, iRadix );
507 int iRes = -1; 532 int iRes = -1;
508 Bu::println("{x = %1, sub=%2, rhs=%4, iRes=%3}").arg( x ).arg(sub).arg(iRes).arg(rhs); 533// Bu::println("{x = %1, sub=%2, rhs=%4, iRes=%3}").arg( x ).arg(sub).arg(iRes).arg(rhs);
509 for( ; x <= sub; iRes++, x = x + rhs ) { 534 for( ; x <= sub; iRes++, x = x + rhs ) {
510 Bu::println("{x = %1, sub=%2, rhs=%4, iRes=%3, x+rhs=%5}").arg( x ).arg(sub).arg(iRes).arg(rhs).arg(x+rhs); 535// Bu::println("{x = %1, sub=%2, rhs=%4, iRes=%3, x+rhs=%5}").arg( x ).arg(sub).arg(iRes).arg(rhs).arg(x+rhs);
511 } 536 }
512 x = sub - (x - rhs); 537 x = sub - (x - rhs);
513 if( !x.bPositive ) 538 if( !x.bPositive )
514 { 539 {
515 iSample++; 540 iSample++;
516 iAnchor--; 541 iAnchor--;
517 Bu::println("What? it's negative? %1").arg( x ); 542// Bu::println("What? it's negative? %1").arg( x );
518 continue; 543 continue;
519 } 544 }
520 for( int j = 0; iAnchor+j >= 0 && j < x.aInt.getSize(); j++ ) 545 if( iAnchor < 0 )
521 r.aInt.set( iAnchor+j, x.aInt.get( j ) ); 546 {
522 while( r.aInt.getSize() > iAnchor+x.aInt.getSize() ) 547 r = x;
548 }
549 else
550 {
551 for( int j = 0; j < x.aInt.getSize(); j++ )
552 r.aInt.set( iAnchor+j, x.aInt.get( j ) );
553 }
554
555 while( r.aInt.getSize() > Bu::buMax(0,iAnchor)+x.aInt.getSize() )
523 r.aInt.remove(); 556 r.aInt.remove();
524 Bu::println(" -> Post remainder patch: %1 -> %2"). 557// Bu::println(" -> Post remainder patch: %1 -> %2").
525 arg( x.toString() ).arg( r.toString() ); 558// arg( x.toString() ).arg( r.toString() );
526 559
527 Bu::println("%1 (%2)").arg( iRes ).arg( x.toString() ); 560// Bu::println("%1 (%2)").arg( iRes ).arg( x.toString() );
528 while( q.aInt.getSize() <= iAnchor ) 561 while( q.aInt.getSize() <= iAnchor )
529 q.aInt.append(0); 562 q.aInt.append(0);
530 q.aInt.set( iAnchor, iRes ); 563 if( iAnchor >= 0 )
531 564 q.aInt.set( iAnchor, iRes );
565 else
566 q.aFrac.set( -1-iAnchor, iRes );
567
532 iSample = iMinWidth; 568 iSample = iMinWidth;
533 iAnchor = r.aInt.getSize()-iMinWidth; 569 if( iAnchor > 0 )
534 Bu::println(" -> new Anchor: %1, Sample: %2").arg( iAnchor ). 570 iAnchor -= rhs.aInt.getSize()-x.aInt.getSize();
535 arg( iSample ); 571 else
536 } while( iAnchor >= 0 ); 572 iAnchor--;
573// iAnchor = r.aInt.getSize()-iMinWidth;
574// Bu::println(" -> new Anchor: %1, Sample: %2").arg( iAnchor ).
575// arg( iSample );
576 } while( iAnchor >= -iScale );
577
578// Bu::println("Complete: q = %1, r = %2").arg( q.toString() ).arg( r.toString() );
579}
580
581bool Number::isZero() const
582{
583 if( aInt.getSize() == 0 && iScale == 0 )
584 return true;
537 585
538 Bu::println("Complete: q = %1, r = %2").arg( q.toString() ).arg( r.toString() ); 586 for( int j = 0; j < aInt.getSize(); j++ )
587 {
588 if( aInt[j] )
589 return false;
590 }
591 for( int j = 0; j < aFrac.getSize(); j++ )
592 {
593 if( aFrac[j] )
594 return false;
595 }
596
597 return true;
539} 598}
540 599
541Bu::Formatter &operator<<( Bu::Formatter &f, const Number &n ) 600Bu::Formatter &operator<<( Bu::Formatter &f, const Number &n )