sp_arithmetic/
biguint.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Infinite precision unsigned integer for substrate runtime.
19
20use alloc::{vec, vec::Vec};
21use codec::{Decode, Encode};
22use core::{cell::RefCell, cmp::Ordering, ops};
23use num_traits::{One, Zero};
24
25// A sensible value for this would be half of the dword size of the host machine. Since the
26// runtime is compiled to 32bit webassembly, using 32 and 64 for single and double respectively
27// should yield the most performance.
28
29/// Representation of a single limb.
30pub type Single = u32;
31/// Representation of two limbs.
32pub type Double = u64;
33/// Difference in the number of bits of [`Single`] and [`Double`].
34const SHIFT: usize = 32;
35/// short form of _Base_. Analogous to the value 10 in base-10 decimal numbers.
36const B: Double = Single::max_value() as Double + 1;
37
38static_assertions::const_assert!(
39	core::mem::size_of::<Double>() - core::mem::size_of::<Single>() == SHIFT / 8
40);
41
42/// Splits a [`Double`] limb number into a tuple of two [`Single`] limb numbers.
43pub fn split(a: Double) -> (Single, Single) {
44	let al = a as Single;
45	let ah = (a >> SHIFT) as Single;
46	(ah, al)
47}
48
49/// Assumed as a given primitive.
50///
51/// Multiplication of two singles, which at most yields 1 double.
52pub fn mul_single(a: Single, b: Single) -> Double {
53	let a: Double = a.into();
54	let b: Double = b.into();
55	a * b
56}
57
58/// Assumed as a given primitive.
59///
60/// Addition of two singles, which at most takes a single limb of result and a carry,
61/// returned as a tuple respectively.
62pub fn add_single(a: Single, b: Single) -> (Single, Single) {
63	let a: Double = a.into();
64	let b: Double = b.into();
65	let q = a + b;
66	let (carry, r) = split(q);
67	(r, carry)
68}
69
70/// Assumed as a given primitive.
71///
72/// Division of double by a single limb. Always returns a double limb of quotient and a single
73/// limb of remainder.
74fn div_single(a: Double, b: Single) -> (Double, Single) {
75	let b: Double = b.into();
76	let q = a / b;
77	let r = a % b;
78	// both conversions are trivially safe.
79	(q, r as Single)
80}
81
82/// Simple wrapper around an infinitely large integer, represented as limbs of [`Single`].
83#[derive(Encode, Decode, Clone, Default)]
84pub struct BigUint {
85	/// digits (limbs) of this number (sorted as msb -> lsb).
86	pub(crate) digits: Vec<Single>,
87}
88
89impl BigUint {
90	/// Create a new instance with `size` limbs. This prevents any number with zero limbs to be
91	/// created.
92	///
93	/// The behavior of the type is undefined with zero limbs.
94	pub fn with_capacity(size: usize) -> Self {
95		Self { digits: vec![0; size.max(1)] }
96	}
97
98	/// Raw constructor from custom limbs. If `limbs` is empty, `Zero::zero()` implementation is
99	/// used.
100	pub fn from_limbs(limbs: &[Single]) -> Self {
101		if !limbs.is_empty() {
102			Self { digits: limbs.to_vec() }
103		} else {
104			Zero::zero()
105		}
106	}
107
108	/// Number of limbs.
109	pub fn len(&self) -> usize {
110		self.digits.len()
111	}
112
113	/// A naive getter for limb at `index`. Note that the order is lsb -> msb.
114	///
115	/// #### Panics
116	///
117	/// This panics if index is out of range.
118	pub fn get(&self, index: usize) -> Single {
119		self.digits[self.len() - 1 - index]
120	}
121
122	/// A naive getter for limb at `index`. Note that the order is lsb -> msb.
123	pub fn checked_get(&self, index: usize) -> Option<Single> {
124		let i = self.len().checked_sub(1)?;
125		let j = i.checked_sub(index)?;
126		self.digits.get(j).cloned()
127	}
128
129	/// A naive setter for limb at `index`. Note that the order is lsb -> msb.
130	///
131	/// #### Panics
132	///
133	/// This panics if index is out of range.
134	pub fn set(&mut self, index: usize, value: Single) {
135		let len = self.digits.len();
136		self.digits[len - 1 - index] = value;
137	}
138
139	/// returns the least significant limb of the number.
140	///
141	/// #### Panics
142	///
143	/// While the constructor of the type prevents this, this can panic if `self` has no digits.
144	pub fn lsb(&self) -> Single {
145		self.digits[self.len() - 1]
146	}
147
148	/// returns the most significant limb of the number.
149	///
150	/// #### Panics
151	///
152	/// While the constructor of the type prevents this, this can panic if `self` has no digits.
153	pub fn msb(&self) -> Single {
154		self.digits[0]
155	}
156
157	/// Strips zeros from the left side (the most significant limbs) of `self`, if any.
158	pub fn lstrip(&mut self) {
159		// by definition, a big-int number should never have leading zero limbs. This function
160		// has the ability to cause this. There is nothing to do if the number already has 1
161		// limb only. call it a day and return.
162		if self.len().is_zero() {
163			return
164		}
165		let index = self.digits.iter().position(|&elem| elem != 0).unwrap_or(self.len() - 1);
166
167		if index > 0 {
168			self.digits = self.digits[index..].to_vec()
169		}
170	}
171
172	/// Zero-pad `self` from left to reach `size` limbs. Will not make any difference if `self`
173	/// is already bigger than `size` limbs.
174	pub fn lpad(&mut self, size: usize) {
175		let n = self.len();
176		if n >= size {
177			return
178		}
179		let pad = size - n;
180		let mut new_digits = (0..pad).map(|_| 0).collect::<Vec<Single>>();
181		new_digits.extend(self.digits.iter());
182		self.digits = new_digits;
183	}
184
185	/// Adds `self` with `other`. self and other do not have to have any particular size. Given
186	/// that the `n = max{size(self), size(other)}`, it will produce a number with `n + 1`
187	/// limbs.
188	///
189	/// This function does not strip the output and returns the original allocated `n + 1`
190	/// limbs. The caller may strip the output if desired.
191	///
192	/// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4.
193	pub fn add(self, other: &Self) -> Self {
194		let n = self.len().max(other.len());
195		let mut k: Double = 0;
196		let mut w = Self::with_capacity(n + 1);
197
198		for j in 0..n {
199			let u = Double::from(self.checked_get(j).unwrap_or(0));
200			let v = Double::from(other.checked_get(j).unwrap_or(0));
201			let s = u + v + k;
202			// proof: any number % B will fit into `Single`.
203			w.set(j, (s % B) as Single);
204			k = s / B;
205		}
206		// k is always 0 or 1.
207		w.set(n, k as Single);
208		w
209	}
210
211	/// Subtracts `other` from `self`. self and other do not have to have any particular size.
212	/// Given that the `n = max{size(self), size(other)}`, it will produce a number of size `n`.
213	///
214	/// If `other` is bigger than `self`, `Err(B - borrow)` is returned.
215	///
216	/// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4.
217	pub fn sub(self, other: &Self) -> Result<Self, Self> {
218		let n = self.len().max(other.len());
219		let mut k = 0;
220		let mut w = Self::with_capacity(n);
221		for j in 0..n {
222			let s = {
223				let u = Double::from(self.checked_get(j).unwrap_or(0));
224				let v = Double::from(other.checked_get(j).unwrap_or(0));
225
226				if let Some(v2) = u.checked_sub(v).and_then(|v1| v1.checked_sub(k)) {
227					// no borrow is needed. u - v - k can be computed as-is
228					let t = v2;
229					k = 0;
230
231					t
232				} else {
233					// borrow is needed. Add a `B` to u, before subtracting.
234					// PROOF: addition: `u + B < 2*B`, thus can fit in double.
235					// PROOF: subtraction: if `u - v - k < 0`, then `u + B - v - k < B`.
236					// NOTE: the order of operations is critical to ensure underflow won't happen.
237					let t = u + B - v - k;
238					k = 1;
239
240					t
241				}
242			};
243			w.set(j, s as Single);
244		}
245
246		if k.is_zero() {
247			Ok(w)
248		} else {
249			Err(w)
250		}
251	}
252
253	/// Multiplies n-limb number `self` with m-limb number `other`.
254	///
255	/// The resulting number will always have `n + m` limbs.
256	///
257	/// This function does not strip the output and returns the original allocated `n + m`
258	/// limbs. The caller may strip the output if desired.
259	///
260	/// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4.
261	pub fn mul(self, other: &Self) -> Self {
262		let n = self.len();
263		let m = other.len();
264		let mut w = Self::with_capacity(m + n);
265
266		for j in 0..n {
267			if self.get(j) == 0 {
268				// Note: `with_capacity` allocates with 0. Explicitly set j + m to zero if
269				// otherwise.
270				continue
271			}
272
273			let mut k = 0;
274			for i in 0..m {
275				// PROOF: (B−1) × (B−1) + (B−1) + (B−1) = B^2 −1 < B^2. addition is safe.
276				let t = mul_single(self.get(j), other.get(i)) +
277					Double::from(w.get(i + j)) +
278					Double::from(k);
279				w.set(i + j, (t % B) as Single);
280				// PROOF: (B^2 - 1) / B < B. conversion is safe.
281				k = (t / B) as Single;
282			}
283			w.set(j + m, k);
284		}
285		w
286	}
287
288	/// Divides `self` by a single limb `other`. This can be used in cases where the original
289	/// division cannot work due to the divisor (`other`) being just one limb.
290	///
291	/// Invariant: `other` cannot be zero.
292	pub fn div_unit(self, mut other: Single) -> Self {
293		other = other.max(1);
294		let n = self.len();
295		let mut out = Self::with_capacity(n);
296		let mut r: Single = 0;
297		// PROOF: (B-1) * B + (B-1) still fits in double
298		let with_r = |x: Single, r: Single| Double::from(r) * B + Double::from(x);
299		for d in (0..n).rev() {
300			let (q, rr) = div_single(with_r(self.get(d), r), other);
301			out.set(d, q as Single);
302			r = rr;
303		}
304		out
305	}
306
307	/// Divides an `n + m` limb self by a `n` limb `other`. The result is a `m + 1` limb
308	/// quotient and a `n` limb remainder, if enabled by passing `true` in `rem` argument, both
309	/// in the form of an option's `Ok`.
310	///
311	/// - requires `other` to be stripped and have no leading zeros.
312	/// - requires `self` to be stripped and have no leading zeros.
313	/// - requires `other` to have at least two limbs.
314	/// - requires `self` to have a greater length compared to `other`.
315	///
316	/// All arguments are examined without being stripped for the above conditions. If any of
317	/// the above fails, `None` is returned.`
318	///
319	/// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4.
320	pub fn div(self, other: &Self, rem: bool) -> Option<(Self, Self)> {
321		if other.len() <= 1 || other.msb() == 0 || self.msb() == 0 || self.len() <= other.len() {
322			return None
323		}
324		let n = other.len();
325		let m = self.len() - n;
326
327		let mut q = Self::with_capacity(m + 1);
328		let mut r = Self::with_capacity(n);
329
330		// PROOF: 0 <= normalizer_bits < SHIFT 0 <= normalizer < B. all conversions are
331		// safe.
332		let normalizer_bits = other.msb().leading_zeros() as Single;
333		let normalizer = 2_u32.pow(normalizer_bits as u32) as Single;
334
335		// step D1.
336		let mut self_norm = self.mul(&Self::from(normalizer));
337		let mut other_norm = other.clone().mul(&Self::from(normalizer));
338
339		// defensive only; the mul implementation should always create this.
340		self_norm.lpad(n + m + 1);
341		other_norm.lstrip();
342
343		// step D2.
344		for j in (0..=m).rev() {
345			// step D3.0 Find an estimate of q[j], named qhat.
346			let (qhat, rhat) = {
347				// PROOF: this always fits into `Double`. In the context of Single = u8, and
348				// Double = u16, think of 255 * 256 + 255 which is just u16::MAX.
349				let dividend =
350					Double::from(self_norm.get(j + n)) * B + Double::from(self_norm.get(j + n - 1));
351				let divisor = other_norm.get(n - 1);
352				div_single(dividend, divisor)
353			};
354
355			// D3.1 test qhat
356			// replace qhat and rhat with RefCells. This helps share state with the closure
357			let qhat = RefCell::new(qhat);
358			let rhat = RefCell::new(Double::from(rhat));
359
360			let test = || {
361				// decrease qhat if it is bigger than the base (B)
362				let qhat_local = *qhat.borrow();
363				let rhat_local = *rhat.borrow();
364				let predicate_1 = qhat_local >= B;
365				let predicate_2 = {
366					let lhs = qhat_local * Double::from(other_norm.get(n - 2));
367					let rhs = B * rhat_local + Double::from(self_norm.get(j + n - 2));
368					lhs > rhs
369				};
370				if predicate_1 || predicate_2 {
371					*qhat.borrow_mut() -= 1;
372					*rhat.borrow_mut() += Double::from(other_norm.get(n - 1));
373					true
374				} else {
375					false
376				}
377			};
378
379			test();
380			while (*rhat.borrow() as Double) < B {
381				if !test() {
382					break
383				}
384			}
385
386			let qhat = qhat.into_inner();
387			// we don't need rhat anymore. just let it go out of scope when it does.
388
389			// step D4
390			let lhs = Self { digits: (j..=j + n).rev().map(|d| self_norm.get(d)).collect() };
391			let rhs = other_norm.clone().mul(&Self::from(qhat));
392
393			let maybe_sub = lhs.sub(&rhs);
394			let mut negative = false;
395			let sub = match maybe_sub {
396				Ok(t) => t,
397				Err(t) => {
398					negative = true;
399					t
400				},
401			};
402			(j..=j + n).for_each(|d| {
403				self_norm.set(d, sub.get(d - j));
404			});
405
406			// step D5
407			// PROOF: the `test()` specifically decreases qhat until it is below `B`. conversion
408			// is safe.
409			q.set(j, qhat as Single);
410
411			// step D6: add back if negative happened.
412			if negative {
413				q.set(j, q.get(j) - 1);
414				let u = Self { digits: (j..=j + n).rev().map(|d| self_norm.get(d)).collect() };
415				let r = other_norm.clone().add(&u);
416				(j..=j + n).rev().for_each(|d| {
417					self_norm.set(d, r.get(d - j));
418				})
419			}
420		}
421
422		// if requested, calculate remainder.
423		if rem {
424			// undo the normalization.
425			if normalizer_bits > 0 {
426				let s = SHIFT as u32;
427				let nb = normalizer_bits;
428				for d in 0..n - 1 {
429					let v =
430						(self_norm.get(d) >> nb) | self_norm.get(d + 1).overflowing_shl(s - nb).0;
431					r.set(d, v);
432				}
433				r.set(n - 1, self_norm.get(n - 1) >> normalizer_bits);
434			} else {
435				r = self_norm;
436			}
437		}
438
439		Some((q, r))
440	}
441}
442
443impl core::fmt::Debug for BigUint {
444	#[cfg(feature = "std")]
445	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
446		write!(
447			f,
448			"BigUint {{ {:?} ({:?})}}",
449			self.digits,
450			u128::try_from(self.clone()).unwrap_or(0),
451		)
452	}
453
454	#[cfg(not(feature = "std"))]
455	fn fmt(&self, _: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
456		Ok(())
457	}
458}
459
460impl PartialEq for BigUint {
461	fn eq(&self, other: &Self) -> bool {
462		self.cmp(other) == Ordering::Equal
463	}
464}
465
466impl Eq for BigUint {}
467
468impl Ord for BigUint {
469	fn cmp(&self, other: &Self) -> Ordering {
470		let lhs_first = self.digits.iter().position(|&e| e != 0);
471		let rhs_first = other.digits.iter().position(|&e| e != 0);
472
473		match (lhs_first, rhs_first) {
474			// edge cases that should not happen. This basically means that one or both were
475			// zero.
476			(None, None) => Ordering::Equal,
477			(Some(_), None) => Ordering::Greater,
478			(None, Some(_)) => Ordering::Less,
479			(Some(lhs_idx), Some(rhs_idx)) => {
480				let lhs = &self.digits[lhs_idx..];
481				let rhs = &other.digits[rhs_idx..];
482				let len_cmp = lhs.len().cmp(&rhs.len());
483				match len_cmp {
484					Ordering::Equal => lhs.cmp(rhs),
485					_ => len_cmp,
486				}
487			},
488		}
489	}
490}
491
492impl PartialOrd for BigUint {
493	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
494		Some(self.cmp(other))
495	}
496}
497
498impl ops::Add for BigUint {
499	type Output = Self;
500	fn add(self, rhs: Self) -> Self::Output {
501		self.add(&rhs)
502	}
503}
504
505impl ops::Sub for BigUint {
506	type Output = Self;
507	fn sub(self, rhs: Self) -> Self::Output {
508		self.sub(&rhs).unwrap_or_else(|e| e)
509	}
510}
511
512impl ops::Mul for BigUint {
513	type Output = Self;
514	fn mul(self, rhs: Self) -> Self::Output {
515		self.mul(&rhs)
516	}
517}
518
519impl Zero for BigUint {
520	fn zero() -> Self {
521		Self { digits: vec![Zero::zero()] }
522	}
523
524	fn is_zero(&self) -> bool {
525		self.digits.iter().all(|d| d.is_zero())
526	}
527}
528
529impl One for BigUint {
530	fn one() -> Self {
531		Self { digits: vec![Single::one()] }
532	}
533}
534
535macro_rules! impl_try_from_number_for {
536	($([$type:ty, $len:expr]),+) => {
537		$(
538			impl TryFrom<BigUint> for $type {
539				type Error = &'static str;
540				fn try_from(mut value: BigUint) -> Result<$type, Self::Error> {
541					value.lstrip();
542					let error_message = concat!("cannot fit a number into ", stringify!($type));
543					if value.len() * SHIFT > $len {
544						Err(error_message)
545					} else {
546						let mut acc: $type = Zero::zero();
547						for (i, d) in value.digits.iter().rev().cloned().enumerate() {
548							let d: $type = d.into();
549							acc += d << (SHIFT * i);
550						}
551						Ok(acc)
552					}
553				}
554			}
555		)*
556	};
557}
558// can only be implemented for sizes bigger than two limb.
559impl_try_from_number_for!([u128, 128], [u64, 64]);
560
561macro_rules! impl_from_for_smaller_than_word {
562	($($type:ty),+) => {
563		$(impl From<$type> for BigUint {
564			fn from(a: $type) -> Self {
565				Self { digits: vec! [a.into()] }
566			}
567		})*
568	}
569}
570impl_from_for_smaller_than_word!(u8, u16, u32);
571
572impl From<u64> for BigUint {
573	fn from(a: Double) -> Self {
574		let (ah, al) = split(a);
575		Self { digits: vec![ah, al] }
576	}
577}
578
579impl From<u128> for BigUint {
580	fn from(a: u128) -> Self {
581		crate::helpers_128bit::to_big_uint(a)
582	}
583}
584
585#[cfg(test)]
586pub mod tests {
587	use super::*;
588
589	fn with_limbs(n: usize) -> BigUint {
590		BigUint { digits: vec![1; n] }
591	}
592
593	#[test]
594	fn split_works() {
595		let a = SHIFT / 2;
596		let b = SHIFT * 3 / 2;
597		let num: Double = (1 << a) | (1 << b);
598		assert_eq!(num, 0x_0001_0000_0001_0000);
599		assert_eq!(split(num), (1 << a, 1 << a));
600
601		let a = SHIFT / 2 + 4;
602		let b = SHIFT / 2 - 4;
603		let num: Double = (1 << (SHIFT + a)) | (1 << b);
604		assert_eq!(num, 0x_0010_0000_0000_1000);
605		assert_eq!(split(num), (1 << a, 1 << b));
606	}
607
608	#[test]
609	fn strip_works() {
610		let mut a = BigUint::from_limbs(&[0, 1, 0]);
611		a.lstrip();
612		assert_eq!(a.digits, vec![1, 0]);
613
614		let mut a = BigUint::from_limbs(&[0, 0, 1]);
615		a.lstrip();
616		assert_eq!(a.digits, vec![1]);
617
618		let mut a = BigUint::from_limbs(&[0, 0]);
619		a.lstrip();
620		assert_eq!(a.digits, vec![0]);
621
622		let mut a = BigUint::from_limbs(&[0, 0, 0]);
623		a.lstrip();
624		assert_eq!(a.digits, vec![0]);
625	}
626
627	#[test]
628	fn lpad_works() {
629		let mut a = BigUint::from_limbs(&[0, 1, 0]);
630		a.lpad(2);
631		assert_eq!(a.digits, vec![0, 1, 0]);
632
633		let mut a = BigUint::from_limbs(&[0, 1, 0]);
634		a.lpad(3);
635		assert_eq!(a.digits, vec![0, 1, 0]);
636
637		let mut a = BigUint::from_limbs(&[0, 1, 0]);
638		a.lpad(4);
639		assert_eq!(a.digits, vec![0, 0, 1, 0]);
640	}
641
642	#[test]
643	fn equality_works() {
644		assert_eq!(BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, true);
645		assert_eq!(BigUint { digits: vec![3, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, false);
646		assert_eq!(BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, true);
647	}
648
649	#[test]
650	fn ordering_works() {
651		assert!(BigUint { digits: vec![0] } < BigUint { digits: vec![1] });
652		assert!(BigUint { digits: vec![0] } == BigUint { digits: vec![0] });
653		assert!(BigUint { digits: vec![] } == BigUint { digits: vec![0] });
654		assert!(BigUint { digits: vec![] } == BigUint { digits: vec![] });
655		assert!(BigUint { digits: vec![] } < BigUint { digits: vec![1] });
656
657		assert!(BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] });
658		assert!(BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] });
659
660		assert!(BigUint { digits: vec![1, 2, 4] } > BigUint { digits: vec![1, 2, 3] });
661		assert!(BigUint { digits: vec![0, 1, 2, 4] } > BigUint { digits: vec![1, 2, 3] });
662		assert!(BigUint { digits: vec![1, 2, 1, 0] } > BigUint { digits: vec![1, 2, 3] });
663
664		assert!(BigUint { digits: vec![0, 1, 2, 1] } < BigUint { digits: vec![1, 2, 3] });
665	}
666
667	#[test]
668	fn can_try_build_numbers_from_types() {
669		assert_eq!(u64::try_from(with_limbs(1)).unwrap(), 1);
670		assert_eq!(u64::try_from(with_limbs(2)).unwrap(), u32::MAX as u64 + 2);
671		assert_eq!(u64::try_from(with_limbs(3)).unwrap_err(), "cannot fit a number into u64");
672		assert_eq!(u128::try_from(with_limbs(3)).unwrap(), u32::MAX as u128 + u64::MAX as u128 + 3);
673	}
674
675	#[test]
676	fn zero_works() {
677		assert_eq!(BigUint::zero(), BigUint { digits: vec![0] });
678		assert_eq!(BigUint { digits: vec![0, 1, 0] }.is_zero(), false);
679		assert_eq!(BigUint { digits: vec![0, 0, 0] }.is_zero(), true);
680
681		let a = BigUint::zero();
682		let b = BigUint::zero();
683		let c = a * b;
684		assert_eq!(c.digits, vec![0, 0]);
685	}
686
687	#[test]
688	fn sub_negative_works() {
689		assert_eq!(
690			BigUint::from(10 as Single).sub(&BigUint::from(5 as Single)).unwrap(),
691			BigUint::from(5 as Single)
692		);
693		assert_eq!(
694			BigUint::from(10 as Single).sub(&BigUint::from(10 as Single)).unwrap(),
695			BigUint::from(0 as Single)
696		);
697		assert_eq!(
698			BigUint::from(10 as Single).sub(&BigUint::from(13 as Single)).unwrap_err(),
699			BigUint::from((B - 3) as Single),
700		);
701	}
702
703	#[test]
704	fn mul_always_appends_one_digit() {
705		let a = BigUint::from(10 as Single);
706		let b = BigUint::from(4 as Single);
707		assert_eq!(a.len(), 1);
708		assert_eq!(b.len(), 1);
709
710		let n = a.mul(&b);
711
712		assert_eq!(n.len(), 2);
713		assert_eq!(n.digits, vec![0, 40]);
714	}
715
716	#[test]
717	fn div_conditions_work() {
718		let a = BigUint { digits: vec![2] };
719		let b = BigUint { digits: vec![1, 2] };
720		let c = BigUint { digits: vec![1, 1, 2] };
721		let d = BigUint { digits: vec![0, 2] };
722		let e = BigUint { digits: vec![0, 1, 1, 2] };
723		let f = BigUint { digits: vec![7, 8] };
724
725		assert!(a.clone().div(&b, true).is_none());
726		assert!(c.clone().div(&a, true).is_none());
727		assert!(c.clone().div(&d, true).is_none());
728		assert!(e.clone().div(&a, true).is_none());
729
730		assert!(f.clone().div(&b, true).is_none());
731		assert!(c.clone().div(&b, true).is_some());
732	}
733
734	#[test]
735	fn div_unit_works() {
736		let a = BigUint { digits: vec![100] };
737		let b = BigUint { digits: vec![1, 100] };
738		let c = BigUint { digits: vec![14, 28, 100] };
739
740		assert_eq!(a.clone().div_unit(1), a);
741		assert_eq!(a.clone().div_unit(0), a);
742		assert_eq!(a.clone().div_unit(2), BigUint::from(50 as Single));
743		assert_eq!(a.clone().div_unit(7), BigUint::from(14 as Single));
744
745		assert_eq!(b.clone().div_unit(1), b);
746		assert_eq!(b.clone().div_unit(0), b);
747		assert_eq!(b.clone().div_unit(2), BigUint::from(((B + 100) / 2) as Single));
748		assert_eq!(b.clone().div_unit(7), BigUint::from(((B + 100) / 7) as Single));
749
750		assert_eq!(c.clone().div_unit(1), c);
751		assert_eq!(c.clone().div_unit(0), c);
752		assert_eq!(c.clone().div_unit(2), BigUint { digits: vec![7, 14, 50] });
753		assert_eq!(c.clone().div_unit(7), BigUint { digits: vec![2, 4, 14] });
754	}
755}