@@ -47,6 +47,7 @@ A `BigDigit` is half the size of machine word size.
47
47
pub type BigDigit = u32 ;
48
48
49
49
pub static ZERO_BIG_DIGIT : BigDigit = 0 ;
50
+ static ZERO_VEC : [ BigDigit , ..1 ] = [ ZERO_BIG_DIGIT ] ;
50
51
51
52
pub mod BigDigit {
52
53
use super :: BigDigit ;
@@ -140,37 +141,28 @@ impl Num for BigUint {}
140
141
141
142
impl BitAnd < BigUint , BigUint > for BigUint {
142
143
fn bitand ( & self , other : & BigUint ) -> BigUint {
143
- let new_len = cmp:: min ( self . data . len ( ) , other. data . len ( ) ) ;
144
- let anded = vec:: from_fn ( new_len, |i| {
145
- // i will never be less than the size of either data vector
146
- let ai = self . data [ i] ;
147
- let bi = other. data [ i] ;
148
- ai & bi
149
- } ) ;
150
- return BigUint :: new ( anded) ;
144
+ BigUint :: new ( self . data . iter ( ) . zip ( other. data . iter ( ) ) . map ( |( ai, bi) | * ai & * bi) . collect ( ) )
151
145
}
152
146
}
153
147
154
148
impl BitOr < BigUint , BigUint > for BigUint {
155
149
fn bitor ( & self , other : & BigUint ) -> BigUint {
156
- let new_len = cmp:: max ( self . data . len ( ) , other. data . len ( ) ) ;
157
- let ored = vec:: from_fn ( new_len, |i| {
158
- let ai = if i < self . data . len ( ) { self . data [ i] } else { 0 } ;
159
- let bi = if i < other. data . len ( ) { other. data [ i] } else { 0 } ;
160
- ai | bi
161
- } ) ;
150
+ let zeros = ZERO_VEC . iter ( ) . cycle ( ) ;
151
+ let ( a, b) = if self . data . len ( ) > other. data . len ( ) { ( self , other) } else { ( other, self ) } ;
152
+ let ored = a. data . iter ( ) . zip ( b. data . iter ( ) . chain ( zeros) ) . map (
153
+ |( ai, bi) | * ai | * bi
154
+ ) . collect ( ) ;
162
155
return BigUint :: new ( ored) ;
163
156
}
164
157
}
165
158
166
159
impl BitXor < BigUint , BigUint > for BigUint {
167
160
fn bitxor ( & self , other : & BigUint ) -> BigUint {
168
- let new_len = cmp:: max ( self . data . len ( ) , other. data . len ( ) ) ;
169
- let xored = vec:: from_fn ( new_len, |i| {
170
- let ai = if i < self . data . len ( ) { self . data [ i] } else { 0 } ;
171
- let bi = if i < other. data . len ( ) { other. data [ i] } else { 0 } ;
172
- ai ^ bi
173
- } ) ;
161
+ let zeros = ZERO_VEC . iter ( ) . cycle ( ) ;
162
+ let ( a, b) = if self . data . len ( ) > other. data . len ( ) { ( self , other) } else { ( other, self ) } ;
163
+ let xored = a. data . iter ( ) . zip ( b. data . iter ( ) . chain ( zeros) ) . map (
164
+ |( ai, bi) | * ai ^ * bi
165
+ ) . collect ( ) ;
174
166
return BigUint :: new ( xored) ;
175
167
}
176
168
}
@@ -210,18 +202,15 @@ impl Unsigned for BigUint {}
210
202
211
203
impl Add < BigUint , BigUint > for BigUint {
212
204
fn add ( & self , other : & BigUint ) -> BigUint {
213
- let new_len = cmp:: max ( self . data . len ( ) , other. data . len ( ) ) ;
205
+ let zeros = ZERO_VEC . iter ( ) . cycle ( ) ;
206
+ let ( a, b) = if self . data . len ( ) > other. data . len ( ) { ( self , other) } else { ( other, self ) } ;
214
207
215
208
let mut carry = 0 ;
216
- let mut sum = vec:: from_fn ( new_len, |i| {
217
- let ai = if i < self . data . len ( ) { self . data [ i] } else { 0 } ;
218
- let bi = if i < other. data . len ( ) { other. data [ i] } else { 0 } ;
219
- let ( hi, lo) = BigDigit :: from_uint (
220
- ( ai as uint ) + ( bi as uint ) + ( carry as uint )
221
- ) ;
209
+ let mut sum: ~[ BigDigit ] = a. data . iter ( ) . zip ( b. data . iter ( ) . chain ( zeros) ) . map ( |( ai, bi) | {
210
+ let ( hi, lo) = BigDigit :: from_uint ( ( * ai as uint ) + ( * bi as uint ) + ( carry as uint ) ) ;
222
211
carry = hi;
223
212
lo
224
- } ) ;
213
+ } ) . collect ( ) ;
225
214
if carry != 0 { sum. push ( carry) ; }
226
215
return BigUint :: new ( sum) ;
227
216
}
@@ -230,22 +219,21 @@ impl Add<BigUint, BigUint> for BigUint {
230
219
impl Sub < BigUint , BigUint > for BigUint {
231
220
fn sub ( & self , other : & BigUint ) -> BigUint {
232
221
let new_len = cmp:: max ( self . data . len ( ) , other. data . len ( ) ) ;
222
+ let zeros = ZERO_VEC . iter ( ) . cycle ( ) ;
223
+ let ( a, b) = ( self . data . iter ( ) . chain ( zeros. clone ( ) ) , other. data . iter ( ) . chain ( zeros) ) ;
233
224
234
225
let mut borrow = 0 ;
235
- let diff = vec:: from_fn ( new_len, |i| {
236
- let ai = if i < self . data . len ( ) { self . data [ i] } else { 0 } ;
237
- let bi = if i < other. data . len ( ) { other. data [ i] } else { 0 } ;
226
+ let diff: ~[ BigDigit ] = a. take ( new_len) . zip ( b) . map ( |( ai, bi) | {
238
227
let ( hi, lo) = BigDigit :: from_uint (
239
- ( BigDigit :: base) +
240
- ( ai as uint ) - ( bi as uint ) - ( borrow as uint )
228
+ BigDigit :: base + ( * ai as uint ) - ( * bi as uint ) - ( borrow as uint )
241
229
) ;
242
230
/*
243
231
hi * (base) + lo == 1*(base) + ai - bi - borrow
244
232
=> ai - bi - borrow < 0 <=> hi == 0
245
233
*/
246
234
borrow = if hi == 0 { 1 } else { 0 } ;
247
235
lo
248
- } ) ;
236
+ } ) . collect ( ) ;
249
237
250
238
assert_eq ! ( borrow, 0 ) ; // <=> assert!((self >= other));
251
239
return BigUint :: new ( diff) ;
@@ -451,17 +439,18 @@ impl Integer for BigUint {
451
439
return ( Zero :: zero ( ) , Zero :: zero ( ) , ( * a) . clone ( ) ) ;
452
440
}
453
441
454
- let an = a. data . slice ( a. data . len ( ) - n, a . data . len ( ) ) ;
442
+ let an = a. data . tailn ( a. data . len ( ) - n) ;
455
443
let bn = * b. data . last ( ) . unwrap ( ) ;
456
- let mut d = ~ [ ] ;
444
+ let mut d = vec :: with_capacity ( an . len ( ) ) ;
457
445
let mut carry = 0 ;
458
446
for elt in an. rev_iter ( ) {
459
447
let ai = BigDigit :: to_uint ( carry, * elt) ;
460
448
let di = ai / ( bn as uint ) ;
461
449
assert ! ( di < BigDigit :: base) ;
462
450
carry = ( ai % ( bn as uint ) ) as BigDigit ;
463
- d = ~ [ di as BigDigit ] + d ;
451
+ d. push ( di as BigDigit )
464
452
}
453
+ d. reverse ( ) ;
465
454
466
455
let shift = ( a. data . len ( ) - an. len ( ) ) - ( b. data . len ( ) - 1 ) ;
467
456
if shift == 0 {
@@ -506,10 +495,9 @@ impl Integer for BigUint {
506
495
#[ inline]
507
496
fn is_even ( & self ) -> bool {
508
497
// Considering only the last digit.
509
- if self . data . is_empty ( ) {
510
- true
511
- } else {
512
- self . data [ 0 ] . is_even ( )
498
+ match self . data . head ( ) {
499
+ Some ( x) => x. is_even ( ) ,
500
+ None => true
513
501
}
514
502
}
515
503
@@ -664,12 +652,12 @@ impl ToStrRadix for BigUint {
664
652
if base == BigDigit :: base {
665
653
return fill_concat ( self . data , radix, max_len)
666
654
}
667
- return fill_concat ( convert_base ( ( * self ) . clone ( ) , base) , radix, max_len) ;
655
+ return fill_concat ( convert_base ( self , base) , radix, max_len) ;
668
656
669
- fn convert_base ( n : BigUint , base : uint ) -> ~[ BigDigit ] {
657
+ fn convert_base ( n : & BigUint , base : uint ) -> ~[ BigDigit ] {
670
658
let divider = FromPrimitive :: from_uint ( base) . unwrap ( ) ;
671
659
let mut result = ~[ ] ;
672
- let mut m = n;
660
+ let mut m = n. clone ( ) ;
673
661
while m >= divider {
674
662
let ( d, m0) = m. div_mod_floor ( & divider) ;
675
663
result. push ( m0. to_uint ( ) . unwrap ( ) as BigDigit ) ;
0 commit comments