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 | |
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 '')
-rw-r--r-- | src/main.cpp | 104 | ||||
-rw-r--r-- | src/number.cpp | 51 | ||||
-rw-r--r-- | src/number.h | 5 |
3 files changed, 141 insertions, 19 deletions
diff --git a/src/main.cpp b/src/main.cpp index d436a20..6674075 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
@@ -1,5 +1,7 @@ | |||
1 | #include "number.h" | 1 | #include "number.h" |
2 | #include "packedintarray.h" | 2 | #include "packedintarray.h" |
3 | #include <math.h> | ||
4 | #include <sys/time.h> | ||
3 | 5 | ||
4 | #include <bu/sio.h> | 6 | #include <bu/sio.h> |
5 | using namespace Bu; | 7 | using namespace Bu; |
@@ -177,6 +179,18 @@ void numbertest1() | |||
177 | arg( a.toString() ). | 179 | arg( a.toString() ). |
178 | arg( b.toString() ). | 180 | arg( b.toString() ). |
179 | arg( (a % b).toString() ); | 181 | arg( (a % b).toString() ); |
182 | |||
183 | a = "983429807324875233421784598754987439873472349875329853298732"; | ||
184 | b = "18446744073709551615"; | ||
185 | |||
186 | println("%1 / %2 = %3"). | ||
187 | arg( a.toString() ). | ||
188 | arg( b.toString() ). | ||
189 | arg( (a / b).toString() ); | ||
190 | println("%1 %% %2 = %3"). | ||
191 | arg( a.toString() ). | ||
192 | arg( b.toString() ). | ||
193 | arg( (a % b).toString() ); | ||
180 | } | 194 | } |
181 | 195 | ||
182 | #define compcheck( anum, op, bnum ) \ | 196 | #define compcheck( anum, op, bnum ) \ |
@@ -245,13 +259,101 @@ void numbertestcomp() | |||
245 | compcheck( 123, <=, -122 ); | 259 | compcheck( 123, <=, -122 ); |
246 | } | 260 | } |
247 | 261 | ||
262 | int getHob( int x ) | ||
263 | { | ||
264 | for( int j = 31; j >= 0; j-- ) | ||
265 | { | ||
266 | if( x&(1<<j) ) | ||
267 | { | ||
268 | return j+1; | ||
269 | } | ||
270 | } | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | int getOrd( int x ) | ||
275 | { | ||
276 | return (int)(log(x)*0xb.8aa3b295c17fp-3+1.0); | ||
277 | } | ||
278 | |||
279 | double getTime() | ||
280 | { | ||
281 | timeval t; | ||
282 | gettimeofday( &t, NULL ); | ||
283 | return (double)t.tv_sec + (double)(t.tv_usec*.000001); | ||
284 | } | ||
285 | |||
286 | void ordertest() | ||
287 | { | ||
288 | for( int j = 2; j < 64; j++ ) | ||
289 | { | ||
290 | if( getOrd( j ) != getHob(j-1) ) | ||
291 | println("Failure on radix %1").arg( j ); | ||
292 | } | ||
293 | |||
294 | double dStart, dEnd; | ||
295 | |||
296 | dStart = getTime(); | ||
297 | for( int k = 0; k < 100000; k++ ) | ||
298 | { | ||
299 | for( int j = 2; j < 32; j++ ) | ||
300 | { | ||
301 | getOrd( j ); | ||
302 | } | ||
303 | } | ||
304 | dEnd = getTime(); | ||
305 | |||
306 | println("getOrd: %1 in %2 (%3 cps)").arg( 30*100000 ).arg( dEnd-dStart ). | ||
307 | arg( (30*100000)/(dEnd-dStart) ); | ||
308 | |||
309 | dStart = getTime(); | ||
310 | for( int k = 0; k < 100000; k++ ) | ||
311 | { | ||
312 | for( int j = 2; j < 32; j++ ) | ||
313 | { | ||
314 | getHob( j-1 ); | ||
315 | } | ||
316 | } | ||
317 | dEnd = getTime(); | ||
318 | |||
319 | println("getHob: %1 in %2 (%3 cps)").arg( 30*100000 ).arg( dEnd-dStart ). | ||
320 | arg( (30*100000)/(dEnd-dStart) ); | ||
321 | } | ||
322 | |||
323 | void radixtest() | ||
324 | { | ||
325 | Number a( 16 ), b( 16 ); | ||
326 | |||
327 | a = "f8a72bce3"; | ||
328 | b = "9ea8cb3"; | ||
329 | println("%1 + %2 = %3"). | ||
330 | arg( a.toString() ). | ||
331 | arg( b.toString() ). | ||
332 | arg( (a + b).toString() ); | ||
333 | println("%1 - %2 = %3"). | ||
334 | arg( a.toString() ). | ||
335 | arg( b.toString() ). | ||
336 | arg( (a - b).toString() ); | ||
337 | println("%1 / %2 = %3"). | ||
338 | arg( a.toString() ). | ||
339 | arg( b.toString() ). | ||
340 | arg( (a / b).toString() ); | ||
341 | println("%1 * %2 = %3"). | ||
342 | arg( a.toString() ). | ||
343 | arg( b.toString() ). | ||
344 | arg( (a * b).toString() ); | ||
345 | } | ||
346 | |||
248 | int main( int , char *[] ) | 347 | int main( int , char *[] ) |
249 | { | 348 | { |
250 | println("CliC"); | 349 | println("CliC"); |
251 | 350 | ||
252 | // packedtest1(); | 351 | // packedtest1(); |
253 | numbertest1(); | 352 | // numbertest1(); |
254 | // numbertestcomp(); | 353 | // numbertestcomp(); |
354 | radixtest(); | ||
355 | |||
356 | // ordertest(); | ||
255 | 357 | ||
256 | return 0; | 358 | return 0; |
257 | } | 359 | } |
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); |
diff --git a/src/number.h b/src/number.h index ee000a8..8d98a1b 100644 --- a/src/number.h +++ b/src/number.h | |||
@@ -7,8 +7,8 @@ | |||
7 | class Number | 7 | class Number |
8 | { | 8 | { |
9 | public: | 9 | public: |
10 | Number( int iOrd=0 ); | 10 | Number( int iRadix=10, int iOrd=0 ); |
11 | Number( const Bu::String &sData, int iOrd=0 ); | 11 | Number( const Bu::String &sData, int iRadix=10, int iOrd=0 ); |
12 | virtual ~Number(); | 12 | virtual ~Number(); |
13 | 13 | ||
14 | Number &operator=( const Bu::String &sNum ); | 14 | Number &operator=( const Bu::String &sNum ); |
@@ -46,6 +46,7 @@ private: | |||
46 | Number add( const Number &rhs, bool bSub ) const; | 46 | Number add( const Number &rhs, bool bSub ) const; |
47 | 47 | ||
48 | private: | 48 | private: |
49 | int iRadix; | ||
49 | int iOrd; | 50 | int iOrd; |
50 | bool bPositive; | 51 | bool bPositive; |
51 | PackedIntArray aInt; | 52 | PackedIntArray aInt; |