13
13
//! This is designed to avoid the heap allocation at expense of stack memory.
14
14
//! The most used bignum type, `Big32x40`, is limited by 32 × 40 = 1,280 bits
15
15
//! and will take at most 160 bytes of stack memory. This is more than enough
16
- //! for formatting and parsing all possible finite `f64` values.
16
+ //! for round-tripping all possible finite `f64` values.
17
17
//!
18
18
//! In principle it is possible to have multiple bignum types for different
19
19
//! inputs, but we don't do so to avoid the code bloat. Each bignum is still
@@ -92,6 +92,14 @@ impl_full_ops! {
92
92
// u64: add(intrinsics::u64_add_with_overflow), mul/div(u128); // see RFC #521 for enabling this.
93
93
}
94
94
95
+ /// Table of powers of 5 representable in digits. Specifically, the largest {u8, u16, u32} value
96
+ /// that's a power of five, plus the corresponding exponent. Used in `mul_pow5`.
97
+ const SMALL_POW5 : [ ( u64 , usize ) ; 3 ] = [
98
+ ( 125 , 3 ) ,
99
+ ( 15625 , 6 ) ,
100
+ ( 1_220_703_125 , 13 ) ,
101
+ ] ;
102
+
95
103
macro_rules! define_bignum {
96
104
( $name: ident: type =$ty: ty, n=$n: expr) => (
97
105
/// Stack-allocated arbitrary-precision (up to certain limit) integer.
@@ -135,9 +143,53 @@ macro_rules! define_bignum {
135
143
$name { size: sz, base: base }
136
144
}
137
145
146
+ /// Return the internal digits as a slice `[a, b, c, ...]` such that the numeric
147
+ /// value is `a + b * 2^W + c * 2^(2W) + ...` where `W` is the number of bits in
148
+ /// the digit type.
149
+ pub fn digits( & self ) -> & [ $ty] {
150
+ & self . base[ ..self . size]
151
+ }
152
+
153
+ /// Return the `i`-th bit where bit 0 is the least significant one.
154
+ /// In other words, the bit with weight `2^i`.
155
+ pub fn get_bit( & self , i: usize ) -> u8 {
156
+ use mem;
157
+
158
+ let digitbits = mem:: size_of:: <$ty>( ) * 8 ;
159
+ let d = i / digitbits;
160
+ let b = i % digitbits;
161
+ ( ( self . base[ d] >> b) & 1 ) as u8
162
+ }
163
+
138
164
/// Returns true if the bignum is zero.
139
165
pub fn is_zero( & self ) -> bool {
140
- self . base[ ..self . size] . iter( ) . all( |& v| v == 0 )
166
+ self . digits( ) . iter( ) . all( |& v| v == 0 )
167
+ }
168
+
169
+ /// Returns the number of bits necessary to represent this value. Note that zero
170
+ /// is considered to need 0 bits.
171
+ pub fn bit_length( & self ) -> usize {
172
+ use mem;
173
+
174
+ let digitbits = mem:: size_of:: <$ty>( ) * 8 ;
175
+ // Skip over the most significant digits which are zero.
176
+ let nonzero = match self . digits( ) . iter( ) . rposition( |& x| x != 0 ) {
177
+ Some ( n) => {
178
+ let end = self . size - n;
179
+ & self . digits( ) [ ..end]
180
+ }
181
+ None => {
182
+ // There are no non-zero digits, i.e. the number is zero.
183
+ return 0 ;
184
+ }
185
+ } ;
186
+ // This could be optimized with leading_zeros() and bit shifts, but that's
187
+ // probably not worth the hassle.
188
+ let mut i = nonzero. len( ) * digitbits - 1 ;
189
+ while self . get_bit( i) == 0 {
190
+ i -= 1 ;
191
+ }
192
+ i + 1
141
193
}
142
194
143
195
/// Adds `other` to itself and returns its own mutable reference.
@@ -160,6 +212,24 @@ macro_rules! define_bignum {
160
212
self
161
213
}
162
214
215
+ pub fn add_small<' a>( & ' a mut self , other: $ty) -> & ' a mut $name {
216
+ use num:: flt2dec:: bignum:: FullOps ;
217
+
218
+ let ( mut carry, v) = self . base[ 0 ] . full_add( other, false ) ;
219
+ self . base[ 0 ] = v;
220
+ let mut i = 1 ;
221
+ while carry {
222
+ let ( c, v) = self . base[ i] . full_add( 0 , carry) ;
223
+ self . base[ i] = v;
224
+ carry = c;
225
+ i += 1 ;
226
+ }
227
+ if i > self . size {
228
+ self . size = i;
229
+ }
230
+ self
231
+ }
232
+
163
233
/// Subtracts `other` from itself and returns its own mutable reference.
164
234
pub fn sub<' a>( & ' a mut self , other: & $name) -> & ' a mut $name {
165
235
use cmp;
@@ -238,6 +308,34 @@ macro_rules! define_bignum {
238
308
self
239
309
}
240
310
311
+ /// Multiplies itself by `5^e` and returns its own mutable reference.
312
+ pub fn mul_pow5<' a>( & ' a mut self , mut e: usize ) -> & ' a mut $name {
313
+ use mem;
314
+ use num:: flt2dec:: bignum:: SMALL_POW5 ;
315
+
316
+ // There are exactly n trailing zeros on 2^n, and the only relevant digit sizes
317
+ // are consecutive powers of two, so this is well suited index for the table.
318
+ let table_index = mem:: size_of:: <$ty>( ) . trailing_zeros( ) as usize ;
319
+ let ( small_power, small_e) = SMALL_POW5 [ table_index] ;
320
+ let small_power = small_power as $ty;
321
+
322
+ // Multiply with the largest single-digit power as long as possible ...
323
+ while e >= small_e {
324
+ self . mul_small( small_power) ;
325
+ e -= small_e;
326
+ }
327
+
328
+ // ... then finish off the remainder.
329
+ let mut rest_power = 1 ;
330
+ for _ in 0 ..e {
331
+ rest_power *= 5 ;
332
+ }
333
+ self . mul_small( rest_power) ;
334
+
335
+ self
336
+ }
337
+
338
+
241
339
/// Multiplies itself by a number described by `other[0] + other[1] * 2^W +
242
340
/// other[2] * 2^(2W) + ...` (where `W` is the number of bits in the digit type)
243
341
/// and returns its own mutable reference.
@@ -269,9 +367,9 @@ macro_rules! define_bignum {
269
367
270
368
let mut ret = [ 0 ; $n] ;
271
369
let retsz = if self . size < other. len( ) {
272
- mul_inner( & mut ret, & self . base [ .. self . size ] , other)
370
+ mul_inner( & mut ret, & self . digits ( ) , other)
273
371
} else {
274
- mul_inner( & mut ret, other, & self . base [ .. self . size ] )
372
+ mul_inner( & mut ret, other, & self . digits ( ) )
275
373
} ;
276
374
self . base = ret;
277
375
self . size = retsz;
@@ -294,6 +392,45 @@ macro_rules! define_bignum {
294
392
}
295
393
( self , borrow)
296
394
}
395
+
396
+ /// Divide self by another bignum, overwriting `q` with the quotient and `r` with the
397
+ /// remainder.
398
+ pub fn div_rem( & self , d: & $name, q: & mut $name, r: & mut $name) {
399
+ use mem;
400
+
401
+ // Stupid slow base-2 long division taken from
402
+ // https://en.wikipedia.org/wiki/Division_algorithm
403
+ // FIXME use a greater base ($ty) for the long division.
404
+ assert!( !d. is_zero( ) ) ;
405
+ let digitbits = mem:: size_of:: <$ty>( ) * 8 ;
406
+ for digit in & mut q. base[ ..] {
407
+ * digit = 0 ;
408
+ }
409
+ for digit in & mut r. base[ ..] {
410
+ * digit = 0 ;
411
+ }
412
+ r. size = d. size;
413
+ q. size = 1 ;
414
+ let mut q_is_zero = true ;
415
+ let end = self . bit_length( ) ;
416
+ for i in ( 0 ..end) . rev( ) {
417
+ r. mul_pow2( 1 ) ;
418
+ r. base[ 0 ] |= self . get_bit( i) as $ty;
419
+ if & * r >= d {
420
+ r. sub( d) ;
421
+ // Set bit `i` of q to 1.
422
+ let digit_idx = i / digitbits;
423
+ let bit_idx = i % digitbits;
424
+ if q_is_zero {
425
+ q. size = digit_idx + 1 ;
426
+ q_is_zero = false ;
427
+ }
428
+ q. base[ digit_idx] |= 1 << bit_idx;
429
+ }
430
+ }
431
+ debug_assert!( q. base[ q. size..] . iter( ) . all( |& d| d == 0 ) ) ;
432
+ debug_assert!( r. base[ r. size..] . iter( ) . all( |& d| d == 0 ) ) ;
433
+ }
297
434
}
298
435
299
436
impl :: cmp:: PartialEq for $name {
@@ -355,4 +492,3 @@ pub mod tests {
355
492
use prelude:: v1:: * ;
356
493
define_bignum ! ( Big8x3 : type =u8 , n=3 ) ;
357
494
}
358
-
0 commit comments