@@ -31,50 +31,43 @@ use std::{i64, u64};
31
31
32
32
/**
33
33
A `BigDigit` is a `BigUint`'s composing element.
34
-
35
- A `BigDigit` is half the size of machine word size.
36
34
*/
37
- #[ cfg( target_word_size = "32" ) ]
38
- pub type BigDigit = u16 ;
35
+ pub type BigDigit = u32 ;
39
36
40
37
/**
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`.
44
40
*/
45
- #[ cfg( target_word_size = "64" ) ]
46
- pub type BigDigit = u32 ;
41
+ pub type DoubleBigDigit = u64 ;
47
42
48
43
pub static ZERO_BIG_DIGIT : BigDigit = 0 ;
49
44
static ZERO_VEC : [ BigDigit , ..1 ] = [ ZERO_BIG_DIGIT ] ;
50
45
51
46
pub mod BigDigit {
52
47
use super :: BigDigit ;
48
+ use super :: DoubleBigDigit ;
53
49
54
- #[ cfg( target_word_size = "32" ) ]
55
- pub static bits: uint = 16 ;
56
-
57
- #[ cfg( target_word_size = "64" ) ]
50
+ // `DoubleBigDigit` size dependent
58
51
pub static bits: uint = 32 ;
59
52
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;
62
55
63
56
#[ inline]
64
- fn get_hi ( n : uint ) -> BigDigit { ( n >> bits) as BigDigit }
57
+ fn get_hi ( n : DoubleBigDigit ) -> BigDigit { ( n >> bits) as BigDigit }
65
58
#[ 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 }
67
60
68
- /// Split one machine sized unsigned integer into two `BigDigit`s.
61
+ /// Split one `DoubleBigDigit` into two `BigDigit`s.
69
62
#[ inline]
70
- pub fn from_uint ( n : uint ) -> ( BigDigit , BigDigit ) {
63
+ pub fn from_doublebigdigit ( n : DoubleBigDigit ) -> ( BigDigit , BigDigit ) {
71
64
( get_hi ( n) , get_lo ( n) )
72
65
}
73
66
74
- /// Join two `BigDigit`s into one machine sized unsigned integer
67
+ /// Join two `BigDigit`s into one `DoubleBigDigit`
75
68
#[ 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)
78
71
}
79
72
}
80
73
@@ -202,7 +195,8 @@ impl Add<BigUint, BigUint> for BigUint {
202
195
203
196
let mut carry = 0 ;
204
197
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 ) ) ;
206
200
carry = hi;
207
201
lo
208
202
} ) . collect ( ) ;
@@ -219,8 +213,11 @@ impl Sub<BigUint, BigUint> for BigUint {
219
213
220
214
let mut borrow = 0 ;
221
215
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 )
224
221
) ;
225
222
/*
226
223
hi * (base) + lo == 1*(base) + ai - bi - borrow
@@ -274,8 +271,8 @@ impl Mul<BigUint, BigUint> for BigUint {
274
271
275
272
let mut carry = 0 ;
276
273
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 )
279
276
) ;
280
277
carry = hi;
281
278
lo
@@ -440,10 +437,10 @@ impl Integer for BigUint {
440
437
let mut d = Vec :: with_capacity ( an. len ( ) ) ;
441
438
let mut carry = 0 ;
442
439
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 ) ;
445
442
assert ! ( di < BigDigit :: base) ;
446
- carry = ( ai % ( bn as uint ) ) as BigDigit ;
443
+ carry = ( ai % ( bn as DoubleBigDigit ) ) as BigDigit ;
447
444
d. push ( di as BigDigit )
448
445
}
449
446
d. reverse ( ) ;
@@ -515,39 +512,14 @@ impl ToPrimitive for BigUint {
515
512
} )
516
513
}
517
514
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
545
516
#[ inline]
546
517
fn to_u64 ( & self ) -> Option < u64 > {
547
518
match self . data . len ( ) {
548
519
0 => Some ( 0 ) ,
549
520
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 ) ,
551
523
_ => None
552
524
}
553
525
}
@@ -565,26 +537,10 @@ impl FromPrimitive for BigUint {
565
537
}
566
538
}
567
539
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
585
541
#[ inline]
586
542
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 ) {
588
544
( 0 , 0 ) => Zero :: zero ( ) ,
589
545
( 0 , n0) => BigUint :: new ( vec ! ( n0) ) ,
590
546
( n1, n0) => BigUint :: new ( vec ! ( n0, n1) )
@@ -650,8 +606,8 @@ impl ToStrRadix for BigUint {
650
606
}
651
607
return fill_concat ( convert_base ( self , base) . as_slice ( ) , radix, max_len) ;
652
608
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 ( ) ;
655
611
let mut result = Vec :: new ( ) ;
656
612
let mut m = n. clone ( ) ;
657
613
while m >= divider {
@@ -709,7 +665,7 @@ impl BigUint {
709
665
/// Creates and initializes a `BigUint`.
710
666
pub fn parse_bytes ( buf : & [ u8 ] , radix : uint ) -> Option < BigUint > {
711
667
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 ( ) {
713
669
Some ( base_num) => base_num,
714
670
None => { return None ; }
715
671
} ;
@@ -756,8 +712,8 @@ impl BigUint {
756
712
757
713
let mut carry = 0 ;
758
714
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 )
761
717
) ;
762
718
carry = hi;
763
719
lo
@@ -797,33 +753,9 @@ impl BigUint {
797
753
}
798
754
}
799
755
800
- # [ cfg ( target_word_size = "32" ) ]
756
+ // `DoubleBigDigit` size dependent
801
757
#[ 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 ) {
827
759
assert ! ( 1 < radix && radix <= 16 ) ;
828
760
match radix {
829
761
2 => ( 4294967296 , 32 ) ,
@@ -1599,36 +1531,7 @@ mod biguint_tests {
1599
1531
"88887777666655554444333322221111" ) ;
1600
1532
}
1601
1533
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
1632
1535
#[ test]
1633
1536
fn test_convert_i64 ( ) {
1634
1537
fn check ( b1 : BigUint , i : i64 ) {
@@ -1653,35 +1556,7 @@ mod biguint_tests {
1653
1556
assert_eq ! ( BigUint :: new( vec!( -1 , -1 , -1 ) ) . to_i64( ) , None ) ;
1654
1557
}
1655
1558
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
1685
1560
#[ test]
1686
1561
fn test_convert_u64 ( ) {
1687
1562
fn check ( b1 : BigUint , u : u64 ) {
0 commit comments