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