@@ -31,50 +31,43 @@ use std::{i64, u64};
3131
3232/**
3333A `BigDigit` is a `BigUint`'s composing element.
34-
35- A `BigDigit` is half the size of machine word size.
3634*/
37- #[ cfg( target_word_size = "32" ) ]
38- pub type BigDigit = u16 ;
35+ pub type BigDigit = u32 ;
3936
4037/**
41- A `BigDigit` is a `BigUint`'s composing element.
42-
43- A `BigDigit` is half the size of machine word size.
38+ A `DoubleBigDigit` is the internal type used to do the computations. Its
39+ size is the double of the size of `BigDigit`.
4440*/
45- #[ cfg( target_word_size = "64" ) ]
46- pub type BigDigit = u32 ;
41+ pub type DoubleBigDigit = u64 ;
4742
4843pub static ZERO_BIG_DIGIT : BigDigit = 0 ;
4944static ZERO_VEC : [ BigDigit , ..1 ] = [ ZERO_BIG_DIGIT ] ;
5045
5146pub mod BigDigit {
5247 use super :: BigDigit ;
48+ use super :: DoubleBigDigit ;
5349
54- #[ cfg( target_word_size = "32" ) ]
55- pub static bits: uint = 16 ;
56-
57- #[ cfg( target_word_size = "64" ) ]
50+ // `DoubleBigDigit` size dependent
5851 pub static bits: uint = 32 ;
5952
60- pub static base: uint = 1 << bits;
61- static lo_mask: uint = ( -1 as uint ) >> bits;
53+ pub static base: DoubleBigDigit = 1 << bits;
54+ static lo_mask: DoubleBigDigit = ( -1 as DoubleBigDigit ) >> bits;
6255
6356 #[ inline]
64- fn get_hi ( n : uint ) -> BigDigit { ( n >> bits) as BigDigit }
57+ fn get_hi ( n : DoubleBigDigit ) -> BigDigit { ( n >> bits) as BigDigit }
6558 #[ inline]
66- fn get_lo ( n : uint ) -> BigDigit { ( n & lo_mask) as BigDigit }
59+ fn get_lo ( n : DoubleBigDigit ) -> BigDigit { ( n & lo_mask) as BigDigit }
6760
68- /// Split one machine sized unsigned integer into two `BigDigit`s.
61+ /// Split one `DoubleBigDigit` into two `BigDigit`s.
6962 #[ inline]
70- pub fn from_uint ( n : uint ) -> ( BigDigit , BigDigit ) {
63+ pub fn from_doublebigdigit ( n : DoubleBigDigit ) -> ( BigDigit , BigDigit ) {
7164 ( get_hi ( n) , get_lo ( n) )
7265 }
7366
74- /// Join two `BigDigit`s into one machine sized unsigned integer
67+ /// Join two `BigDigit`s into one `DoubleBigDigit`
7568 #[ inline]
76- pub fn to_uint ( hi : BigDigit , lo : BigDigit ) -> uint {
77- ( lo as uint ) | ( ( hi as uint ) << bits)
69+ pub fn to_doublebigdigit ( hi : BigDigit , lo : BigDigit ) -> DoubleBigDigit {
70+ ( lo as DoubleBigDigit ) | ( ( hi as DoubleBigDigit ) << bits)
7871 }
7972}
8073
@@ -202,7 +195,8 @@ impl Add<BigUint, BigUint> for BigUint {
202195
203196 let mut carry = 0 ;
204197 let mut sum: Vec < BigDigit > = a. data . iter ( ) . zip ( b. data . iter ( ) . chain ( zeros) ) . map ( |( ai, bi) | {
205- let ( hi, lo) = BigDigit :: from_uint ( ( * ai as uint ) + ( * bi as uint ) + ( carry as uint ) ) ;
198+ let ( hi, lo) = BigDigit :: from_doublebigdigit (
199+ ( * ai as DoubleBigDigit ) + ( * bi as DoubleBigDigit ) + ( carry as DoubleBigDigit ) ) ;
206200 carry = hi;
207201 lo
208202 } ) . collect ( ) ;
@@ -219,8 +213,11 @@ impl Sub<BigUint, BigUint> for BigUint {
219213
220214 let mut borrow = 0 ;
221215 let diff: Vec < BigDigit > = a. take ( new_len) . zip ( b) . map ( |( ai, bi) | {
222- let ( hi, lo) = BigDigit :: from_uint (
223- BigDigit :: base + ( * ai as uint ) - ( * bi as uint ) - ( borrow as uint )
216+ let ( hi, lo) = BigDigit :: from_doublebigdigit (
217+ BigDigit :: base
218+ + ( * ai as DoubleBigDigit )
219+ - ( * bi as DoubleBigDigit )
220+ - ( borrow as DoubleBigDigit )
224221 ) ;
225222 /*
226223 hi * (base) + lo == 1*(base) + ai - bi - borrow
@@ -274,8 +271,8 @@ impl Mul<BigUint, BigUint> for BigUint {
274271
275272 let mut carry = 0 ;
276273 let mut prod: Vec < BigDigit > = a. data . iter ( ) . map ( |ai| {
277- let ( hi, lo) = BigDigit :: from_uint (
278- ( * ai as uint ) * ( n as uint ) + ( carry as uint )
274+ let ( hi, lo) = BigDigit :: from_doublebigdigit (
275+ ( * ai as DoubleBigDigit ) * ( n as DoubleBigDigit ) + ( carry as DoubleBigDigit )
279276 ) ;
280277 carry = hi;
281278 lo
@@ -440,10 +437,10 @@ impl Integer for BigUint {
440437 let mut d = Vec :: with_capacity ( an. len ( ) ) ;
441438 let mut carry = 0 ;
442439 for elt in an. iter ( ) . rev ( ) {
443- let ai = BigDigit :: to_uint ( carry, * elt) ;
444- let di = ai / ( bn as uint ) ;
440+ let ai = BigDigit :: to_doublebigdigit ( carry, * elt) ;
441+ let di = ai / ( bn as DoubleBigDigit ) ;
445442 assert ! ( di < BigDigit :: base) ;
446- carry = ( ai % ( bn as uint ) ) as BigDigit ;
443+ carry = ( ai % ( bn as DoubleBigDigit ) ) as BigDigit ;
447444 d. push ( di as BigDigit )
448445 }
449446 d. reverse ( ) ;
@@ -515,39 +512,14 @@ impl ToPrimitive for BigUint {
515512 } )
516513 }
517514
518- #[ cfg( target_word_size = "32" ) ]
519- #[ inline]
520- fn to_u64 ( & self ) -> Option < u64 > {
521- match self . data . len ( ) {
522- 0 => Some ( 0 ) ,
523- 1 => Some ( self . data . as_slice ( ) [ 0 ] as u64 ) ,
524- 2 => {
525- Some ( BigDigit :: to_uint ( self . data . as_slice ( ) [ 1 ] , self . data . as_slice ( ) [ 0 ] ) as u64 )
526- }
527- 3 => {
528- let n_lo = BigDigit :: to_uint ( self . data . as_slice ( ) [ 1 ] , self . data . as_slice ( ) [ 0 ] ) as
529- u64 ;
530- let n_hi = self . data . as_slice ( ) [ 2 ] as u64 ;
531- Some ( ( n_hi << 32 ) + n_lo)
532- }
533- 4 => {
534- let n_lo = BigDigit :: to_uint ( self . data . as_slice ( ) [ 1 ] , self . data . as_slice ( ) [ 0 ] )
535- as u64 ;
536- let n_hi = BigDigit :: to_uint ( self . data . as_slice ( ) [ 3 ] , self . data . as_slice ( ) [ 2 ] )
537- as u64 ;
538- Some ( ( n_hi << 32 ) + n_lo)
539- }
540- _ => None
541- }
542- }
543-
544- #[ cfg( target_word_size = "64" ) ]
515+ // `DoubleBigDigit` size dependent
545516 #[ inline]
546517 fn to_u64 ( & self ) -> Option < u64 > {
547518 match self . data . len ( ) {
548519 0 => Some ( 0 ) ,
549520 1 => Some ( self . data . as_slice ( ) [ 0 ] as u64 ) ,
550- 2 => Some ( BigDigit :: to_uint ( self . data . as_slice ( ) [ 1 ] , self . data . as_slice ( ) [ 0 ] ) as u64 ) ,
521+ 2 => Some ( BigDigit :: to_doublebigdigit ( self . data . as_slice ( ) [ 1 ] , self . data . as_slice ( ) [ 0 ] )
522+ as u64 ) ,
551523 _ => None
552524 }
553525 }
@@ -565,26 +537,10 @@ impl FromPrimitive for BigUint {
565537 }
566538 }
567539
568- #[ cfg( target_word_size = "32" ) ]
569- #[ inline]
570- fn from_u64 ( n : u64 ) -> Option < BigUint > {
571- let n_lo = ( n & 0x0000_0000_FFFF_FFFF ) as uint ;
572- let n_hi = ( n >> 32 ) as uint ;
573-
574- let n = match ( BigDigit :: from_uint ( n_hi) , BigDigit :: from_uint ( n_lo) ) {
575- ( ( 0 , 0 ) , ( 0 , 0 ) ) => Zero :: zero ( ) ,
576- ( ( 0 , 0 ) , ( 0 , n0) ) => BigUint :: new ( vec ! ( n0) ) ,
577- ( ( 0 , 0 ) , ( n1, n0) ) => BigUint :: new ( vec ! ( n0, n1) ) ,
578- ( ( 0 , n2) , ( n1, n0) ) => BigUint :: new ( vec ! ( n0, n1, n2) ) ,
579- ( ( n3, n2) , ( n1, n0) ) => BigUint :: new ( vec ! ( n0, n1, n2, n3) ) ,
580- } ;
581- Some ( n)
582- }
583-
584- #[ cfg( target_word_size = "64" ) ]
540+ // `DoubleBigDigit` size dependent
585541 #[ inline]
586542 fn from_u64 ( n : u64 ) -> Option < BigUint > {
587- let n = match BigDigit :: from_uint ( n as uint ) {
543+ let n = match BigDigit :: from_doublebigdigit ( n ) {
588544 ( 0 , 0 ) => Zero :: zero ( ) ,
589545 ( 0 , n0) => BigUint :: new ( vec ! ( n0) ) ,
590546 ( n1, n0) => BigUint :: new ( vec ! ( n0, n1) )
@@ -650,8 +606,8 @@ impl ToStrRadix for BigUint {
650606 }
651607 return fill_concat ( convert_base ( self , base) . as_slice ( ) , radix, max_len) ;
652608
653- fn convert_base ( n : & BigUint , base : uint ) -> Vec < BigDigit > {
654- let divider = FromPrimitive :: from_uint ( base) . unwrap ( ) ;
609+ fn convert_base ( n : & BigUint , base : DoubleBigDigit ) -> Vec < BigDigit > {
610+ let divider = base. to_biguint ( ) . unwrap ( ) ;
655611 let mut result = Vec :: new ( ) ;
656612 let mut m = n. clone ( ) ;
657613 while m >= divider {
@@ -709,7 +665,7 @@ impl BigUint {
709665 /// Creates and initializes a `BigUint`.
710666 pub fn parse_bytes ( buf : & [ u8 ] , radix : uint ) -> Option < BigUint > {
711667 let ( base, unit_len) = get_radix_base ( radix) ;
712- let base_num = match FromPrimitive :: from_uint ( base) {
668+ let base_num = match base. to_biguint ( ) {
713669 Some ( base_num) => base_num,
714670 None => { return None ; }
715671 } ;
@@ -756,8 +712,8 @@ impl BigUint {
756712
757713 let mut carry = 0 ;
758714 let mut shifted: Vec < BigDigit > = self . data . iter ( ) . map ( |elem| {
759- let ( hi, lo) = BigDigit :: from_uint (
760- ( * elem as uint ) << n_bits | ( carry as uint )
715+ let ( hi, lo) = BigDigit :: from_doublebigdigit (
716+ ( * elem as DoubleBigDigit ) << n_bits | ( carry as DoubleBigDigit )
761717 ) ;
762718 carry = hi;
763719 lo
@@ -797,33 +753,9 @@ impl BigUint {
797753 }
798754}
799755
800- # [ cfg ( target_word_size = "32" ) ]
756+ // `DoubleBigDigit` size dependent
801757#[ inline]
802- fn get_radix_base ( radix : uint ) -> ( uint , uint ) {
803- assert ! ( 1 < radix && radix <= 16 ) ;
804- match radix {
805- 2 => ( 65536 , 16 ) ,
806- 3 => ( 59049 , 10 ) ,
807- 4 => ( 65536 , 8 ) ,
808- 5 => ( 15625 , 6 ) ,
809- 6 => ( 46656 , 6 ) ,
810- 7 => ( 16807 , 5 ) ,
811- 8 => ( 32768 , 5 ) ,
812- 9 => ( 59049 , 5 ) ,
813- 10 => ( 10000 , 4 ) ,
814- 11 => ( 14641 , 4 ) ,
815- 12 => ( 20736 , 4 ) ,
816- 13 => ( 28561 , 4 ) ,
817- 14 => ( 38416 , 4 ) ,
818- 15 => ( 50625 , 4 ) ,
819- 16 => ( 65536 , 4 ) ,
820- _ => fail ! ( )
821- }
822- }
823-
824- #[ cfg( target_word_size = "64" ) ]
825- #[ inline]
826- fn get_radix_base ( radix : uint ) -> ( uint , uint ) {
758+ fn get_radix_base ( radix : uint ) -> ( DoubleBigDigit , uint ) {
827759 assert ! ( 1 < radix && radix <= 16 ) ;
828760 match radix {
829761 2 => ( 4294967296 , 32 ) ,
@@ -1599,36 +1531,7 @@ mod biguint_tests {
15991531 "88887777666655554444333322221111" ) ;
16001532 }
16011533
1602- #[ cfg( target_word_size = "32" ) ]
1603- #[ test]
1604- fn test_convert_i64 ( ) {
1605- fn check ( b1 : BigUint , i : i64 ) {
1606- let b2: BigUint = FromPrimitive :: from_i64 ( i) . unwrap ( ) ;
1607- assert ! ( b1 == b2) ;
1608- assert ! ( b1. to_i64( ) . unwrap( ) == i) ;
1609- }
1610-
1611- check ( Zero :: zero ( ) , 0 ) ;
1612- check ( One :: one ( ) , 1 ) ;
1613- check ( i64:: MAX . to_biguint ( ) . unwrap ( ) , i64:: MAX ) ;
1614-
1615- check ( BigUint :: new ( vec ! ( ) ) , 0 ) ;
1616- check ( BigUint :: new ( vec ! ( 1 ) ) , ( 1 << ( 0 * BigDigit :: bits) ) ) ;
1617- check ( BigUint :: new ( vec ! ( -1 ) ) , ( 1 << ( 1 * BigDigit :: bits) ) - 1 ) ;
1618- check ( BigUint :: new ( vec ! ( 0 , 1 ) ) , ( 1 << ( 1 * BigDigit :: bits) ) ) ;
1619- check ( BigUint :: new ( vec ! ( -1 , -1 ) ) , ( 1 << ( 2 * BigDigit :: bits) ) - 1 ) ;
1620- check ( BigUint :: new ( vec ! ( 0 , 0 , 1 ) ) , ( 1 << ( 2 * BigDigit :: bits) ) ) ;
1621- check ( BigUint :: new ( vec ! ( -1 , -1 , -1 ) ) , ( 1 << ( 3 * BigDigit :: bits) ) - 1 ) ;
1622- check ( BigUint :: new ( vec ! ( 0 , 0 , 0 , 1 ) ) , ( 1 << ( 3 * BigDigit :: bits) ) ) ;
1623- check ( BigUint :: new ( vec ! ( -1 , -1 , -1 , -1 >> 1 ) ) , i64:: MAX ) ;
1624-
1625- assert_eq ! ( i64 :: MIN . to_biguint( ) , None ) ;
1626- assert_eq ! ( BigUint :: new( vec!( -1 , -1 , -1 , -1 ) ) . to_i64( ) , None ) ;
1627- assert_eq ! ( BigUint :: new( vec!( 0 , 0 , 0 , 0 , 1 ) ) . to_i64( ) , None ) ;
1628- assert_eq ! ( BigUint :: new( vec!( -1 , -1 , -1 , -1 , -1 ) ) . to_i64( ) , None ) ;
1629- }
1630-
1631- #[ cfg( target_word_size = "64" ) ]
1534+ // `DoubleBigDigit` size dependent
16321535 #[ test]
16331536 fn test_convert_i64 ( ) {
16341537 fn check ( b1 : BigUint , i : i64 ) {
@@ -1653,35 +1556,7 @@ mod biguint_tests {
16531556 assert_eq ! ( BigUint :: new( vec!( -1 , -1 , -1 ) ) . to_i64( ) , None ) ;
16541557 }
16551558
1656- #[ cfg( target_word_size = "32" ) ]
1657- #[ test]
1658- fn test_convert_u64 ( ) {
1659- fn check ( b1 : BigUint , u : u64 ) {
1660- let b2: BigUint = FromPrimitive :: from_u64 ( u) . unwrap ( ) ;
1661- assert ! ( b1 == b2) ;
1662- assert ! ( b1. to_u64( ) . unwrap( ) == u) ;
1663- }
1664-
1665- check ( Zero :: zero ( ) , 0 ) ;
1666- check ( One :: one ( ) , 1 ) ;
1667- check ( u64:: MIN . to_biguint ( ) . unwrap ( ) , u64:: MIN ) ;
1668- check ( u64:: MAX . to_biguint ( ) . unwrap ( ) , u64:: MAX ) ;
1669-
1670- check ( BigUint :: new ( vec ! ( ) ) , 0 ) ;
1671- check ( BigUint :: new ( vec ! ( 1 ) ) , ( 1 << ( 0 * BigDigit :: bits) ) ) ;
1672- check ( BigUint :: new ( vec ! ( -1 ) ) , ( 1 << ( 1 * BigDigit :: bits) ) - 1 ) ;
1673- check ( BigUint :: new ( vec ! ( 0 , 1 ) ) , ( 1 << ( 1 * BigDigit :: bits) ) ) ;
1674- check ( BigUint :: new ( vec ! ( -1 , -1 ) ) , ( 1 << ( 2 * BigDigit :: bits) ) - 1 ) ;
1675- check ( BigUint :: new ( vec ! ( 0 , 0 , 1 ) ) , ( 1 << ( 2 * BigDigit :: bits) ) ) ;
1676- check ( BigUint :: new ( vec ! ( -1 , -1 , -1 ) ) , ( 1 << ( 3 * BigDigit :: bits) ) - 1 ) ;
1677- check ( BigUint :: new ( vec ! ( 0 , 0 , 0 , 1 ) ) , ( 1 << ( 3 * BigDigit :: bits) ) ) ;
1678- check ( BigUint :: new ( vec ! ( -1 , -1 , -1 , -1 ) ) , u64:: MAX ) ;
1679-
1680- assert_eq ! ( BigUint :: new( vec!( 0 , 0 , 0 , 0 , 1 ) ) . to_u64( ) , None ) ;
1681- assert_eq ! ( BigUint :: new( vec!( -1 , -1 , -1 , -1 , -1 ) ) . to_u64( ) , None ) ;
1682- }
1683-
1684- #[ cfg( target_word_size = "64" ) ]
1559+ // `DoubleBigDigit` size dependent
16851560 #[ test]
16861561 fn test_convert_u64 ( ) {
16871562 fn check ( b1 : BigUint , u : u64 ) {
0 commit comments