diff options
author | Mike Buland <mike@xagasoft.com> | 2013-04-16 14:41:14 -0600 |
---|---|---|
committer | Mike Buland <mike@xagasoft.com> | 2013-04-16 14:41:14 -0600 |
commit | 7cfca326d8f824d3749ece6ad63a793197bf6c9d (patch) | |
tree | fcde2eb8a7e479e6e4cfb3c88cd4c7d5828b5aa6 /src/number.cpp | |
parent | 0e95be4d89b394315a969814a77e08ed358261d6 (diff) | |
download | clic-7cfca326d8f824d3749ece6ad63a793197bf6c9d.tar.gz clic-7cfca326d8f824d3749ece6ad63a793197bf6c9d.tar.bz2 clic-7cfca326d8f824d3749ece6ad63a793197bf6c9d.tar.xz clic-7cfca326d8f824d3749ece6ad63a793197bf6c9d.zip |
Full support for arbitrary radixes is in place.
It computes the radix and bitwidth dynamically, we could probably speed
that up another step by simply having a table of common ones, but for
now it'll work for anything.
Diffstat (limited to 'src/number.cpp')
-rw-r--r-- | src/number.cpp | 51 |
1 files changed, 35 insertions, 16 deletions
diff --git a/src/number.cpp b/src/number.cpp index b3a33dc..12a86e0 100644 --- a/src/number.cpp +++ b/src/number.cpp | |||
@@ -1,20 +1,23 @@ | |||
1 | #include "number.h" | 1 | #include "number.h" |
2 | 2 | ||
3 | #include <bu/sio.h> | 3 | #include <bu/sio.h> |
4 | #include <math.h> | ||
4 | 5 | ||
5 | #define iRadix (10) | 6 | #define RadixToBits( x ) ((int)(log((x))*0xb.8aa3b295c17fp-3+1.0)) |
6 | 7 | ||
7 | Number::Number( int iOrd ) : | 8 | Number::Number( int iRadix, int iOrd ) : |
9 | iRadix( iRadix ), | ||
8 | iOrd( iOrd ), | 10 | iOrd( iOrd ), |
9 | bPositive( true ), | 11 | bPositive( true ), |
10 | aInt( 4 ) | 12 | aInt( RadixToBits(iRadix) ) |
11 | { | 13 | { |
12 | } | 14 | } |
13 | 15 | ||
14 | Number::Number( const Bu::String &sData, int iOrd ) : | 16 | Number::Number( const Bu::String &sData, int iRadix, int iOrd ) : |
17 | iRadix( iRadix ), | ||
15 | iOrd( iOrd ), | 18 | iOrd( iOrd ), |
16 | bPositive( true ), | 19 | bPositive( true ), |
17 | aInt( 4 ) | 20 | aInt( RadixToBits( iRadix ) ) |
18 | { | 21 | { |
19 | set( sData ); | 22 | set( sData ); |
20 | } | 23 | } |
@@ -47,7 +50,7 @@ Number Number::operator-( const Number &rhs ) const | |||
47 | 50 | ||
48 | Number Number::operator*( const Number &rhs ) const | 51 | Number Number::operator*( const Number &rhs ) const |
49 | { | 52 | { |
50 | Number ret( iOrd ); | 53 | Number ret( iRadix, iOrd ); |
51 | 54 | ||
52 | int iCnt = aInt.getSize()+rhs.aInt.getSize(); | 55 | int iCnt = aInt.getSize()+rhs.aInt.getSize(); |
53 | 56 | ||
@@ -91,14 +94,14 @@ Number Number::operator*( const Number &rhs ) const | |||
91 | 94 | ||
92 | Number Number::operator/( const Number &rhs ) const | 95 | Number Number::operator/( const Number &rhs ) const |
93 | { | 96 | { |
94 | Number q( iOrd ), r( iOrd ); | 97 | Number q( iRadix, iOrd ), r( iRadix, iOrd ); |
95 | divide( rhs, q, r ); | 98 | divide( rhs, q, r ); |
96 | return q; | 99 | return q; |
97 | } | 100 | } |
98 | 101 | ||
99 | Number Number::operator%( const Number &rhs ) const | 102 | Number Number::operator%( const Number &rhs ) const |
100 | { | 103 | { |
101 | Number q( iOrd ), r( iOrd ); | 104 | Number q( iRadix, iOrd ), r( iRadix, iOrd ); |
102 | divide( rhs, q, r ); | 105 | divide( rhs, q, r ); |
103 | return r; | 106 | return r; |
104 | } | 107 | } |
@@ -244,7 +247,10 @@ void Number::set( const Bu::String &sNum ) | |||
244 | bPositive = false; | 247 | bPositive = false; |
245 | break; | 248 | break; |
246 | } | 249 | } |
247 | aInt.append( sNum[j]-'0' ); | 250 | if( sNum[j] >= '0' && sNum[j] <= '9' ) |
251 | aInt.append( sNum[j]-'0' ); | ||
252 | else | ||
253 | aInt.append( sNum[j]-'a'+10 ); | ||
248 | } | 254 | } |
249 | } | 255 | } |
250 | 256 | ||
@@ -259,7 +265,19 @@ Bu::String Number::toString() const | |||
259 | { | 265 | { |
260 | if( aInt.getSize() == 0 ) | 266 | if( aInt.getSize() == 0 ) |
261 | return "0"; | 267 | return "0"; |
262 | return (bPositive?"":"-") + aInt.toString(); | 268 | Bu::String sRet; |
269 | if( !bPositive ) | ||
270 | sRet += '-'; | ||
271 | for( int j = aInt.getSize()-1; j >= 0; j-- ) | ||
272 | { | ||
273 | int x = aInt.get( j ); | ||
274 | if( x >= 10 ) | ||
275 | sRet += x-10+'a'; | ||
276 | else | ||
277 | sRet += x+'0'; | ||
278 | } | ||
279 | |||
280 | return sRet; | ||
263 | } | 281 | } |
264 | 282 | ||
265 | int Number::digit( int iOrder ) const | 283 | int Number::digit( int iOrder ) const |
@@ -271,7 +289,7 @@ int Number::digit( int iOrder ) const | |||
271 | 289 | ||
272 | Number Number::add( const Number &rhs, bool bSub ) const | 290 | Number Number::add( const Number &rhs, bool bSub ) const |
273 | { | 291 | { |
274 | Number ret( iOrd ); | 292 | Number ret( iRadix, iOrd ); |
275 | 293 | ||
276 | int iPlaces = Bu::buMax(rhs.aInt.getSize(), aInt.getSize() ); | 294 | int iPlaces = Bu::buMax(rhs.aInt.getSize(), aInt.getSize() ); |
277 | 295 | ||
@@ -309,9 +327,10 @@ Number Number::add( const Number &rhs, bool bSub ) const | |||
309 | // Bu::println("--method b--"); | 327 | // Bu::println("--method b--"); |
310 | ret.bPositive = bPositive; | 328 | ret.bPositive = bPositive; |
311 | int iRes; | 329 | int iRes; |
330 | int iComp = (iRadix-1); | ||
312 | for( int j = 0; j < iPlaces; j++ ) | 331 | for( int j = 0; j < iPlaces; j++ ) |
313 | { | 332 | { |
314 | iRes = digit( j ) + (9-rhs.digit( j )) + iCarry; | 333 | iRes = digit( j ) + (iComp-rhs.digit( j )) + iCarry; |
315 | // Bu::println(" Place: %1 + %2 + (%3) = %4"). | 334 | // Bu::println(" Place: %1 + %2 + (%3) = %4"). |
316 | // arg( digit(j) ).arg( 9-rhs.digit( j ) ).arg( iCarry ) | 335 | // arg( digit(j) ).arg( 9-rhs.digit( j ) ).arg( iCarry ) |
317 | // .arg( iRes ); | 336 | // .arg( iRes ); |
@@ -332,10 +351,10 @@ Number Number::add( const Number &rhs, bool bSub ) const | |||
332 | if( iCarry == 0 ) | 351 | if( iCarry == 0 ) |
333 | { | 352 | { |
334 | ret.bPositive = false; | 353 | ret.bPositive = false; |
335 | ret.aInt.set( 0, 9-ret.aInt.get( 0 )+1); | 354 | ret.aInt.set( 0, iComp-ret.aInt.get( 0 )+1); |
336 | for( int j = 1; j < ret.aInt.getSize(); j++ ) | 355 | for( int j = 1; j < ret.aInt.getSize(); j++ ) |
337 | { | 356 | { |
338 | ret.aInt.set( j, 9-ret.aInt.get( j )); | 357 | ret.aInt.set( j, iComp-ret.aInt.get( j )); |
339 | } | 358 | } |
340 | } | 359 | } |
341 | else | 360 | else |
@@ -367,7 +386,7 @@ void Number::divide( const Number &rhs, Number &q, Number &r ) const | |||
367 | do | 386 | do |
368 | { | 387 | { |
369 | // Bu::println("%1\n-----").arg( r.aInt.toString() ); | 388 | // Bu::println("%1\n-----").arg( r.aInt.toString() ); |
370 | Number sub( iOrd ); | 389 | Number sub( iRadix, iOrd ); |
371 | for(;;) | 390 | for(;;) |
372 | { | 391 | { |
373 | // Bu::println(" -> Anchor: %1, Sample: %2").arg( iAnchor ).arg( iSample ); | 392 | // Bu::println(" -> Anchor: %1, Sample: %2").arg( iAnchor ).arg( iSample ); |
@@ -387,7 +406,7 @@ void Number::divide( const Number &rhs, Number &q, Number &r ) const | |||
387 | break; | 406 | break; |
388 | } | 407 | } |
389 | 408 | ||
390 | Number x( iOrd ); | 409 | Number x( iRadix, iOrd ); |
391 | int iRes = 0; | 410 | int iRes = 0; |
392 | for( ; x <= sub; iRes++, x = x + rhs ) { } | 411 | for( ; x <= sub; iRes++, x = x + rhs ) { } |
393 | x = sub - (x - rhs); | 412 | x = sub - (x - rhs); |