@@ -47,6 +47,7 @@ A `BigDigit` is half the size of machine word size.
4747pub type BigDigit = u32 ;
4848
4949pub static ZERO_BIG_DIGIT : BigDigit = 0 ;
50+ static ZERO_VEC : [ BigDigit , ..1 ] = [ ZERO_BIG_DIGIT ] ;
5051
5152pub mod BigDigit {
5253 use super :: BigDigit ;
@@ -140,37 +141,28 @@ impl Num for BigUint {}
140141
141142impl BitAnd < BigUint , BigUint > for BigUint {
142143 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 ( ) )
151145 }
152146}
153147
154148impl BitOr < BigUint , BigUint > for BigUint {
155149 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 ( ) ;
162155 return BigUint :: new ( ored) ;
163156 }
164157}
165158
166159impl BitXor < BigUint , BigUint > for BigUint {
167160 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 ( ) ;
174166 return BigUint :: new ( xored) ;
175167 }
176168}
@@ -210,18 +202,15 @@ impl Unsigned for BigUint {}
210202
211203impl Add < BigUint , BigUint > for BigUint {
212204 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 ) } ;
214207
215208 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 ) ) ;
222211 carry = hi;
223212 lo
224- } ) ;
213+ } ) . collect ( ) ;
225214 if carry != 0 { sum. push ( carry) ; }
226215 return BigUint :: new ( sum) ;
227216 }
@@ -230,22 +219,21 @@ impl Add<BigUint, BigUint> for BigUint {
230219impl Sub < BigUint , BigUint > for BigUint {
231220 fn sub ( & self , other : & BigUint ) -> BigUint {
232221 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) ) ;
233224
234225 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) | {
238227 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 )
241229 ) ;
242230 /*
243231 hi * (base) + lo == 1*(base) + ai - bi - borrow
244232 => ai - bi - borrow < 0 <=> hi == 0
245233 */
246234 borrow = if hi == 0 { 1 } else { 0 } ;
247235 lo
248- } ) ;
236+ } ) . collect ( ) ;
249237
250238 assert_eq ! ( borrow, 0 ) ; // <=> assert!((self >= other));
251239 return BigUint :: new ( diff) ;
@@ -451,17 +439,18 @@ impl Integer for BigUint {
451439 return ( Zero :: zero ( ) , Zero :: zero ( ) , ( * a) . clone ( ) ) ;
452440 }
453441
454- let an = a. data . slice ( a. data . len ( ) - n, a . data . len ( ) ) ;
442+ let an = a. data . tailn ( a. data . len ( ) - n) ;
455443 let bn = * b. data . last ( ) . unwrap ( ) ;
456- let mut d = ~ [ ] ;
444+ let mut d = vec :: with_capacity ( an . len ( ) ) ;
457445 let mut carry = 0 ;
458446 for elt in an. rev_iter ( ) {
459447 let ai = BigDigit :: to_uint ( carry, * elt) ;
460448 let di = ai / ( bn as uint ) ;
461449 assert ! ( di < BigDigit :: base) ;
462450 carry = ( ai % ( bn as uint ) ) as BigDigit ;
463- d = ~ [ di as BigDigit ] + d ;
451+ d. push ( di as BigDigit )
464452 }
453+ d. reverse ( ) ;
465454
466455 let shift = ( a. data . len ( ) - an. len ( ) ) - ( b. data . len ( ) - 1 ) ;
467456 if shift == 0 {
@@ -506,10 +495,9 @@ impl Integer for BigUint {
506495 #[ inline]
507496 fn is_even ( & self ) -> bool {
508497 // 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
513501 }
514502 }
515503
@@ -664,12 +652,12 @@ impl ToStrRadix for BigUint {
664652 if base == BigDigit :: base {
665653 return fill_concat ( self . data , radix, max_len)
666654 }
667- return fill_concat ( convert_base ( ( * self ) . clone ( ) , base) , radix, max_len) ;
655+ return fill_concat ( convert_base ( self , base) , radix, max_len) ;
668656
669- fn convert_base ( n : BigUint , base : uint ) -> ~[ BigDigit ] {
657+ fn convert_base ( n : & BigUint , base : uint ) -> ~[ BigDigit ] {
670658 let divider = FromPrimitive :: from_uint ( base) . unwrap ( ) ;
671659 let mut result = ~[ ] ;
672- let mut m = n;
660+ let mut m = n. clone ( ) ;
673661 while m >= divider {
674662 let ( d, m0) = m. div_mod_floor ( & divider) ;
675663 result. push ( m0. to_uint ( ) . unwrap ( ) as BigDigit ) ;
0 commit comments