diff options
author | Mike Buland <mike@xagasoft.com> | 2014-10-31 10:41:57 -0600 |
---|---|---|
committer | Mike Buland <mike@xagasoft.com> | 2014-10-31 10:41:57 -0600 |
commit | 9e204039f0b310bdb101063bbfb82b9a9fb5d5e0 (patch) | |
tree | fef00f18505f649b3dfa07a2aa3dccef92bcb651 /src | |
parent | 301844ef30b44966463ab22d6a518bc302330e1e (diff) | |
download | clic-9e204039f0b310bdb101063bbfb82b9a9fb5d5e0.tar.gz clic-9e204039f0b310bdb101063bbfb82b9a9fb5d5e0.tar.bz2 clic-9e204039f0b310bdb101063bbfb82b9a9fb5d5e0.tar.xz clic-9e204039f0b310bdb101063bbfb82b9a9fb5d5e0.zip |
Corrected issue with particular sequences of zeros.
No more known division issues.
Diffstat (limited to 'src')
-rw-r--r-- | src/config.h | 8 | ||||
-rw-r--r-- | src/number.cpp | 60 |
2 files changed, 48 insertions, 20 deletions
diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..00fb067 --- /dev/null +++ b/src/config.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef CONFIG_H | ||
2 | #define CONFIG_H | ||
3 | |||
4 | #define DEBUG_DIVIDE false | ||
5 | #define DBS( s, x ) if( DEBUG_ ##s ) { x; } (void)0 | ||
6 | |||
7 | |||
8 | #endif | ||
diff --git a/src/number.cpp b/src/number.cpp index 9a7da17..328cb58 100644 --- a/src/number.cpp +++ b/src/number.cpp | |||
@@ -1,8 +1,20 @@ | |||
1 | #include "config.h" | ||
1 | #include "number.h" | 2 | #include "number.h" |
2 | 3 | ||
3 | #include <bu/sio.h> | 4 | #include <bu/sio.h> |
4 | #include <math.h> | 5 | #include <math.h> |
5 | 6 | ||
7 | // Enjoy the majisty of my magic floating point literal! | ||
8 | // This tells us how many bits we'll need per digit to represent a particular | ||
9 | // radix. You can figure out how many digits any number will take up in any | ||
10 | // radix with the following: | ||
11 | // | ||
12 | // ceiling(ln( num ) / ln( radix )) | ||
13 | // | ||
14 | // As long as the base of the logs are the same it doesn't matter what the base | ||
15 | // is, it cancels out, so we don't have to be particular. But we're always | ||
16 | // looking for the largest number in a radix to be stored in binary, so the | ||
17 | // denominator is always the same, so I precomputed it. | ||
6 | #define RadixToBits( x ) ((int)(log((x))*0xb.8aa3b295c17fp-3+1.0)) | 18 | #define RadixToBits( x ) ((int)(log((x))*0xb.8aa3b295c17fp-3+1.0)) |
7 | 19 | ||
8 | Number::Number( int iScale, int iRadix ) : | 20 | Number::Number( int iScale, int iRadix ) : |
@@ -392,27 +404,27 @@ void Number::set( int32_t iNum ) | |||
392 | 404 | ||
393 | void Number::divide( const Number &rhs, Number &q, Number &r ) const | 405 | void Number::divide( const Number &rhs, Number &q, Number &r ) const |
394 | { | 406 | { |
395 | // Bu::println("divide: %1 / %2").arg( *this ).arg( rhs ); | 407 | DBS( DIVIDE, Bu::println("divide: %1 / %2").arg( *this ).arg( rhs ) ); |
396 | 408 | ||
397 | // iNumShift is how many digits we've shifted the entire equation, | 409 | // iNumShift is how many digits we've shifted the entire equation, |
398 | // effectively multiplying the numerator and divisor by iRadix*iNumShift | 410 | // effectively multiplying the numerator and divisor by iRadix*iNumShift |
399 | int iNumShift = rhs.getEffectiveScale(); | 411 | int iNumShift = rhs.getEffectiveScale(); |
400 | // Bu::println("iNumShift = %1").arg( iNumShift ); | 412 | DBS( DIVIDE, Bu::println("iNumShift = %1").arg( iNumShift ) ); |
401 | 413 | ||
402 | // Setup our divisor, this is important, it should be an integer to make | 414 | // Setup our divisor, this is important, it should be an integer to make |
403 | // things easy, and it won't change once we create it. | 415 | // things easy, and it won't change once we create it. |
404 | Number nDiv( 0, iRadix ); | 416 | Number nDiv( 0, iRadix ); |
405 | for( int j = -iNumShift; j < rhs.aInt.getSize(); j++ ) | 417 | for( int j = -iNumShift; j < rhs.aInt.getSize(); j++ ) |
406 | { | 418 | { |
407 | // Bu::println(" -> '%1'").arg( rhs.digit( j ) ); | 419 | DBS( DIVIDE, Bu::println(" -> '%1'").arg( rhs.digit( j ) ) ); |
408 | nDiv.aInt.append( rhs.digit( j ) ); | 420 | nDiv.aInt.append( rhs.digit( j ) ); |
409 | } | 421 | } |
410 | // Bu::println("New divisor: %1").arg( nDiv ); | 422 | DBS( DIVIDE, Bu::println("New divisor: %1").arg( nDiv ) ); |
411 | 423 | ||
412 | // Anchor is the position in the output the new digit will appear. | 424 | // Anchor is the position in the output the new digit will appear. |
413 | // This also tells us where the ones place will be in our new numerator. | 425 | // This also tells us where the ones place will be in our new numerator. |
414 | int iAnchor = (aInt.getSize()+iNumShift)-nDiv.aInt.getSize(); | 426 | int iAnchor = (aInt.getSize()+iNumShift)-nDiv.aInt.getSize(); |
415 | // Bu::println("Anchor: %1").arg( iAnchor ); | 427 | DBS( DIVIDE, Bu::println("Anchor: %1").arg( iAnchor ) ); |
416 | 428 | ||
417 | // Setup our output variables | 429 | // Setup our output variables |
418 | q.iRadix = r.iRadix = iRadix; | 430 | q.iRadix = r.iRadix = iRadix; |
@@ -433,22 +445,30 @@ void Number::divide( const Number &rhs, Number &q, Number &r ) const | |||
433 | for( int j = iAnchor-iNumShift; | 445 | for( int j = iAnchor-iNumShift; |
434 | nNum.aInt.getSize() < nDiv.aInt.getSize(); j++ ) | 446 | nNum.aInt.getSize() < nDiv.aInt.getSize(); j++ ) |
435 | { | 447 | { |
436 | // Bu::println(" ->[%1] '%2'").arg( j ).arg( digit(j) ); | 448 | DBS( DIVIDE, Bu::println(" ->[%1] '%2'").arg( j ).arg( digit(j) ) ); |
437 | nNum.aInt.append( digit( j ) ); | 449 | nNum.aInt.append( digit( j ) ); |
438 | } | 450 | } |
439 | // Bu::println("New numerator: %1").arg( nNum ); | 451 | DBS( DIVIDE, Bu::println("New numerator: %1").arg( nNum ) ); |
440 | while( iAnchor >= -iScale && (!nNum.isZero() || iAnchor > 0)) // division loop | 452 | while( iAnchor >= -iScale && (!nNum.isZero() || iAnchor > 0)) // division loop |
441 | { | 453 | { |
442 | // As long as the numerator is smaller than the divisor we keep | 454 | // As long as the numerator is smaller than the divisor we keep |
443 | // including new digits. | 455 | // including new digits. |
444 | while( nNum < nDiv ) | 456 | while( nNum.aInt.getSize() < nDiv.aInt.getSize() || |
457 | nNum < nDiv ) | ||
445 | { | 458 | { |
446 | iAnchor--; | 459 | iAnchor--; |
447 | nNum.aInt.insert( 0, digit(iAnchor-iNumShift) ); | 460 | int iDig = digit(iAnchor-iNumShift); |
448 | // Bu::println("Numerator too small, new numerator: %1").arg( nNum ); | 461 | if( nNum.aInt.getSize() == 0 && iDig == 0 ) |
462 | { | ||
463 | if( iAnchor < -iScale ) | ||
464 | break; | ||
465 | continue; | ||
466 | } | ||
467 | nNum.aInt.insert( 0, iDig ); | ||
468 | DBS( DIVIDE, Bu::println("Numerator too small, new numerator: %1").arg( nNum ) ); | ||
449 | } | 469 | } |
450 | 470 | ||
451 | // Bu::println(" New anchor: %1 vs iScale = %2").arg( iAnchor ).arg( iScale ); | 471 | DBS( DIVIDE, Bu::println(" New anchor: %1 vs iScale = %2").arg( iAnchor ).arg( iScale ) ); |
452 | if( iAnchor < 0 && -1-iAnchor >= iScale ) | 472 | if( iAnchor < 0 && -1-iAnchor >= iScale ) |
453 | break; | 473 | break; |
454 | 474 | ||
@@ -456,11 +476,11 @@ void Number::divide( const Number &rhs, Number &q, Number &r ) const | |||
456 | int iCount = 0; | 476 | int iCount = 0; |
457 | for(;nNum >= nDiv; iCount++ ) | 477 | for(;nNum >= nDiv; iCount++ ) |
458 | { | 478 | { |
459 | // Bu::print(" ==> step %3: %1 - %2 = ").arg( nNum ).arg( nDiv ).arg( iCount ); | 479 | DBS( DIVIDE, Bu::print(" ==> step %3: %1 - %2 = ").arg( nNum ).arg( nDiv ).arg( iCount ) ); |
460 | nNum = nNum - nDiv; | 480 | nNum = nNum - nDiv; |
461 | // Bu::println("%1").arg( nNum ); | 481 | DBS( DIVIDE, Bu::println("%1").arg( nNum ) ); |
462 | } | 482 | } |
463 | // Bu::println("Total steps: %1").arg( iCount ); | 483 | DBS( DIVIDE, Bu::println("Total steps: %1").arg( iCount ) ); |
464 | 484 | ||
465 | if( iAnchor >= 0 ) | 485 | if( iAnchor >= 0 ) |
466 | { | 486 | { |
@@ -481,15 +501,15 @@ void Number::divide( const Number &rhs, Number &q, Number &r ) const | |||
481 | r.aInt.append( nNum.aInt[j] ); | 501 | r.aInt.append( nNum.aInt[j] ); |
482 | int jtop = 0; | 502 | int jtop = 0; |
483 | for(; nNum.aInt[jtop] == 0; jtop++ ) { } | 503 | for(; nNum.aInt[jtop] == 0; jtop++ ) { } |
484 | // Bu::println("Computing remainder fraction from %1 to %2") | 504 | DBS( DIVIDE, Bu::println("Computing remainder fraction from %1 to %2") |
485 | // .arg( -iAnchor-1 ).arg( jtop ); | 505 | .arg( -iAnchor-1 ).arg( jtop ) ); |
486 | r.aFrac.clear(); | 506 | r.aFrac.clear(); |
487 | for( int j = -iAnchor-1, k = 0; j >= jtop && k < r.iScale; j--, k++ ) | 507 | for( int j = -iAnchor-1, k = 0; j >= jtop && k < r.iScale; j--, k++ ) |
488 | { | 508 | { |
489 | if( j < nNum.aInt.getSize() ) | 509 | if( j < nNum.aInt.getSize() ) |
490 | { | 510 | { |
491 | r.aFrac.set( k, nNum.aInt[j] ); | 511 | r.aFrac.set( k, nNum.aInt[j] ); |
492 | // Bu::println("setting %1 to %2").arg( k ).arg( nNum.aInt[j] ); | 512 | DBS( DIVIDE, Bu::println("setting %1 to %2").arg( k ).arg( nNum.aInt[j] ) ); |
493 | } | 513 | } |
494 | } | 514 | } |
495 | } | 515 | } |
@@ -497,9 +517,9 @@ void Number::divide( const Number &rhs, Number &q, Number &r ) const | |||
497 | // { | 517 | // { |
498 | // Bu::println("iAnchor: %1").arg( iAnchor ); | 518 | // Bu::println("iAnchor: %1").arg( iAnchor ); |
499 | // } | 519 | // } |
500 | // Bu::println("Quotient: %1").arg( q ); | 520 | DBS( DIVIDE, Bu::println("Quotient: %1").arg( q ) ); |
501 | // Bu::println("Final numerator? %1").arg( nNum ); | 521 | DBS( DIVIDE, Bu::println("Final numerator? %1").arg( nNum ) ); |
502 | // Bu::println("Remainder? %1").arg( r ); | 522 | DBS( DIVIDE, Bu::println("Remainder? %1").arg( r ) ); |
503 | 523 | ||
504 | } | 524 | } |
505 | 525 | ||