feanor_math/algorithms/
bigint_ops.rs

1use serde::de::{self, DeserializeSeed, Visitor};
2use serde::Deserializer;
3
4use crate::seq::*;
5
6use core::fmt;
7use std::cmp::{Ordering, min, max};
8use std::alloc::Allocator;
9
10type BlockInt = u64;
11type DoubleBlockInt = u128;
12const BLOCK_BITS: u32 = u64::BITS;
13
14fn expand<A: Allocator>(x: &mut Vec<BlockInt, A>, len: usize) {
15	if len > x.len() {
16		x.resize(len, 0)
17	}
18}
19
20#[cfg(test)]
21fn truncate_zeros(mut x: Vec<BlockInt>) -> Vec<BlockInt> {
22	x.truncate(x.len() - x.iter().rev().take_while(|a| **a == 0).count());
23	return x;
24}
25
26fn assign<A: Allocator>(x: &mut Vec<BlockInt, A>, rhs: &[BlockInt]) {
27    x.clear();
28    x.extend((0..rhs.len()).map(|i| rhs[i]))
29}
30
31#[stability::unstable(feature = "enable")]
32pub fn bigint_add<A: Allocator>(lhs: &mut Vec<BlockInt, A>, rhs: &[BlockInt], block_offset: usize) {
33	let prev_len = lhs.len();
34	let mut buffer: bool = false;
35	let mut i = 0;
36	if let Some(rhs_d) = highest_set_block(rhs) {
37		while i <= rhs_d || buffer {
38			let rhs_val = *rhs.get(i).unwrap_or(&0);
39			let j = i + block_offset;
40			expand(lhs, j + 1);
41			let (sum, overflow) = lhs[j].overflowing_add(rhs_val);
42			if buffer {
43				let (carry_sum, carry_overflow) = sum.overflowing_add(1);
44				*lhs.at_mut(j) = carry_sum;
45				buffer = overflow || carry_overflow;
46			} else {
47				*lhs.at_mut(j) = sum;
48				buffer = overflow;
49			}
50			i += 1;
51		}
52	}
53	let new_highest_set_block = highest_set_block(&lhs);
54	debug_assert!(new_highest_set_block.is_none() || max(prev_len, new_highest_set_block.unwrap() + 1) == lhs.len());
55}
56
57#[stability::unstable(feature = "enable")]
58pub fn highest_set_block(x: &[BlockInt]) -> Option<usize> {
59	for i in (0..x.len()).rev() {
60		if x[i] != 0 {
61			return Some(i);
62		}
63	}
64	return None;
65}
66
67#[stability::unstable(feature = "enable")]
68pub fn bigint_cmp(lhs: &[BlockInt], rhs: &[BlockInt]) -> Ordering {
69	match (highest_set_block(lhs.as_ref()), highest_set_block(rhs.as_ref())) {
70		(None, None) => return Ordering::Equal,
71		(Some(_), None) => return Ordering::Greater,
72		(None, Some(_)) => return Ordering::Less,
73		(Some(x), Some(y)) => match x.cmp(&y) {
74			Ordering::Less => return Ordering::Less,
75			Ordering::Greater => return Ordering::Greater,
76			Ordering::Equal => {
77				for i in (0..=x).rev() {
78					match lhs[i].cmp(&rhs[i]) {
79						Ordering::Less => return Ordering::Less,
80						Ordering::Greater => return Ordering::Greater,
81						_ => {}
82					}
83				}
84				return Ordering::Equal;
85			}
86		}
87	};
88}
89
90#[stability::unstable(feature = "enable")]
91pub fn bigint_cmp_small(lhs: &[BlockInt], rhs: DoubleBlockInt) -> Ordering {
92	match highest_set_block(lhs.as_ref()) {
93	   None => 0.cmp(&rhs),
94	   Some(0) => (lhs[0] as DoubleBlockInt).cmp(&rhs),
95	   Some(1) => (((lhs[1] as DoubleBlockInt) << BLOCK_BITS) | (lhs[0] as DoubleBlockInt)).cmp(&rhs),
96	   Some(_) => Ordering::Greater,
97	}
98}
99
100///
101/// Calculate lhs -= rhs * (1 << BLOCK_BITS)^block_offset
102/// 
103/// This will panic if the subtraction would result in a negative number
104/// 
105#[stability::unstable(feature = "enable")]
106pub fn bigint_sub(lhs: &mut [BlockInt], rhs: &[BlockInt], block_offset: usize) {
107	assert!(bigint_cmp(lhs.as_ref(), rhs.as_ref()) != Ordering::Less);
108
109	if let Some(rhs_high) = highest_set_block(rhs.as_ref()) {
110		let mut buffer: bool = false;
111		let mut i = 0;
112		while i <= rhs_high || buffer {
113			let rhs_val = *rhs.get(i).unwrap_or(&0);
114			let j = i + block_offset;
115			debug_assert!(j < lhs.len());
116			let (difference, overflow) = lhs[j].overflowing_sub(rhs_val);
117			if buffer {
118				let (carry_difference, carry_overflow) = difference.overflowing_sub(1);
119				lhs[j] = carry_difference;
120				buffer = overflow || carry_overflow;
121			} else {
122				lhs[j] = difference;
123				buffer = overflow;
124			}
125			i += 1;
126		}
127	}
128}
129
130///
131/// Calculate lhs = rhs - lhs
132/// 
133/// This will panic or give a wrong result if the subtraction would result in a negative number
134/// 
135#[stability::unstable(feature = "enable")]
136pub fn bigint_sub_self<A: Allocator>(lhs: &mut Vec<BlockInt, A>, rhs: &[BlockInt]) {
137	debug_assert!(bigint_cmp(lhs.as_ref(), rhs.as_ref()) != Ordering::Greater);
138
139	let rhs_high = highest_set_block(rhs.as_ref()).expect("rhs must be larger than lhs");
140	expand(lhs, rhs_high + 1);
141	let mut buffer: bool = false;
142	let mut i = 0;
143	while i <= rhs_high {
144		let (difference, overflow) = rhs[i].overflowing_sub(lhs[i]);
145		if buffer {
146			let (carry_difference, carry_overflow) = difference.overflowing_sub(1);
147			lhs[i] = carry_difference;
148			buffer = overflow || carry_overflow;
149		} else {
150			lhs[i] = difference;
151			buffer = overflow;
152		}
153		i += 1;
154	}
155	assert!(!buffer);
156}
157
158#[stability::unstable(feature = "enable")]
159pub fn bigint_lshift<A: Allocator>(lhs: &mut Vec<BlockInt, A>, power: usize) {
160	if let Some(high) = highest_set_block(&lhs) {
161		let mut buffer: BlockInt = 0;
162		let mut i = 0;
163		let in_block = (power % BlockInt::BITS as usize) as u32;
164		if in_block != 0 {
165			while i <= high || buffer != 0 {
166				expand(lhs, i + 1);
167				let tmp = lhs[i].overflowing_shr(BlockInt::BITS - in_block).0;
168				lhs[i] = (lhs[i] << in_block) | buffer;
169				buffer = tmp;
170				i += 1;
171			}
172		}
173		lhs.reverse();
174		lhs.extend((0..(power / BlockInt::BITS as usize)).map(|_| 0));
175		lhs.reverse();
176	}
177}
178
179#[stability::unstable(feature = "enable")]
180pub fn bigint_rshift(lhs: &mut [BlockInt], power: usize) {
181	if let Some(high) = highest_set_block(lhs) {
182		let mut buffer: BlockInt = 0;
183		let in_block = (power % BlockInt::BITS as usize) as u32;
184		let mut i = high as isize;
185		if in_block != 0 {
186			while i >= 0 {
187				let tmp = lhs[i as usize].overflowing_shl(BlockInt::BITS - in_block).0;
188				lhs[i as usize] = (lhs[i as usize] >> in_block) | buffer;
189				buffer = tmp;
190				i -= 1;
191			}
192		}
193		let blocks = power / BlockInt::BITS as usize;
194		if blocks != 0 {
195			for i in 0..min(blocks, lhs.len()) {
196				lhs[i] = 0;
197			}
198			for i in blocks..=high {
199				lhs[i - blocks] = lhs[i];
200				lhs[i] = 0;
201			}
202		}
203	}
204}
205
206#[stability::unstable(feature = "enable")]
207pub fn bigint_fma<A: Allocator, A2: Allocator>(lhs: &[BlockInt], rhs: &[BlockInt], mut out: Vec<BlockInt, A>, scratch_alloc: A2) -> Vec<BlockInt, A> {
208	let prev_len = highest_set_block(&out).map(|x| x + 1).unwrap_or(0);
209	let new_len = max(prev_len + 1, highest_set_block(lhs.as_ref()).and_then(|lb| highest_set_block(rhs.as_ref()).map(|rb| lb + rb + 2)).unwrap_or(0));
210	out.resize(new_len, 0);
211	if let Some(d) = highest_set_block(rhs.as_ref()) {
212		let mut val = Vec::new_in(scratch_alloc);
213		for i in 0..=d {
214			assign(&mut val, lhs.as_ref());
215			bigint_mul_small(&mut val, rhs[i]);
216			bigint_add(&mut out, val.as_ref(), i);
217		}
218	}
219	debug_assert!(highest_set_block(&out).is_none() || highest_set_block(&out).unwrap() as isize >= out.len() as isize - 2);
220	return out;
221}
222
223///
224/// Complexity O(log(n))
225/// 
226#[stability::unstable(feature = "enable")]
227pub fn bigint_mul_small<A: Allocator>(lhs: &mut Vec<BlockInt, A>, factor: BlockInt) {
228	if let Some(d) = highest_set_block(lhs.as_ref()) {
229		let mut buffer: u64 = 0;
230		for i in 0..=d {
231			let prod = lhs[i] as u128 * factor as u128 + buffer as u128;
232			*lhs.at_mut(i) = (prod & ((1u128 << BLOCK_BITS) - 1)) as u64;
233			buffer = (prod >> BLOCK_BITS) as u64;
234		}
235		expand(lhs, d + 2);
236		*lhs.at_mut(d + 1) = buffer;
237	}
238}
239
240#[stability::unstable(feature = "enable")]
241pub fn bigint_add_small<A: Allocator>(lhs: &mut Vec<BlockInt, A>, rhs: BlockInt) {
242	if lhs.len() > 0 {
243		let (sum, mut buffer) = lhs[0].overflowing_add(rhs);
244		*lhs.at_mut(0) = sum;
245		let mut i = 1;
246		while buffer {
247			expand(lhs, i + 1);
248			let (sum, overflow) = lhs[i].overflowing_add(1);
249			buffer = overflow;
250			*lhs.at_mut(i) = sum;
251			i += 1;
252		}
253	} else {
254		expand(lhs, 1);
255		*lhs.at_mut(0) = rhs;
256	}
257}
258
259///
260/// Same as division_step, but for self_high == rhs_high == d
261/// 
262fn division_step_last<A: Allocator>(lhs: &mut [BlockInt], rhs: &[BlockInt], d: usize, tmp: &mut Vec<BlockInt, A>) -> u64 {
263	assert!(lhs[d] != 0);
264	assert!(rhs[d] != 0);
265
266	let self_high_blocks: u128 = ((lhs[d] as u128) << BLOCK_BITS) | (lhs[d - 1] as u128);
267	let rhs_high_blocks: u128 = ((rhs[d] as u128) << BLOCK_BITS) | (rhs[d - 1] as u128);
268
269	if rhs_high_blocks == u128::MAX {
270		if bigint_cmp(lhs, rhs) != Ordering::Less {
271			bigint_sub(lhs, rhs, 0);
272			return 1;
273		} else {
274			return 0;
275		}
276	} else {
277		let mut quotient = (self_high_blocks / (rhs_high_blocks + 1)) as u64;
278		assign(tmp, rhs.as_ref());
279		bigint_mul_small(tmp, quotient);
280		bigint_sub(lhs, tmp.as_ref(), 0);
281
282		if bigint_cmp(lhs.as_ref(), rhs.as_ref()) != Ordering::Less {
283			bigint_sub(lhs, rhs.as_ref(), 0);
284			quotient += 1;
285		}
286		if bigint_cmp(lhs.as_ref(), rhs.as_ref()) != Ordering::Less {
287			bigint_sub(lhs, rhs.as_ref(), 0);
288			quotient += 1;
289		}
290		
291		debug_assert!(bigint_cmp(lhs.as_ref(), rhs) == Ordering::Less);
292		return quotient;
293	}
294}
295
296///
297/// Finds some integer d such that subtracting d * rhs from self clears the top
298/// block of self. self will be assigned the value after the subtraction and d
299/// will be returned as d = (u * 2 ^ block_bits + l) * 2 ^ (k * block_bits) 
300/// where the return value is (u, l, k)
301/// 
302/// Complexity O(log(n))
303/// 
304fn division_step<A: Allocator>(
305	lhs: &mut [BlockInt], 
306	rhs: &[BlockInt], 
307	lhs_high: usize, 
308	rhs_high: usize, 
309	tmp: &mut Vec<BlockInt, A>
310) -> (u64, u64, usize) {
311	assert!(lhs_high > rhs_high);
312	assert!(lhs[lhs_high] != 0);
313	assert!(rhs[rhs_high] != 0);
314
315	// the basic idea is as follows:
316	// we know that for a and b, have a - a//(b+1) * b <= b + a/(b+1)
317	// Hence, we perform two steps:
318	//  - by choosing a and b as the top two blocks of lhs resp. lhs, achieve that a - a//(b+1) * b <= b + 2^k
319	//    (where k = BLOCK_BITS); hence, lhs - a//(b+1) * rhs <= rhs + 2^k, and so possibly subtracting rhs
320	//    achieves new_lhs <= rhs
321	//  - by choosing a as the top two blocks and b as only the top block of lhs resp. lhs (now b < 2^k), achieve that
322	//    lhs - a//(b+1) * rhs < 2^k + 2^k = 2 * 2^k, and so after possibly subtracting rhs we find
323	//    that the top block of lhs is cleared
324
325	let mut result_upper = 0;
326	let mut result_lower = 0;
327
328	// first step
329	{
330		let lhs_high_blocks = ((lhs[lhs_high] as DoubleBlockInt) << BLOCK_BITS) | (lhs[lhs_high - 1] as DoubleBlockInt);
331		let rhs_high_blocks = ((rhs[rhs_high] as DoubleBlockInt) << BLOCK_BITS) | (rhs[rhs_high - 1] as DoubleBlockInt);
332
333		if rhs_high_blocks != DoubleBlockInt::MAX && lhs_high_blocks >= (rhs_high_blocks + 1) {
334			let mut quotient = (lhs_high_blocks / (rhs_high_blocks + 1)) as u64;
335			debug_assert!(quotient != 0);
336			assign(tmp, rhs.as_ref());
337			bigint_mul_small(tmp, quotient);
338			bigint_sub(lhs, tmp.as_ref(), lhs_high - rhs_high);
339
340			let lhs_high_blocks = ((lhs[lhs_high] as DoubleBlockInt) << BLOCK_BITS) | (lhs[lhs_high - 1] as DoubleBlockInt);
341
342			if lhs_high_blocks > rhs_high_blocks {
343				bigint_sub(lhs, rhs.as_ref(), lhs_high - rhs_high);
344				quotient += 1;
345			}
346			result_upper = quotient;
347		}
348
349		// this is what we wanted to achieve in the first step
350		let lhs_high_blocks = ((lhs[lhs_high] as DoubleBlockInt) << BLOCK_BITS) | (lhs[lhs_high - 1] as DoubleBlockInt);
351		debug_assert!(lhs_high_blocks <= rhs_high_blocks);
352	}
353
354	// second step
355	{
356		let lhs_high_blocks = ((lhs[lhs_high] as DoubleBlockInt) << BLOCK_BITS) | (lhs[lhs_high - 1] as DoubleBlockInt);
357		let rhs_high_block = rhs[rhs_high] as DoubleBlockInt;
358
359		if lhs[lhs_high] != 0 {
360			let mut quotient = (lhs_high_blocks / (rhs_high_block + 1)) as BlockInt;
361			assign(tmp, rhs.as_ref());
362			bigint_mul_small(tmp, quotient);
363			bigint_sub(lhs, tmp.as_ref(), lhs_high - rhs_high - 1);
364
365			if lhs[lhs_high] != 0 {
366				bigint_sub(lhs, rhs.as_ref(), lhs_high - rhs_high - 1);
367				quotient += 1;
368			}
369			result_lower = quotient;
370		}
371
372		debug_assert!(lhs[lhs_high] == 0);
373	}
374	return (result_upper, result_lower, lhs_high - rhs_high - 1);
375}
376
377///
378/// Calculates abs(self) = abs(self) % abs(rhs) and returns the quotient
379/// of the division abs(self) / abs(rhs). The sign bit of self is ignored
380/// and left unchanged.
381/// 
382/// Complexity O(log(n)^2)
383/// 
384#[stability::unstable(feature = "enable")]
385pub fn bigint_div<A: Allocator, A2: Allocator>(lhs: &mut [BlockInt], rhs: &[BlockInt], mut out: Vec<BlockInt, A>, scratch_alloc: A2) -> Vec<BlockInt, A> {
386	assert!(highest_set_block(rhs.as_ref()).is_some());
387	
388	out.clear();
389	match (highest_set_block(lhs), highest_set_block(rhs)) {
390		(_, None) => panic!("division by zero"),
391		(None, Some(_)) => return out,
392		(Some(d), Some(k)) if d < k => return out,
393		(Some(d), Some(k)) if k == 0 => {
394			let rem = bigint_div_small(lhs, rhs[0]);
395			for i in 0..=d {
396				out.push(lhs[i]);
397				lhs[i] = 0;
398			}
399			lhs[0] = rem;
400			return out;
401		},
402		(Some(mut d), Some(k)) => {
403			let mut tmp = Vec::new_in(scratch_alloc);
404			expand(&mut out, d - k + 1);
405			while d > k {
406				if lhs[d] != 0 {
407					let (quo_upper, quo_lower, quo_power) = division_step(lhs, rhs.as_ref(), d, k, &mut tmp);
408					*out.at_mut(quo_power) = quo_lower;
409					bigint_add(&mut out, &[quo_upper][..], quo_power + 1);
410					debug_assert!(lhs[d] == 0);
411				}
412				d -= 1;
413			}
414			let quo = if lhs[d] != 0 {
415				division_step_last(lhs, rhs, d, &mut tmp)
416			} else {
417				0
418			};
419			bigint_add(&mut out, &[quo], 0);
420			return out;
421		}
422	}
423}
424
425///
426/// Calculates self /= divisor and returns the remainder of the division.
427/// 
428#[stability::unstable(feature = "enable")]
429pub fn bigint_div_small(lhs: &mut [BlockInt], rhs: BlockInt) -> BlockInt {
430	assert!(rhs != 0);
431	let highest_block_opt = highest_set_block(lhs.as_ref());
432	if highest_block_opt == Some(0) {
433		let (quo, rem) = (lhs[0] / rhs, lhs[0] % rhs);
434		*lhs.at_mut(0) = quo;
435		return rem;
436	} else if let Some(highest_block) = highest_block_opt {
437		let (quo, rem) = (lhs[highest_block] / rhs, lhs[highest_block] % rhs);
438		let mut buffer = rem as DoubleBlockInt;
439		*lhs.at_mut(highest_block) = quo;
440		for i in (0..highest_block).rev() {
441			buffer = (buffer << BLOCK_BITS) | (lhs[i] as DoubleBlockInt);
442			let (quo, rem) = (buffer / rhs as DoubleBlockInt, buffer % rhs as DoubleBlockInt);
443			debug_assert!(quo <= BlockInt::MAX as DoubleBlockInt);
444			*lhs.at_mut(i) = quo as BlockInt;
445			buffer = rem;
446		}
447		return buffer as BlockInt;
448	} else {
449		return 0;
450	}
451}
452
453///
454/// Deserializes a 2-element tuple, consisting of a sign bit and a list of bytes
455/// in little endian order to represent a number.
456/// The list of bytes is converted into a `T` by the given closure, and the resulting
457/// tuple is returned.
458/// 
459/// The main difference between using this function and `<(bool, &serde_bytes::Bytes)>::deserialize`
460/// is that this function can accept a byte array with a shorter lifetime.
461/// 
462#[stability::unstable(feature = "enable")]
463pub fn deserialize_bigint_from_bytes<'de, D, F, T>(deserializer: D, from_bytes: F) -> Result<(bool, T), D::Error>
464	where D: Deserializer<'de>,
465		F: FnOnce(&[u8]) -> T
466{
467	struct ResultVisitor<F, T>
468		where F: FnOnce(&[u8]) -> T
469	{
470		from_bytes: F
471	}
472	impl<'de, F, T> Visitor<'de> for ResultVisitor<F, T>
473		where F: FnOnce(&[u8]) -> T
474	{
475		type Value = (bool, T);
476
477		fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
478			write!(f, "a sign bit as `bool` and a list of bytes in little endian order")
479		}
480
481        fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
482            where A: serde::de::SeqAccess<'de>
483        {
484			let is_negative = seq.next_element()?;
485			if is_negative.is_none() {
486				return Err(de::Error::invalid_length(0, &"expected a sign bit as `bool`" as &'static dyn de::Expected));
487			}
488			let is_negative: bool = is_negative.unwrap();
489
490			struct BytesVisitor<F, T>
491				where F: FnOnce(&[u8]) -> T
492			{
493				from_bytes: F
494			}
495			impl<'de, F, T> Visitor<'de> for BytesVisitor<F, T>
496				where F: FnOnce(&[u8]) -> T
497			{
498				type Value = T;
499
500				fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
501					write!(f, "a list of bytes in little endian order")
502				}
503
504				fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
505					where E: de::Error,
506				{
507					Ok((self.from_bytes)(v))
508				}
509			}
510			struct DeserializeBytes<F, T>
511				where F: FnOnce(&[u8]) -> T
512			{
513				from_bytes: F
514			}
515			impl<'de, F, T> DeserializeSeed<'de> for DeserializeBytes<F, T>
516				where F: FnOnce(&[u8]) -> T
517			{
518				type Value = T;
519
520				fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
521					where D: Deserializer<'de>
522				{
523					deserializer.deserialize_bytes(BytesVisitor { from_bytes: self.from_bytes })
524				}
525			}
526
527			let data = seq.next_element_seed(DeserializeBytes { from_bytes: self.from_bytes })?;
528			if data.is_none() {
529				return Err(de::Error::invalid_length(1, &"expected a representation of the number as list of little endian bytes" as &'static dyn de::Expected));
530			}
531			let data: T = data.unwrap();
532
533            return Ok((is_negative, data));
534        }
535	}
536	return deserializer.deserialize_tuple(2, ResultVisitor { from_bytes: from_bytes });
537}
538
539#[cfg(test)]
540use std::alloc::Global;
541
542#[cfg(test)]
543fn parse(s: &str, base: u32) -> Vec<BlockInt> {
544    use crate::rings::rust_bigint::RustBigintRing;
545	use crate::integer::*;
546	use crate::ring::*;
547
548	truncate_zeros(RustBigintRing::RING.get_ring().abs_base_u64_repr(&RustBigintRing::RING.parse(s, base).unwrap()).collect::<Vec<_>>())
549}
550
551#[test]
552fn test_sub() {
553    let mut x = parse("923645871236598172365987287530543", 10);
554    let y = parse("58430657823473456743684735863478", 10);
555    let z = parse("865215213413124715622302551667065", 10);
556    bigint_sub(&mut x, &y, 0);
557    assert_eq!(truncate_zeros(z), truncate_zeros(x));
558
559    let x = parse("4294836225", 10);
560    let mut y = parse("4294967297", 10);
561    let z = parse("131072", 10);
562    bigint_sub(&mut y, &x, 0);
563    assert_eq!(truncate_zeros(y), truncate_zeros(z));
564}
565
566#[test]
567fn test_sub_with_carry() {
568    let mut x = parse("1000000000000000000", 16);
569    let y = parse("FFFFFFFFFFFFFFFF00", 16);
570    bigint_sub(&mut x, &y, 0);
571    assert_eq!(vec![256], truncate_zeros(x));
572}
573
574#[test]
575fn test_add() {
576    let mut x = parse("923645871236598172365987287530543", 10);
577    let y = parse("58430657823473456743684735863478", 10);
578    let z = parse("982076529060071629109672023394021", 10);
579    bigint_add(&mut x, &y, 0);
580    assert_eq!(truncate_zeros(z), truncate_zeros(x));
581}
582
583#[test]
584fn test_add_with_carry() {
585    let mut x = parse("1BC00000000000000BC", 16);
586    let y =  parse("FFFFFFFFFFFFFFFF0000000000000000BC", 16);
587    let z = parse("10000000000000000BC0000000000000178", 16);
588    bigint_add(&mut x, &y, 0);
589    assert_eq!(truncate_zeros(z), truncate_zeros(x));
590}
591
592#[test]
593fn test_mul() {
594    let x = parse("57873674586797895671345345", 10);
595    let y = parse("21308561789045691782534873921650342768903561413264128756389247568729346542359871235465", 10);
596    let z = parse("1233204770891906354921751949503652431220138020953161094405729272872607166072371117664593787957056214903826660425", 10);
597    assert_eq!(truncate_zeros(z), truncate_zeros(bigint_fma(&x, &y, Vec::new(), Global)));
598}
599
600#[test]
601fn test_fma() {
602    let x = parse("543929578293075482904560982347609823468792", 10);
603    let y = parse("598147578092315980234089723484389243859743", 10);
604    let a = parse("98734435342", 10);
605    let z = parse("325350159908777866468983871740437853305599423427707736569559476320508903561720075798", 10);
606    assert_eq!(truncate_zeros(z), truncate_zeros(bigint_fma(&x, &y, a, Global)));
607}
608
609#[test]
610fn test_div_no_remainder() {
611    let mut x = parse("578435387FF0582367863200000000000000000000", 16);
612    let y = parse("200000000000000000000", 16);
613    let z = parse("2BC21A9C3FF82C11B3C319", 16);
614    let quotient = bigint_div(&mut x, &y, Vec::new(), Global);
615    assert_eq!(Vec::<BlockInt>::new(), truncate_zeros(x));
616    assert_eq!(truncate_zeros(z), truncate_zeros(quotient));
617}
618
619#[test]
620fn test_div_with_remainder() {
621    let mut x = parse("578435387FF0582367863200000000007651437856", 16);
622    let y = parse("200000000000000000000", 16);
623    let z = parse("2BC21A9C3FF82C11B3C319", 16);
624    let r = parse("7651437856", 16);
625    let quotient = bigint_div(&mut x, &y, Vec::new(), Global);
626    assert_eq!(truncate_zeros(r), truncate_zeros(x));
627    assert_eq!(truncate_zeros(z), truncate_zeros(quotient));
628}
629
630#[test]
631fn test_div_big() {
632    let mut x = parse("581239456149785691238569872349872348569871269871234657986123987237865847935698734296434575367565723846982523852347", 10);
633    let y = parse("903852718907268716125180964783634518356783568793426834569872365791233387356325", 10);
634    let q = parse("643068769934649368349591185247155725", 10);
635    let r = parse("265234469040774335115597728873888165088018116561138613092906563355599185141722", 10);
636    let actual = bigint_div(&mut x, &y, Vec::new(), Global);
637    assert_eq!(truncate_zeros(r), truncate_zeros(x));
638    assert_eq!(truncate_zeros(q), truncate_zeros(actual));
639
640	let mut x = vec![0, 0, 0, 0, 1];
641	let y = parse("170141183460469231731687303715884105727", 10);
642	let q = parse("680564733841876926926749214863536422916", 10);
643	let r = vec![4];
644	let actual = bigint_div(&mut x, &y, Vec::new(), Global);
645	assert_eq!(truncate_zeros(r), truncate_zeros(x));
646    assert_eq!(truncate_zeros(q), truncate_zeros(actual));
647}
648
649#[test]
650fn test_div_last_block_overflow() {
651    let mut x = parse("3227812347608635737069898965003764842912132241036529391038324195675809527521051493287056691600172289294878964965934366720", 10);
652    let y = parse("302231454903657293676544", 10);
653    let q = parse("10679935179604550411975108530847760573013522611783263849735208039111098628903202750114810434682880", 10);
654    let quotient = bigint_div(&mut x, &y, Vec::new(), Global);
655    assert_eq!(truncate_zeros(q), truncate_zeros(quotient));
656    assert_eq!(Vec::<BlockInt>::new(), truncate_zeros(x));
657}
658
659#[test]
660fn test_div_small() {
661    let mut x = parse("891023591340178345678931246518793456983745682137459364598623489512389745698237456890239238476873429872346579", 10);
662    let q = parse("255380794307875708133829534685810678413226048190730686328066348384175908769916152734376393945793473738133", 10);
663    _ = bigint_div_small(&mut x, 3489);
664    assert_eq!(truncate_zeros(q), truncate_zeros(x));
665}
666
667#[test]
668fn test_bigint_rshift() {
669    let mut x = parse("9843a756781b34567f81394", 16);
670    let z = parse("9843a756781b34567", 16);
671	bigint_rshift(&mut x, 24);
672    assert_eq!(truncate_zeros(x), truncate_zeros(z));
673
674    let mut x = parse("9843a756781b34567f81394", 16);
675	bigint_rshift(&mut x, 1000);
676    assert_eq!(truncate_zeros(x), Vec::<u64>::new());
677}
678
679#[test]
680fn test_bigint_lshift() {
681    let mut x = parse("2", 10);
682	bigint_lshift(&mut x, 0);
683    assert_eq!(parse("2", 10), truncate_zeros(x));
684
685    let mut x = parse("4829192", 10);
686	bigint_lshift(&mut x, 3);
687    assert_eq!(parse("38633536", 10), truncate_zeros(x));
688
689    let mut x = parse("4829192", 10);
690	bigint_lshift(&mut x, 64);
691    assert_eq!(parse("89082868906805576987574272", 10), truncate_zeros(x));
692}