]> git.proxmox.com Git - rustc.git/blob - src/libcore/num/bignum.rs
Imported Upstream version 1.7.0+dfsg1
[rustc.git] / src / libcore / num / bignum.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Custom arbitrary-precision number (bignum) implementation.
12 //!
13 //! This is designed to avoid the heap allocation at expense of stack memory.
14 //! The most used bignum type, `Big32x40`, is limited by 32 × 40 = 1,280 bits
15 //! and will take at most 160 bytes of stack memory. This is more than enough
16 //! for round-tripping all possible finite `f64` values.
17 //!
18 //! In principle it is possible to have multiple bignum types for different
19 //! inputs, but we don't do so to avoid the code bloat. Each bignum is still
20 //! tracked for the actual usages, so it normally doesn't matter.
21
22 // This module is only for dec2flt and flt2dec, and only public because of libcoretest.
23 // It is not intended to ever be stabilized.
24 #![doc(hidden)]
25 #![unstable(feature = "core_private_bignum",
26 reason = "internal routines only exposed for testing",
27 issue = "0")]
28 #![macro_use]
29
30 use prelude::v1::*;
31
32 use mem;
33 use intrinsics;
34
35 /// Arithmetic operations required by bignums.
36 pub trait FullOps {
37 /// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`,
38 /// where `W` is the number of bits in `Self`.
39 fn full_add(self, other: Self, carry: bool) -> (bool /*carry*/, Self);
40
41 /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + carry`,
42 /// where `W` is the number of bits in `Self`.
43 fn full_mul(self, other: Self, carry: Self) -> (Self /*carry*/, Self);
44
45 /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + other2 + carry`,
46 /// where `W` is the number of bits in `Self`.
47 fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /*carry*/, Self);
48
49 /// Returns `(quo, rem)` such that `borrow * 2^W + self = quo * other + rem`
50 /// and `0 <= rem < other`, where `W` is the number of bits in `Self`.
51 fn full_div_rem(self, other: Self, borrow: Self) -> (Self /*quotient*/, Self /*remainder*/);
52 }
53
54 macro_rules! impl_full_ops {
55 ($($ty:ty: add($addfn:path), mul/div($bigty:ident);)*) => (
56 $(
57 impl FullOps for $ty {
58 fn full_add(self, other: $ty, carry: bool) -> (bool, $ty) {
59 // this cannot overflow, the output is between 0 and 2*2^nbits - 1
60 // FIXME will LLVM optimize this into ADC or similar???
61 let (v, carry1) = unsafe { intrinsics::add_with_overflow(self, other) };
62 let (v, carry2) = unsafe {
63 intrinsics::add_with_overflow(v, if carry {1} else {0})
64 };
65 (carry1 || carry2, v)
66 }
67
68 fn full_mul(self, other: $ty, carry: $ty) -> ($ty, $ty) {
69 // this cannot overflow, the output is between 0 and 2^nbits * (2^nbits - 1)
70 let nbits = mem::size_of::<$ty>() * 8;
71 let v = (self as $bigty) * (other as $bigty) + (carry as $bigty);
72 ((v >> nbits) as $ty, v as $ty)
73 }
74
75 fn full_mul_add(self, other: $ty, other2: $ty, carry: $ty) -> ($ty, $ty) {
76 // this cannot overflow, the output is between 0 and 2^(2*nbits) - 1
77 let nbits = mem::size_of::<$ty>() * 8;
78 let v = (self as $bigty) * (other as $bigty) + (other2 as $bigty) +
79 (carry as $bigty);
80 ((v >> nbits) as $ty, v as $ty)
81 }
82
83 fn full_div_rem(self, other: $ty, borrow: $ty) -> ($ty, $ty) {
84 debug_assert!(borrow < other);
85 // this cannot overflow, the dividend is between 0 and other * 2^nbits - 1
86 let nbits = mem::size_of::<$ty>() * 8;
87 let lhs = ((borrow as $bigty) << nbits) | (self as $bigty);
88 let rhs = other as $bigty;
89 ((lhs / rhs) as $ty, (lhs % rhs) as $ty)
90 }
91 }
92 )*
93 )
94 }
95
96 impl_full_ops! {
97 u8: add(intrinsics::u8_add_with_overflow), mul/div(u16);
98 u16: add(intrinsics::u16_add_with_overflow), mul/div(u32);
99 u32: add(intrinsics::u32_add_with_overflow), mul/div(u64);
100 // u64: add(intrinsics::u64_add_with_overflow), mul/div(u128); // see RFC #521 for enabling this.
101 }
102
103 /// Table of powers of 5 representable in digits. Specifically, the largest {u8, u16, u32} value
104 /// that's a power of five, plus the corresponding exponent. Used in `mul_pow5`.
105 const SMALL_POW5: [(u64, usize); 3] = [
106 (125, 3),
107 (15625, 6),
108 (1_220_703_125, 13),
109 ];
110
111 macro_rules! define_bignum {
112 ($name:ident: type=$ty:ty, n=$n:expr) => (
113 /// Stack-allocated arbitrary-precision (up to certain limit) integer.
114 ///
115 /// This is backed by a fixed-size array of given type ("digit").
116 /// While the array is not very large (normally some hundred bytes),
117 /// copying it recklessly may result in the performance hit.
118 /// Thus this is intentionally not `Copy`.
119 ///
120 /// All operations available to bignums panic in the case of over/underflows.
121 /// The caller is responsible to use large enough bignum types.
122 pub struct $name {
123 /// One plus the offset to the maximum "digit" in use.
124 /// This does not decrease, so be aware of the computation order.
125 /// `base[size..]` should be zero.
126 size: usize,
127 /// Digits. `[a, b, c, ...]` represents `a + b*2^W + c*2^(2W) + ...`
128 /// where `W` is the number of bits in the digit type.
129 base: [$ty; $n]
130 }
131
132 impl $name {
133 /// Makes a bignum from one digit.
134 pub fn from_small(v: $ty) -> $name {
135 let mut base = [0; $n];
136 base[0] = v;
137 $name { size: 1, base: base }
138 }
139
140 /// Makes a bignum from `u64` value.
141 pub fn from_u64(mut v: u64) -> $name {
142 use mem;
143
144 let mut base = [0; $n];
145 let mut sz = 0;
146 while v > 0 {
147 base[sz] = v as $ty;
148 v >>= mem::size_of::<$ty>() * 8;
149 sz += 1;
150 }
151 $name { size: sz, base: base }
152 }
153
154 /// Return the internal digits as a slice `[a, b, c, ...]` such that the numeric
155 /// value is `a + b * 2^W + c * 2^(2W) + ...` where `W` is the number of bits in
156 /// the digit type.
157 pub fn digits(&self) -> &[$ty] {
158 &self.base[..self.size]
159 }
160
161 /// Return the `i`-th bit where bit 0 is the least significant one.
162 /// In other words, the bit with weight `2^i`.
163 pub fn get_bit(&self, i: usize) -> u8 {
164 use mem;
165
166 let digitbits = mem::size_of::<$ty>() * 8;
167 let d = i / digitbits;
168 let b = i % digitbits;
169 ((self.base[d] >> b) & 1) as u8
170 }
171
172 /// Returns true if the bignum is zero.
173 pub fn is_zero(&self) -> bool {
174 self.digits().iter().all(|&v| v == 0)
175 }
176
177 /// Returns the number of bits necessary to represent this value. Note that zero
178 /// is considered to need 0 bits.
179 pub fn bit_length(&self) -> usize {
180 use mem;
181
182 // Skip over the most significant digits which are zero.
183 let digits = self.digits();
184 let zeros = digits.iter().rev().take_while(|&&x| x == 0).count();
185 let end = digits.len() - zeros;
186 let nonzero = &digits[..end];
187
188 if nonzero.is_empty() {
189 // There are no non-zero digits, i.e. the number is zero.
190 return 0;
191 }
192 // This could be optimized with leading_zeros() and bit shifts, but that's
193 // probably not worth the hassle.
194 let digitbits = mem::size_of::<$ty>()* 8;
195 let mut i = nonzero.len() * digitbits - 1;
196 while self.get_bit(i) == 0 {
197 i -= 1;
198 }
199 i + 1
200 }
201
202 /// Adds `other` to itself and returns its own mutable reference.
203 pub fn add<'a>(&'a mut self, other: &$name) -> &'a mut $name {
204 use cmp;
205 use num::bignum::FullOps;
206
207 let mut sz = cmp::max(self.size, other.size);
208 let mut carry = false;
209 for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) {
210 let (c, v) = (*a).full_add(*b, carry);
211 *a = v;
212 carry = c;
213 }
214 if carry {
215 self.base[sz] = 1;
216 sz += 1;
217 }
218 self.size = sz;
219 self
220 }
221
222 pub fn add_small(&mut self, other: $ty) -> &mut $name {
223 use num::bignum::FullOps;
224
225 let (mut carry, v) = self.base[0].full_add(other, false);
226 self.base[0] = v;
227 let mut i = 1;
228 while carry {
229 let (c, v) = self.base[i].full_add(0, carry);
230 self.base[i] = v;
231 carry = c;
232 i += 1;
233 }
234 if i > self.size {
235 self.size = i;
236 }
237 self
238 }
239
240 /// Subtracts `other` from itself and returns its own mutable reference.
241 pub fn sub<'a>(&'a mut self, other: &$name) -> &'a mut $name {
242 use cmp;
243 use num::bignum::FullOps;
244
245 let sz = cmp::max(self.size, other.size);
246 let mut noborrow = true;
247 for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) {
248 let (c, v) = (*a).full_add(!*b, noborrow);
249 *a = v;
250 noborrow = c;
251 }
252 assert!(noborrow);
253 self.size = sz;
254 self
255 }
256
257 /// Multiplies itself by a digit-sized `other` and returns its own
258 /// mutable reference.
259 pub fn mul_small(&mut self, other: $ty) -> &mut $name {
260 use num::bignum::FullOps;
261
262 let mut sz = self.size;
263 let mut carry = 0;
264 for a in &mut self.base[..sz] {
265 let (c, v) = (*a).full_mul(other, carry);
266 *a = v;
267 carry = c;
268 }
269 if carry > 0 {
270 self.base[sz] = carry;
271 sz += 1;
272 }
273 self.size = sz;
274 self
275 }
276
277 /// Multiplies itself by `2^bits` and returns its own mutable reference.
278 pub fn mul_pow2(&mut self, bits: usize) -> &mut $name {
279 use mem;
280
281 let digitbits = mem::size_of::<$ty>() * 8;
282 let digits = bits / digitbits;
283 let bits = bits % digitbits;
284
285 assert!(digits < $n);
286 debug_assert!(self.base[$n-digits..].iter().all(|&v| v == 0));
287 debug_assert!(bits == 0 || (self.base[$n-digits-1] >> (digitbits - bits)) == 0);
288
289 // shift by `digits * digitbits` bits
290 for i in (0..self.size).rev() {
291 self.base[i+digits] = self.base[i];
292 }
293 for i in 0..digits {
294 self.base[i] = 0;
295 }
296
297 // shift by `bits` bits
298 let mut sz = self.size + digits;
299 if bits > 0 {
300 let last = sz;
301 let overflow = self.base[last-1] >> (digitbits - bits);
302 if overflow > 0 {
303 self.base[last] = overflow;
304 sz += 1;
305 }
306 for i in (digits+1..last).rev() {
307 self.base[i] = (self.base[i] << bits) |
308 (self.base[i-1] >> (digitbits - bits));
309 }
310 self.base[digits] <<= bits;
311 // self.base[..digits] is zero, no need to shift
312 }
313
314 self.size = sz;
315 self
316 }
317
318 /// Multiplies itself by `5^e` and returns its own mutable reference.
319 pub fn mul_pow5(&mut self, mut e: usize) -> &mut $name {
320 use mem;
321 use num::bignum::SMALL_POW5;
322
323 // There are exactly n trailing zeros on 2^n, and the only relevant digit sizes
324 // are consecutive powers of two, so this is well suited index for the table.
325 let table_index = mem::size_of::<$ty>().trailing_zeros() as usize;
326 let (small_power, small_e) = SMALL_POW5[table_index];
327 let small_power = small_power as $ty;
328
329 // Multiply with the largest single-digit power as long as possible ...
330 while e >= small_e {
331 self.mul_small(small_power);
332 e -= small_e;
333 }
334
335 // ... then finish off the remainder.
336 let mut rest_power = 1;
337 for _ in 0..e {
338 rest_power *= 5;
339 }
340 self.mul_small(rest_power);
341
342 self
343 }
344
345
346 /// Multiplies itself by a number described by `other[0] + other[1] * 2^W +
347 /// other[2] * 2^(2W) + ...` (where `W` is the number of bits in the digit type)
348 /// and returns its own mutable reference.
349 pub fn mul_digits<'a>(&'a mut self, other: &[$ty]) -> &'a mut $name {
350 // the internal routine. works best when aa.len() <= bb.len().
351 fn mul_inner(ret: &mut [$ty; $n], aa: &[$ty], bb: &[$ty]) -> usize {
352 use num::bignum::FullOps;
353
354 let mut retsz = 0;
355 for (i, &a) in aa.iter().enumerate() {
356 if a == 0 { continue; }
357 let mut sz = bb.len();
358 let mut carry = 0;
359 for (j, &b) in bb.iter().enumerate() {
360 let (c, v) = a.full_mul_add(b, ret[i + j], carry);
361 ret[i + j] = v;
362 carry = c;
363 }
364 if carry > 0 {
365 ret[i + sz] = carry;
366 sz += 1;
367 }
368 if retsz < i + sz {
369 retsz = i + sz;
370 }
371 }
372 retsz
373 }
374
375 let mut ret = [0; $n];
376 let retsz = if self.size < other.len() {
377 mul_inner(&mut ret, &self.digits(), other)
378 } else {
379 mul_inner(&mut ret, other, &self.digits())
380 };
381 self.base = ret;
382 self.size = retsz;
383 self
384 }
385
386 /// Divides itself by a digit-sized `other` and returns its own
387 /// mutable reference *and* the remainder.
388 pub fn div_rem_small(&mut self, other: $ty) -> (&mut $name, $ty) {
389 use num::bignum::FullOps;
390
391 assert!(other > 0);
392
393 let sz = self.size;
394 let mut borrow = 0;
395 for a in self.base[..sz].iter_mut().rev() {
396 let (q, r) = (*a).full_div_rem(other, borrow);
397 *a = q;
398 borrow = r;
399 }
400 (self, borrow)
401 }
402
403 /// Divide self by another bignum, overwriting `q` with the quotient and `r` with the
404 /// remainder.
405 pub fn div_rem(&self, d: &$name, q: &mut $name, r: &mut $name) {
406 use mem;
407
408 // Stupid slow base-2 long division taken from
409 // https://en.wikipedia.org/wiki/Division_algorithm
410 // FIXME use a greater base ($ty) for the long division.
411 assert!(!d.is_zero());
412 let digitbits = mem::size_of::<$ty>() * 8;
413 for digit in &mut q.base[..] {
414 *digit = 0;
415 }
416 for digit in &mut r.base[..] {
417 *digit = 0;
418 }
419 r.size = d.size;
420 q.size = 1;
421 let mut q_is_zero = true;
422 let end = self.bit_length();
423 for i in (0..end).rev() {
424 r.mul_pow2(1);
425 r.base[0] |= self.get_bit(i) as $ty;
426 if &*r >= d {
427 r.sub(d);
428 // Set bit `i` of q to 1.
429 let digit_idx = i / digitbits;
430 let bit_idx = i % digitbits;
431 if q_is_zero {
432 q.size = digit_idx + 1;
433 q_is_zero = false;
434 }
435 q.base[digit_idx] |= 1 << bit_idx;
436 }
437 }
438 debug_assert!(q.base[q.size..].iter().all(|&d| d == 0));
439 debug_assert!(r.base[r.size..].iter().all(|&d| d == 0));
440 }
441 }
442
443 impl ::cmp::PartialEq for $name {
444 fn eq(&self, other: &$name) -> bool { self.base[..] == other.base[..] }
445 }
446
447 impl ::cmp::Eq for $name {
448 }
449
450 impl ::cmp::PartialOrd for $name {
451 fn partial_cmp(&self, other: &$name) -> ::option::Option<::cmp::Ordering> {
452 ::option::Option::Some(self.cmp(other))
453 }
454 }
455
456 impl ::cmp::Ord for $name {
457 fn cmp(&self, other: &$name) -> ::cmp::Ordering {
458 use cmp::max;
459 let sz = max(self.size, other.size);
460 let lhs = self.base[..sz].iter().cloned().rev();
461 let rhs = other.base[..sz].iter().cloned().rev();
462 lhs.cmp(rhs)
463 }
464 }
465
466 impl ::clone::Clone for $name {
467 fn clone(&self) -> $name {
468 $name { size: self.size, base: self.base }
469 }
470 }
471
472 impl ::fmt::Debug for $name {
473 fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
474 use mem;
475
476 let sz = if self.size < 1 {1} else {self.size};
477 let digitlen = mem::size_of::<$ty>() * 2;
478
479 try!(write!(f, "{:#x}", self.base[sz-1]));
480 for &v in self.base[..sz-1].iter().rev() {
481 try!(write!(f, "_{:01$x}", v, digitlen));
482 }
483 ::result::Result::Ok(())
484 }
485 }
486 )
487 }
488
489 /// The digit type for `Big32x40`.
490 pub type Digit32 = u32;
491
492 define_bignum!(Big32x40: type=Digit32, n=40);
493
494 // this one is used for testing only.
495 #[doc(hidden)]
496 pub mod tests {
497 use prelude::v1::*;
498 define_bignum!(Big8x3: type=u8, n=3);
499 }