diff --git a/.gitignore b/.gitignore
index ad67955..9a850e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,4 @@ target
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
+.DS_Store
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..d610d6a
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,25 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "autocfg"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "rust_big_int"
+version = "0.1.0"
+dependencies = [
+ "num-traits",
+]
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..0b33848
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "rust_big_int"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+num-traits = { version = "0.2.19", features = ["i128"] }
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..9a7579f
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 Adam Sedláček
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e629a75
--- /dev/null
+++ b/README.md
@@ -0,0 +1,148 @@
+# RustBigInt
+
+BigInt written in Rust.
+
+## Description
+
+My own implementation of BigInt (type of integer with unlimited size) as project to learn Rust.
+
+## Example
+
+```rs
+use RustBigInt::BigInt;
+use std::str::FromStr;
+
+//from
+let x: BigInt = 66.into();
+let y: BigInt = BigInt::from(34);
+let z: BigInt = BigInt::from_str("999999").unwrap();
+
+//tryInto
+let x: BigInt = 32.into();
+let x_num: i32 = x.try_into.unwrap();
+assert_eq!(32, x_num);
+
+let y: BigInt = i16:MAX.into();
+let y_num: i8 = y.try_into();
+assert!(y_num.is_err());
+
+//Display
+let x: BigInt = BigInt::from(1003);
+assert_eq!(format!("Number is: {x}"), "Number is: 1003");
+assert_eq!(format!("Number is: {x:0^11}"), "Number is: 00010030000");
+assert_eq!(format!("Number is: {x:0>10}"), "Number is: 0000001003");
+assert_eq!(format!("Number is: {x:0<10}"), "Number is: 1003000000");
+assert_eq!(format!("Number is: {x:->10}"), "Number is: ------1003");
+assert_eq!(format!("Number is: {x:9}"), "Number is: 1003");
+
+//Binary
+let x: BigInt = BigInt::from(11);
+assert_eq!(format!("{x:#b}"), "0b1011");
+assert_eq!(format!("{x:b}"), "1011");
+assert_eq!(format!("{x:0^11b}"), "00010110000");
+
+
+//Hexadecimal
+let x: BigInt = BigInt::from(11);
+assert_eq!(format!("{x:x}"), "a");
+assert_eq!(format!("{x:X}"), "A");
+assert_eq!(format!("{x:#X}"), "0xA");
+assert_eq!(format!("{x:0^11X}"), "00000A00000");
+
+let x: BigInt = BigInt::from(20);
+assert_eq!(x.to_words(), "two zero");
+
+//Math operations
+let x: BigInt = BigInt::from(66);
+let y: BigInt = BigInt::from(34);
+assert!(x != y);
+assert_eq!(x + y, 100);
+assert_eq!(x - y, 32);
+assert_eq!(x * y, 2244);
+assert_eq!(x / y, 1);
+assert_eq!(x % y, 32);
+assert_eq!(x.pow(2), 4356);
+
+//Binary operations
+let x: BigInt = 11; //Ob1011
+let y: BigInt = 6; //Ob0110
+assert_eq!(x & y, 2); //0b0010
+assert_eq!(x | y, 15); //0b1111
+assert_eq!(x ^ y, 13); //0b1101
+assert_eq!(x >> 2, 2) //0b10
+assert_eq!(x << 2, 44) //0b101100
+```
+
+## All implemented traits and functions
+
+
+From and Into traits
+
+- Default
+- New
+- FromStr
+- From
+- TryInto
+
+
+
+
+ Display traits
+
+- Display
+- Binary
+- UpperHex
+- LowerHex
+- to_words
+
+
+
+ Comparing traits
+
+- PartialEq
+- PartialOrd
+
+
+
+ Math traits
+
+- Neg (-)
+- Add (+)
+- AddAssign(+=)
+- Sub (-)
+- SubAssign (-=)
+- Mul (*)
+- MulAssign (*=)
+- Div (/)
+- DivAssign (/=)
+- Rem (%)
+- RemAssign (%=)
+- Pow
+
+
+
+
+ Bit operation traits
+
+- BitAnd (&)
+- BitAndAssign (&=)
+- BitOr (|)
+- BitOrAssign (|=)
+- BitXor (^)
+- BitXorAssign (^=)
+- Shl (<<)
+- ShlAssign (<<=)
+- Shr (>>)
+- ShrAssign (>>=)
+
+
+
+## Acknowledgments
+
+Special thanks to [magnusi](https://github.com/luciusmagn) for leading me throughout this project.
+
+## License
+
+Project is licensed under the MIT license. See the LICENSE file for more info.
+
+Adam Sedláček, 2025 (C)
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..7973e05
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,1137 @@
+use num_traits::{Pow, ToPrimitive, Zero};
+
+use std::cmp::Ordering;
+use std::error::Error;
+use std::fmt::{self, Alignment, Binary, Display, LowerHex, UpperHex};
+use std::ops::*;
+use std::str::FromStr;
+
+#[derive(Debug)]
+pub enum BigIntError {
+ NaN,
+ LargeNumber,
+}
+
+impl Error for BigIntError {}
+
+impl Display for BigIntError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ BigIntError::NaN => write!(f, "Not a Number"),
+ BigIntError::LargeNumber => write!(f, "Too large"),
+ }
+ }
+}
+
+#[derive(Clone, Eq, Debug)]
+pub struct BigInt {
+ positive: bool,
+ numbers: Vec,
+}
+
+impl Default for BigInt {
+ fn default() -> Self {
+ BigInt {
+ positive: true,
+ numbers: vec![0],
+ }
+ }
+}
+
+impl FromStr for BigInt {
+ type Err = BigIntError;
+ fn from_str(string_of_numbers: &str) -> Result {
+ let original = string_of_numbers;
+
+ //empty string edgecaase
+ if string_of_numbers.is_empty() {
+ return Err(BigIntError::NaN);
+ }
+
+ let mut positive = !(string_of_numbers.starts_with('-'));
+ let mut numbers: Vec = Vec::new();
+
+ //if negative - remove '-'
+ let string_of_numbers = &string_of_numbers[!positive as usize..];
+
+ for char in string_of_numbers.chars() {
+ if !char.is_ascii_digit() {
+ return BigInt::parse_word_digits(if positive {
+ string_of_numbers
+ } else {
+ original
+ });
+ }
+
+ numbers.push(char.to_digit(10).unwrap().to_u8().unwrap());
+ }
+
+ if numbers.as_slice() == [0] {
+ positive = true;
+ }
+
+ Ok(BigInt { positive, numbers })
+ }
+}
+
+macro_rules! from_int {
+ ($($t:ty),*)=>{
+ $(
+ impl From<$t> for BigInt{
+ fn from(mut original_number: $t) -> Self {
+
+ //zero edgecase
+ if original_number == 0 {
+ return BigInt::default();
+ }
+
+ let mut numbers = Vec::new();
+ let positive = !(original_number < 0);
+
+ //negative number
+ if original_number < 0 {
+ original_number = -original_number;
+ }
+
+ //transformation of digits
+ while original_number != 0{
+ numbers.push((original_number % 10).to_u8().unwrap());
+ original_number /= 10;
+ }
+
+ numbers.reverse();
+
+ //return value
+ BigInt {positive, numbers}
+
+ }
+ }
+ )*
+ }
+}
+
+macro_rules! from_uint {
+ ($($t:ty),*)=>{
+ $(
+ impl From<$t> for BigInt{
+ fn from(mut original_number: $t) -> Self {
+
+ //zero edgecase
+ if original_number == 0 {
+ return BigInt::default();
+ }
+
+ let mut numbers = Vec::new();
+
+ //transformation of digits
+ while original_number != 0{
+ numbers.push((original_number % 10).to_u8().unwrap());
+ original_number /= 10;
+ }
+
+ numbers.reverse();
+
+ //return value
+ BigInt {
+ positive: true, numbers}
+
+ }
+ }
+ )*
+ }
+}
+
+from_int!(i8, i16, i32, i64, i128);
+from_uint!(u8, u16, u32, u64, u128);
+
+macro_rules! try_into_uint {
+ ($($t:ty),*) => {
+ $(impl TryInto<$t> for BigInt{
+ type Error = BigIntError;
+ fn try_into(self) -> Result<$t, Self::Error> {
+
+ if self > <$t>::MAX {
+ return Err(BigIntError::LargeNumber);
+ }
+ if self == 0 {
+ return Ok(0 as $t);
+ }
+
+ let mut result: $t = 0;
+
+ for (position, number) in self.numbers.iter().rev().enumerate() {
+ result += BigInt::create_new_digit(position, number) as $t;
+ }
+
+ Ok(result)
+ }
+ })*
+
+ };
+}
+
+macro_rules! try_into_int {
+ ($($t:ty),*) => {
+ $(impl TryInto<$t> for BigInt{
+ type Error = BigIntError;
+ fn try_into(self) -> Result<$t, Self::Error> {
+
+ if self > <$t>::MAX {
+ return Err(BigIntError::LargeNumber);
+ }
+ if self == 0 {
+ return Ok(0 as $t);
+ }
+
+ let mut result: $t = 0;
+
+ for (position, number) in self.numbers.iter().rev().enumerate() {
+ result += BigInt::create_new_digit(position, number) as $t;
+ }
+
+ if !self.positive {
+ result *= -1;
+ }
+
+
+ Ok(result)
+ }
+ })*
+
+ };
+}
+
+try_into_uint!(u8, u16, u32, u64, u128);
+try_into_int!(i8, i16, i32, i64, i128);
+
+impl Display for BigInt {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let mut output = String::new();
+
+ if !self.positive {
+ output.push('-');
+ }
+ if f.sign_plus() && self.positive {
+ output.push('+');
+ }
+
+ for digit in &self.numbers {
+ output.push_str(&digit.to_string());
+ }
+
+ BigInt::add_alignment(&mut output, f);
+
+ write!(f, "{output}")?;
+
+ Ok(())
+ }
+}
+
+impl Binary for BigInt {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let (positive, binary) = self.to_binary();
+ let mut output = String::new();
+
+ if !positive {
+ output.push('-');
+ }
+ if f.sign_plus() && positive {
+ output.push('+');
+ }
+
+ if f.alternate() {
+ output.push_str("0b");
+ }
+
+ for bit in binary {
+ if bit {
+ output.push('1');
+ } else {
+ output.push('0');
+ }
+ }
+
+ BigInt::add_alignment(&mut output, f);
+
+ write!(f, "{output}")?;
+
+ Ok(())
+ }
+}
+
+impl UpperHex for BigInt {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let output = self.create_hexa_string(f, true);
+
+ write!(f, "{output}")?;
+
+ Ok(())
+ }
+}
+
+impl LowerHex for BigInt {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let output = self.create_hexa_string(f, false);
+
+ write!(f, "{output}")?;
+
+ Ok(())
+ }
+}
+
+impl PartialEq for BigInt {
+ fn eq(&self, other: &BigInt) -> bool {
+ if self.positive != other.positive {
+ false
+ } else {
+ self.numbers == other.numbers
+ }
+ }
+}
+
+macro_rules! eq_with_int {
+ ($($t:ty),*) => {
+ $(
+ impl PartialEq<$t> for BigInt{
+ fn eq(&self, other: &$t) -> bool {
+ self == &BigInt::from(*other)
+ }
+ }
+ )*
+ };
+}
+
+eq_with_int!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
+
+impl PartialEq<&str> for BigInt {
+ fn eq(&self, other: &&str) -> bool {
+ match BigInt::from_str(other) {
+ Ok(right) => self == &right,
+ Err(_) => false,
+ }
+ }
+}
+
+impl Neg for BigInt {
+ type Output = Self;
+ fn neg(mut self) -> Self::Output {
+ if self != 0 {
+ self.positive = !self.positive;
+ }
+ self
+ }
+}
+
+macro_rules! partial_ord_intieger {
+ ($($t:ty),*) => {
+ $(
+ impl PartialOrd<$t> for BigInt{
+ fn partial_cmp(&self, other: &$t) -> Option {
+ return self.partial_cmp(&BigInt::from(*other));
+ }
+ }
+ )*
+ };
+}
+
+partial_ord_intieger!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
+
+impl PartialOrd for BigInt {
+ fn partial_cmp(&self, other: &Self) -> Option {
+ if self == other {
+ return Some(Ordering::Equal);
+ }
+
+ let mut greater = false;
+
+ //check +/-
+ if self.positive != other.positive {
+ greater = self.positive;
+ }
+ //check length
+ else if self.numbers.len() != other.numbers.len() {
+ if self.positive {
+ greater = self.numbers.len() > other.numbers.len();
+ } else {
+ greater = self.numbers.len() < other.numbers.len();
+ }
+ }
+ //compare digits
+ else {
+ let numbers_iterator = self.numbers.iter().zip(other.numbers.iter());
+
+ for (left, right) in numbers_iterator {
+ if left != right {
+ greater = left > right;
+ break;
+ }
+ }
+
+ if !self.positive {
+ greater = !greater;
+ }
+ }
+
+ //return value
+ if greater {
+ Some(Ordering::Greater)
+ } else {
+ Some(Ordering::Less)
+ }
+ }
+}
+
+impl PartialOrd<&str> for BigInt {
+ fn partial_cmp(&self, other: &&str) -> Option {
+ let other = BigInt::from_str(other);
+
+ if other.is_err() {
+ return None;
+ }
+
+ self.partial_cmp(&other.unwrap())
+ }
+}
+
+macro_rules! assign_trait {
+ ($trait:ident, $function:ident, $operation:ident) => {
+ impl $trait for BigInt
+ where
+ T: Into,
+ {
+ fn $function(&mut self, rhs: T) {
+ *self = self.clone().$operation(rhs);
+ }
+ }
+ };
+}
+
+impl Add for BigInt
+where
+ T: Into,
+{
+ type Output = Self;
+ fn add(self, rhs: T) -> Self::Output {
+ let right: BigInt = rhs.into();
+
+ // X + 0 edgecase
+ if self == 0 {
+ return right;
+ }
+ if right == 0 {
+ return self;
+ }
+
+ // negative numbers edgecases
+ if !self.positive && right.positive {
+ // -X + Y => Y - X => -(X - Y)
+ //self.positive = true;
+ return right - (-self);
+ } else if self.positive && !right.positive {
+ //X - Y
+ //right.positive = true;
+ return self - (-right);
+ }
+
+ let mut result = BigInt {
+ positive: self.positive,
+ numbers: vec![],
+ };
+
+ let (longer, shorter) = BigInt::equalize_vectors_length(self.numbers, right.numbers);
+
+ let numbers_set = longer.iter().zip(shorter.iter());
+
+ let mut new_number;
+ let mut carry: u8 = 0;
+
+ for number_set in numbers_set {
+ new_number = 0;
+
+ new_number += number_set.0;
+ new_number += number_set.1;
+ new_number += carry;
+
+ let new_digit = new_number % 10;
+ carry = new_number / 10;
+
+ result.numbers.push(new_digit);
+ }
+
+ if carry != 0 {
+ result.numbers.push(carry);
+ }
+
+ result.numbers.reverse();
+
+ result
+ }
+}
+
+assign_trait!(AddAssign, add_assign, add);
+
+impl Sub for BigInt
+where
+ T: Into,
+{
+ type Output = Self;
+
+ fn sub(mut self, rhs: T) -> Self::Output {
+ let mut right: BigInt = rhs.into();
+
+ // 0 - X edgecase
+ if self == 0 {
+ return -right;
+ }
+ if right == 0 {
+ return self;
+ }
+ if right == self {
+ return 0.into();
+ }
+
+ // negative numbers edgecases
+ if !self.positive && right.positive {
+ // -X - Y => -(X+Y)
+ self.positive = true;
+ return -(self + right);
+ } else if self.positive && !right.positive {
+ //X - (-Y)
+ right.positive = true;
+ return self + right;
+ } else if !self.positive && !right.positive {
+ // -X - (-Y) => -X + Y => Y - X
+ self.positive = true;
+ right.positive = true;
+ return right - self;
+ }
+
+ if self < right {
+ return -(right - self);
+ }
+
+ let mut result: BigInt = BigInt {
+ positive: self >= right,
+ numbers: vec![],
+ };
+
+ self.numbers.reverse();
+ right.numbers.reverse();
+
+ if self.numbers.len() >= right.numbers.len() {
+ right
+ .numbers
+ .extend(vec![0; self.numbers.len() - right.numbers.len()]);
+ } else {
+ self.numbers
+ .extend(vec![0; right.numbers.len() - self.numbers.len()]);
+ }
+
+ let numbers_set = self.numbers.iter().zip(right.numbers.iter());
+
+ let mut new_number: i8;
+ let mut carry = 0;
+
+ for number_set in numbers_set {
+ new_number = 0;
+
+ new_number += *number_set.0 as i8;
+ new_number -= *number_set.1 as i8;
+ new_number -= carry;
+
+ if new_number < 0 {
+ new_number += 10;
+ carry = 1;
+ } else {
+ carry = 0;
+ }
+
+ result.numbers.push(new_number as u8);
+ }
+
+ result.numbers.reverse();
+
+ while result.numbers.first().unwrap_or(&1).is_zero() {
+ result.numbers.remove(0);
+ }
+
+ result
+ }
+}
+
+assign_trait!(SubAssign, sub_assign, sub);
+
+impl Mul for BigInt
+where
+ T: Into,
+{
+ type Output = Self;
+ fn mul(self, rhs: T) -> Self::Output {
+ let right: BigInt = rhs.into();
+
+ //X * 0 edgecase
+ if self == 0 || right == 0 {
+ return BigInt::default();
+ }
+
+ if self == 1 {
+ return right;
+ }
+ if right == 1 {
+ return self;
+ }
+
+ if self == -1 {
+ return -right;
+ }
+ if right == -1 {
+ return -self;
+ }
+
+ let mut result = BigInt::default();
+ let mut sub_total;
+ let mut new_digit;
+ let mut carry;
+
+ for (position, &left) in self.numbers.iter().rev().enumerate() {
+ // *0 edgecase
+ if left == 0 {
+ continue;
+ }
+
+ sub_total = BigInt {
+ positive: true,
+ numbers: vec![],
+ };
+
+ carry = 0;
+
+ //right digit loop
+ for &right in right.numbers.iter().rev() {
+ new_digit = left * right;
+ new_digit += carry;
+ sub_total.numbers.push(new_digit % 10);
+ carry = new_digit / 10;
+ }
+
+ if !carry.is_zero() {
+ sub_total.numbers.push(carry);
+ }
+
+ sub_total.numbers.reverse();
+
+ //zero offset
+ sub_total.numbers.extend(vec![0; position]);
+
+ result += sub_total;
+ }
+
+ result.positive = self.positive == right.positive;
+ result
+ }
+}
+
+assign_trait!(MulAssign, mul_assign, mul);
+
+impl Div for BigInt
+where
+ T: Into,
+{
+ type Output = Self;
+ fn div(self, rhs: T) -> Self::Output {
+ let right: BigInt = rhs.into();
+
+ if right == 0 {
+ panic!("division by zero!");
+ }
+ if self == 0 {
+ return BigInt::default();
+ }
+ if right == 1 {
+ return self;
+ }
+ if self == 1 {
+ if right == 1 {
+ return 1.into();
+ }
+ return BigInt::default();
+ }
+
+ BigInt::divide_with_remainder(self, right).0
+ }
+}
+
+assign_trait!(DivAssign, div_assign, div);
+
+impl Rem for BigInt
+where
+ T: Into,
+{
+ type Output = Self;
+ fn rem(self, rhs: T) -> Self::Output {
+ let right: BigInt = rhs.into();
+
+ if right == 0 {
+ panic!("division by zero!");
+ }
+ if self == 0 || right == 1 {
+ return 0.into();
+ }
+
+ BigInt::divide_with_remainder(self, right).1
+ }
+}
+
+assign_trait!(RemAssign, rem_assign, rem);
+
+impl Pow for BigInt
+where
+ T: Into,
+{
+ type Output = Self;
+
+ fn pow(self, rhs: T) -> Self::Output {
+ let mut right: BigInt = rhs.into();
+
+ if self == 0 || self == 1 || right == 1 {
+ return self;
+ }
+ if right == 0 {
+ return 1.into();
+ }
+ if !right.positive {
+ if self == 1 {
+ return 1.into();
+ }
+ return 0.into();
+ }
+
+ let mut result: BigInt = 1.into();
+
+ while right != 0 {
+ result *= self.clone();
+
+ right -= 1;
+ }
+
+ result
+ }
+}
+
+impl BitAnd for BigInt
+where
+ T: Into,
+{
+ type Output = Self;
+ fn bitand(self, rhs: T) -> Self::Output {
+ BigInt::binary_operation(self, rhs, |left, right| left & right)
+ }
+}
+
+assign_trait!(BitAndAssign, bitand_assign, bitand);
+
+impl BitOr for BigInt
+where
+ T: Into,
+{
+ type Output = Self;
+ fn bitor(self, rhs: T) -> Self::Output {
+ BigInt::binary_operation(self, rhs, |left, right| left | right)
+ }
+}
+
+assign_trait!(BitOrAssign, bitor_assign, bitor);
+
+impl BitXor for BigInt
+where
+ T: Into,
+{
+ type Output = Self;
+ fn bitxor(self, rhs: T) -> Self::Output {
+ BigInt::binary_operation(self, rhs, |left, right| left ^ right)
+ }
+}
+
+assign_trait!(BitXorAssign, bitxor_assign, bitxor);
+
+impl Shl for BigInt
+where
+ T: Into,
+{
+ type Output = Self;
+ fn shl(self, rhs: T) -> Self::Output {
+ let right: BigInt = rhs.into();
+
+ if right == 0 {
+ return self;
+ }
+
+ let base: BigInt = 2.into();
+
+ self * base.pow(right)
+ }
+}
+
+assign_trait!(ShlAssign, shl_assign, shl);
+
+impl Shr for BigInt
+where
+ T: Into,
+{
+ type Output = Self;
+ fn shr(self, rhs: T) -> Self::Output {
+ let right: BigInt = rhs.into();
+
+ if right == 0 {
+ return self;
+ }
+
+ let base: BigInt = 2.into();
+
+ self / base.pow(right)
+ }
+}
+
+assign_trait!(ShrAssign, shr_assign, shr);
+
+impl BigInt {
+ pub fn new() -> BigInt {
+ BigInt::default()
+ }
+
+ pub fn to_words(&self) -> String {
+ let prefix = if self.positive { vec![] } else { vec!["minus"] };
+
+ prefix
+ .into_iter()
+ .chain(
+ self.numbers
+ .iter()
+ .map(|&number| BigInt::number_to_word(number)),
+ )
+ .collect::>()
+ .join(" ")
+ }
+
+ fn word_to_number(word: &str) -> Result {
+ match word {
+ "zero" => Ok(0),
+ "one" => Ok(1),
+ "two" => Ok(2),
+ "three" => Ok(3),
+ "four" => Ok(4),
+ "five" => Ok(5),
+ "six" => Ok(6),
+ "seven" => Ok(7),
+ "eight" => Ok(8),
+ "nine" => Ok(9),
+ _ => Err(BigIntError::NaN),
+ }
+ }
+
+ fn number_to_word(number: u8) -> &'static str {
+ match number {
+ 0 => "zero",
+ 1 => "one",
+ 2 => "two",
+ 3 => "three",
+ 4 => "four",
+ 5 => "five",
+ 6 => "six",
+ 7 => "seven",
+ 8 => "eight",
+ 9 => "nine",
+ _ => unreachable!(),
+ }
+ }
+
+ fn parse_word_digits(string_of_numbers: &str) -> Result {
+ let mut parsed: Vec = string_of_numbers
+ .split_whitespace()
+ .map(str::to_lowercase)
+ .collect();
+
+ let positive;
+
+ if matches!(parsed.first().map(String::as_str), Some("-" | "minus")) {
+ positive = false;
+ parsed.remove(0);
+ } else {
+ positive = true;
+ }
+
+ let numbers: Result, _> = parsed
+ .iter()
+ .map(String::as_str)
+ .map(BigInt::word_to_number)
+ .collect();
+ let numbers = numbers?;
+
+ //additional check
+ if numbers.is_empty() {
+ return Err(BigIntError::NaN);
+ }
+
+ Ok(BigInt { positive, numbers })
+ }
+
+ fn is_even(&self) -> bool {
+ (*self.numbers.last().unwrap() % 2).is_zero()
+ }
+
+ fn to_binary(&self) -> (bool, Vec) {
+ if *self == 0 {
+ return (true, vec![false]);
+ }
+
+ let mut final_vec = vec![];
+
+ let mut number = self.clone();
+
+ let positive = number.positive;
+ number.positive = true;
+
+ while number != 0 {
+ if number.is_even() {
+ final_vec.push(false);
+ } else {
+ final_vec.push(true);
+ }
+ number /= 2;
+ }
+
+ final_vec.reverse();
+
+ (positive, final_vec)
+ }
+
+ fn from_binary(positive: bool, binary: Vec) -> BigInt {
+ if binary.is_empty() {
+ return BigInt::default();
+ }
+
+ let mut result = BigInt::default();
+
+ for (position, bit) in binary.iter().rev().enumerate() {
+ if *bit {
+ result += 2.pow(position);
+ }
+ }
+
+ result.positive = positive;
+
+ result
+ }
+
+ fn number_to_hexa(number: BigInt) -> char {
+ let number: u8 = number.try_into().unwrap_or(0);
+
+ match number {
+ 0 => '0',
+ 1 => '1',
+ 2 => '2',
+ 3 => '3',
+ 4 => '4',
+ 5 => '5',
+ 6 => '6',
+ 7 => '7',
+ 8 => '8',
+ 9 => '9',
+ 10 => 'A',
+ 11 => 'B',
+ 12 => 'C',
+ 13 => 'D',
+ 14 => 'E',
+ 15 => 'F',
+ _ => unreachable!(),
+ }
+ }
+
+ fn to_hexa_vec(&self) -> Vec {
+ let mut final_vec = vec![];
+ let mut number = self.clone();
+
+ number.positive = true;
+
+ while number > 0 {
+ let divided = BigInt::divide_with_remainder(number, 16.into());
+ final_vec.push(BigInt::number_to_hexa(divided.1));
+ number = divided.0;
+ }
+
+ final_vec.reverse();
+
+ final_vec
+ }
+
+ fn create_hexa_string(&self, f: &mut fmt::Formatter<'_>, uppercase: bool) -> String {
+ let hexa = self.to_hexa_vec();
+ let mut output = String::new();
+
+ if !self.positive {
+ output.push('-');
+ }
+ if f.sign_plus() && self.positive {
+ output.push('+');
+ }
+
+ if f.alternate() {
+ output.push_str("0x");
+ }
+
+ for hex in hexa {
+ output.push(if uppercase {
+ hex.to_ascii_uppercase()
+ } else {
+ hex.to_ascii_lowercase()
+ })
+ }
+
+ BigInt::add_alignment(&mut output, f);
+
+ output
+ }
+
+ fn equalize_vectors_length(left: Vec, right: Vec) -> (Vec, Vec) {
+ let (mut longer, mut shorter) = {
+ if left.len() > right.len() {
+ (left, right)
+ } else {
+ (right, left)
+ }
+ };
+
+ longer.reverse();
+ shorter.reverse();
+
+ shorter.extend(vec![0; longer.len() - shorter.len()]);
+
+ (shorter, longer)
+ }
+
+ fn binary_operation(self, rhs: T, bit_operation: F) -> BigInt
+ where
+ F: Fn(bool, bool) -> bool,
+ T: Into,
+ {
+ let right: BigInt = rhs.into();
+
+ let (left_positive, mut left) = self.to_binary();
+ let (right_positive, mut right) = right.to_binary();
+
+ left.reverse();
+ right.reverse();
+
+ let (longer, mut shorter) = if left.len() > right.len() {
+ (left, right)
+ } else {
+ (right, left)
+ };
+
+ shorter.extend(vec![false; longer.len() - shorter.len()]);
+
+ let binary_set = longer.iter().zip(shorter.iter());
+
+ let result: Vec = binary_set
+ .rev()
+ .map(|(left, right)| bit_operation(*left, *right))
+ .collect();
+
+ BigInt::from_binary(bit_operation(left_positive, right_positive), result)
+ }
+
+ fn divide_with_remainder(mut left: BigInt, mut right: BigInt) -> (BigInt, BigInt) {
+ let mut result = BigInt {
+ positive: left.positive == right.positive,
+ numbers: vec![],
+ };
+
+ let mut partial_sum = BigInt {
+ positive: true,
+ numbers: vec![],
+ };
+
+ left.positive = true;
+ right.positive = true;
+
+ let mut new_digit;
+
+ for digit in left.numbers.iter() {
+ partial_sum.numbers.push(*digit);
+ new_digit = 0;
+
+ while partial_sum >= right {
+ partial_sum -= right.clone();
+ new_digit += 1;
+ }
+
+ result.numbers.push(new_digit);
+
+ if partial_sum.numbers == vec![0] {
+ partial_sum.numbers.clear();
+ }
+ }
+
+ while result.numbers.first().unwrap_or(&1).is_zero() {
+ result.numbers.remove(0);
+ }
+
+ if result.numbers.is_empty() {
+ return (BigInt::default(), partial_sum);
+ }
+
+ if partial_sum.numbers.is_empty() {
+ partial_sum = BigInt::default();
+ }
+
+ partial_sum.positive = result.positive;
+
+ (result, partial_sum)
+ }
+
+ fn add_alignment(output: &mut String, f: &mut fmt::Formatter<'_>) {
+ let alignment = (f.width().unwrap_or(output.len()) - output.len()) as i32;
+
+ if alignment > 0 {
+ match f.align() {
+ Some(Alignment::Left) => {
+ output.push_str(f.fill().to_string().repeat(alignment as usize).as_str())
+ }
+ Some(Alignment::Center) => {
+ output.insert_str(
+ 0,
+ f.fill()
+ .to_string()
+ .repeat((alignment / 2) as usize)
+ .as_str(),
+ );
+ output.push_str(
+ f.fill()
+ .to_string()
+ .repeat((alignment / 2 + (alignment % 2)) as usize)
+ .as_str(),
+ );
+ }
+ Some(Alignment::Right) => {
+ output.insert_str(0, f.fill().to_string().repeat(alignment as usize).as_str())
+ }
+ _ => output.insert_str(0, f.fill().to_string().repeat(alignment as usize).as_str()),
+ }
+ }
+ }
+
+ fn create_new_digit(position: usize, number: &u8) -> u64 {
+ let number = *number as u64;
+
+ if number == 0 {
+ return match position {
+ 0 => 0,
+ _ => 10.pow(position),
+ } as u64;
+ }
+ number * 10_u64.pow(position as u32)
+ }
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/tests.rs b/src/tests.rs
new file mode 100644
index 0000000..67a2914
--- /dev/null
+++ b/src/tests.rs
@@ -0,0 +1,1148 @@
+use std::str::FromStr;
+
+use num_traits::Pow;
+
+use crate::BigInt;
+use crate::BigIntError;
+
+#[test]
+fn default() {
+ let def = BigInt::default();
+ assert!(def.positive);
+ assert_eq!(def.numbers, [0].to_vec());
+}
+
+#[test]
+fn new() {
+ let new = BigInt::new();
+ assert!(new.positive);
+ assert_eq!(new.numbers, [0].to_vec());
+}
+
+#[test]
+fn from() {
+ let x = BigInt::from(20);
+ assert!(x.positive);
+ assert_eq!(x.numbers, [2, 0].to_vec());
+ let x = BigInt::from(-20);
+ assert!(!x.positive);
+ assert_eq!(x.numbers, [2, 0].to_vec());
+ let x = BigInt::from(-320020000981234567890_i128);
+ assert!(!x.positive);
+ assert_eq!(
+ x.numbers,
+ [3, 2, 0, 0, 2, 0, 0, 0, 0, 9, 8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0].to_vec()
+ );
+ let x = BigInt::from(0);
+ assert!(x.positive);
+ assert_eq!(x.numbers, [0].to_vec());
+ let x = BigInt::from(-0);
+ assert!(x.positive);
+ assert_eq!(x.numbers, [0].to_vec());
+}
+
+#[test]
+fn from_string_numbers() {
+ let x = BigInt::from_str("20").unwrap();
+ assert!(x.positive);
+ assert_eq!(x.numbers, [2, 0].to_vec());
+ let x = BigInt::from_str("666").unwrap();
+ assert!(x.positive);
+ assert_eq!(x.numbers, [6, 6, 6].to_vec());
+ let x = BigInt::from_str("-20").unwrap();
+ assert!(!x.positive);
+ assert_eq!(x.numbers, [2, 0].to_vec());
+ let x = BigInt::from_str("-320020000981234567890").unwrap();
+ assert!(!x.positive);
+ assert_eq!(
+ x.numbers,
+ [3, 2, 0, 0, 2, 0, 0, 0, 0, 9, 8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0].to_vec()
+ );
+ let x = BigInt::from_str("-0").unwrap();
+ assert!(x.positive);
+ assert_eq!(x.numbers, [0].to_vec());
+ let x = BigInt::from_str("0sw");
+ assert!(x.is_err());
+ let x = BigInt::from_str("0 2020000");
+ assert!(x.is_err());
+ let x = BigInt::from_str("--200");
+ assert!(x.is_err());
+ let x = BigInt::from_str("+2000303");
+ assert!(x.is_err());
+ let x = BigInt::from_str("minus20003002");
+ assert!(x.is_err());
+}
+
+#[test]
+fn from_string_words_from_str_digits() {
+ let x = BigInt::from_str("two zero ").unwrap();
+ assert!(x.positive);
+ assert_eq!(x.numbers, [2, 0].to_vec());
+ let x = BigInt::from_str("minus two four").unwrap();
+ assert!(!x.positive);
+ assert_eq!(x.numbers, [2, 4].to_vec());
+ let x = BigInt::from_str("two five five zero zero two one").unwrap();
+ assert!(x.positive);
+ assert_eq!(x.numbers, [2, 5, 5, 0, 0, 2, 1].to_vec());
+ let x = BigInt::from_str("minus two zero zero zero zero zero one").unwrap();
+ assert!(!x.positive);
+ assert_eq!(x.numbers, [2, 0, 0, 0, 0, 0, 1].to_vec());
+ let x = BigInt::from_str("zero").unwrap();
+ assert!(x.positive);
+ assert_eq!(x.numbers, [0].to_vec());
+ let x = BigInt::from_str("onse");
+ assert!(x.is_err());
+ let x = BigInt::from_str(" ");
+ assert!(x.is_err());
+ let x = BigInt::from_str("twenty thousand thousand");
+ assert!(x.is_err());
+ let x: Result = BigInt::from_str("twenty thousand hundred");
+ assert!(x.is_err());
+ let x = BigInt::from_str("- five four").unwrap();
+ assert!(!x.positive);
+ assert_eq!(x.numbers, [5, 4].to_vec());
+}
+
+#[test]
+fn try_into() {
+ let x = BigInt::from(666);
+ assert_eq!(666_i128, x.try_into().unwrap());
+ let x = BigInt::from(666);
+ assert_eq!(666_u128, x.try_into().unwrap());
+ let x = BigInt::from(-123);
+ assert_eq!(-123_i128, x.try_into().unwrap());
+ let x = BigInt::from(-123);
+ assert_eq!(123_u128, x.try_into().unwrap());
+ let x = BigInt::from(0);
+ assert_eq!(0_i128, x.try_into().unwrap());
+ let x = BigInt::from(0);
+ assert_eq!(0_u128, x.try_into().unwrap());
+ let x = BigInt::from(10);
+ assert_eq!(10_i128, x.try_into().unwrap());
+ let x = BigInt::from(10);
+ assert_eq!(10_u128, x.try_into().unwrap());
+ let x = BigInt::from(-123);
+ assert_eq!(-123_i8, x.try_into().unwrap());
+ let x = BigInt::from(-123);
+ assert_eq!(123_u8, x.try_into().unwrap());
+ let x = BigInt::from(-123);
+ assert_eq!(-123_i16, x.try_into().unwrap());
+ let x = BigInt::from(-123);
+ assert_eq!(123_u32, x.try_into().unwrap());
+ let x = BigInt::from(-123);
+ assert_eq!(-123_i64, x.try_into().unwrap());
+ let x = BigInt::from(-123);
+ assert_eq!(123_u64, x.try_into().unwrap());
+}
+
+#[test]
+#[should_panic]
+fn try_into_panic_i128() {
+ let x = BigInt::from_str("999999999999999999999999999999999999999999999999999999999").unwrap();
+ assert_eq!(666_i128, x.try_into().unwrap());
+}
+
+#[test]
+#[should_panic]
+fn try_into_panic_u128() {
+ let x = BigInt::from_str("999999999999999999999999999999999999999999999999999999999").unwrap();
+ assert_eq!(666_u128, x.try_into().unwrap());
+}
+
+#[test]
+fn display() {
+ let x = BigInt::from(1003);
+ assert_eq!(format!("Number is: {x:0^10}"), "Number is: 0001003000");
+ let x = BigInt::from(1003);
+ assert_eq!(format!("Number is: {x:0^11}"), "Number is: 00010030000");
+ let x = BigInt::from(1003);
+ assert_eq!(format!("Number is: {x:0>10}"), "Number is: 0000001003");
+ let x = BigInt::from(1003);
+ assert_eq!(format!("Number is: {x:0<10}"), "Number is: 1003000000");
+ let x = BigInt::from(1003);
+ assert_eq!(format!("Number is: {x}"), "Number is: 1003");
+ let x = BigInt::from(0);
+ assert_eq!(format!("Number is: {x}"), "Number is: 0");
+ let x = BigInt::from(-100);
+ assert_eq!(format!("Number is: {x}"), "Number is: -100");
+ let x = BigInt::from(-0);
+ assert_eq!(format!("Number is: {x}"), "Number is: 0");
+ let x = BigInt::from(-1);
+ assert_eq!(format!("Number is: {x}"), "Number is: -1");
+ let x = BigInt::from(320020000981234567890_i128);
+ assert_eq!(
+ format!("Number is: {x}"),
+ "Number is: 320020000981234567890"
+ );
+ let x = BigInt::from(1003);
+ assert_eq!(format!("Number is: {x:->10}"), "Number is: ------1003");
+ let x = BigInt::from(1003);
+ assert_eq!(format!("Number is: {x:9}"), "Number is: 1003");
+ let x = BigInt::from(0);
+ assert_eq!(format!("Number is: {x:2}"), "Number is: 0");
+ let x = BigInt::from(-100);
+ assert_eq!(format!("Number is: {x}"), "Number is: -100");
+ let x = BigInt::from(-0);
+ assert_eq!(format!("Number is: {x}"), "Number is: 0");
+ let x = BigInt::from(-100);
+ assert_eq!(format!("Number is: {x:X>5}"), "Number is: X-100");
+ let x = BigInt::from(-0);
+ assert_eq!(format!("Number is: {x:+}"), "Number is: +0");
+}
+
+#[test]
+fn to_words() {
+ let x = BigInt::from(20);
+ assert_eq!(x.to_words(), "two zero");
+ let x = BigInt::from(-24);
+ assert_eq!(x.to_words(), "minus two four");
+ let x = BigInt::from(2550021);
+ assert_eq!(x.to_words(), "two five five zero zero two one");
+ let x = BigInt::from(-2000000000001_i128);
+ assert_eq!(
+ x.to_words(),
+ "minus two zero zero zero zero zero zero zero zero zero zero zero one"
+ );
+}
+
+#[test]
+fn not() {
+ let mut x = BigInt::from(1);
+ assert!(x.positive);
+ assert_eq!(x.to_string(), "1");
+ x = -x;
+ assert!(!x.positive);
+ assert_eq!(x.to_string(), "-1");
+ x = -x;
+ assert!(x.positive);
+ assert_eq!(x.to_string(), "1");
+ x = BigInt::from(-22);
+ assert!(!x.positive);
+ assert_eq!(x.to_string(), "-22");
+ x = -x;
+ assert!(x.positive);
+ assert_eq!(x.to_string(), "22");
+}
+
+#[test]
+fn equal() {
+ let x = BigInt::from(10);
+ let y = BigInt::from(10);
+ assert!(x == y);
+ let x = BigInt::from(101010);
+ let y = BigInt::from(101010);
+ assert!(x == y);
+ let x = BigInt::from(101010);
+ let y = BigInt::from(101210);
+ assert!(!(x == y));
+ let x = BigInt::from(101010);
+ let y = BigInt::from(1);
+ assert!(!(x == y));
+ let x = BigInt::from(0);
+ let y = BigInt::from(0);
+ assert!(x == y);
+ let x = BigInt::from(10);
+ let y = BigInt::from(-10);
+ assert!(x != y);
+ let x = BigInt::from(11);
+ let y = BigInt::from(10);
+ assert!(x != y);
+ let x = BigInt::from(-0);
+ let y = BigInt::from(0);
+ assert!(x == y);
+}
+
+#[test]
+fn equal_int() {
+ let x = BigInt::from(10);
+ assert!(x == 10);
+ let x = BigInt::from(101010);
+ assert!(x == 101010);
+ let x = BigInt::from(101010);
+ assert!(!(x == 101210));
+ let x = BigInt::from(101010);
+ assert!(!(x == 1));
+ let x = BigInt::from(0);
+ assert!(x == 0);
+ let x = BigInt::from(10);
+ assert!(x != -10);
+ let x = BigInt::from(11);
+ assert!(x != 10);
+ let x = BigInt::from(-0);
+ assert!(x == 0);
+}
+
+#[test]
+fn equal_str() {
+ let x = BigInt::from(10);
+ assert!(x == "10");
+ let x = BigInt::from(101010);
+ assert!(x == "101010");
+ let x = BigInt::from(101010);
+ assert!(!(x == "101210"));
+ let x = BigInt::from(101010);
+ assert!(!(x == "1"));
+ let x = BigInt::from(0);
+ assert!(x == "0");
+ let x = BigInt::from(10);
+ assert!(x != "-10");
+ let x = BigInt::from(11);
+ assert!(x != "10");
+ let x = BigInt::from(-0);
+ assert!(x == "0");
+}
+
+#[test]
+fn greater() {
+ let x: BigInt = BigInt::from(15);
+ let y = BigInt::from(10);
+ assert!(x > y);
+ let x: BigInt = BigInt::from(8);
+ let y = BigInt::from(7);
+ assert!(x > y);
+ let x = BigInt::from(10);
+ let y = BigInt::from(10);
+ assert!(x <= y);
+ let x = BigInt::from(10);
+ let y = BigInt::from(10);
+ assert!(x >= y);
+ let x = BigInt::from(101010);
+ let y = BigInt::from(101010);
+ assert!(x >= y);
+ let x = BigInt::from(0);
+ let y = BigInt::from(0);
+ assert!(x >= y);
+ let x = BigInt::from(10);
+ let y = BigInt::from(-10);
+ assert!(x > y);
+ let x = BigInt::from(11);
+ let y = BigInt::from(10);
+ assert!(x > y);
+}
+
+#[test]
+fn lesser() {
+ let x: BigInt = BigInt::from(0);
+ let y = BigInt::from(10);
+ assert!(x < y);
+ let x: BigInt = BigInt::from(8);
+ let y = BigInt::from(9);
+ assert!(x < y);
+ let x = BigInt::from(10);
+ let y = BigInt::from(10);
+ assert!(x >= y);
+ let x = BigInt::from(10);
+ let y = BigInt::from(10);
+ assert!(x <= y);
+ let x = BigInt::from(99999999999_i64);
+ let y = BigInt::from(99999999999_i128);
+ assert!(x <= y);
+ let x = BigInt::from(0);
+ let y = BigInt::from(0);
+ assert!(x <= y);
+ let x = BigInt::from(-10);
+ let y = BigInt::from(10);
+ assert!(x < y);
+ let x = BigInt::from(11);
+ let y = BigInt::from(99999999999_u64);
+ assert!(x < y);
+ let x = BigInt::from(10000010);
+ let y = BigInt::from(20000000);
+ assert!(x < y);
+}
+
+#[test]
+fn add() {
+ let mut x: BigInt = BigInt::from(1000);
+ let y = BigInt::from(10);
+ let z = x.clone() + y.clone();
+ x += y;
+ assert_eq!(z, 1010);
+ assert_eq!(x, z);
+
+ let mut x: BigInt = BigInt::from(10);
+ let y = BigInt::from(10);
+ let z = x.clone() + y.clone();
+ x += y;
+ assert_eq!(z, 20);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(101010);
+ let y = BigInt::from(101010);
+ let z = x.clone() + y.clone();
+ x += y;
+ assert_eq!(z, 202020);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(0);
+ let y = BigInt::from(0);
+ let z = x.clone() + y.clone();
+ x += y;
+ assert_eq!(z, 0);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(10);
+ let y = BigInt::from(-10);
+ let z = x.clone() + y.clone();
+ x += y.clone();
+ assert_eq!(z, 0);
+ assert_ne!(x, y);
+
+ let mut x = BigInt::from(11);
+ let y = BigInt::from(10);
+ let z = x.clone() + y.clone();
+ x += y.clone();
+ assert_eq!(z, 21);
+ assert_ne!(x, y);
+
+ let mut x = BigInt::from(-0);
+ let y = BigInt::from(0);
+ let z = x.clone() + y.clone();
+ x += y.clone();
+ assert_eq!(z, 0);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(6);
+ let y = BigInt::from(4);
+ let z = x.clone() + y.clone();
+ x += y.clone();
+ assert_eq!(z, 10);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(-15);
+ let y = BigInt::from(-4);
+ let z = x.clone() + y.clone();
+ x += y.clone();
+ assert_eq!(z, -19);
+ assert_eq!(x, z);
+}
+
+#[test]
+fn sub() {
+ let mut x: BigInt = BigInt::from(10);
+ let y = BigInt::from(10);
+ let z = x.clone() - y.clone();
+ x -= y;
+ assert_eq!(z, 0);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(101010);
+ let y = BigInt::from(10);
+ let z = x.clone() - y.clone();
+ x -= y;
+ assert_eq!(z, 101000);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(0);
+ let y = BigInt::from(0);
+ let z = x.clone() - y.clone();
+ x -= y;
+ assert_eq!(z, 0);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(10);
+ let y = BigInt::from(-10);
+ let z = x.clone() - y.clone();
+ x -= y.clone();
+ assert_eq!(z, 20);
+ assert_ne!(x, y);
+
+ let mut x = BigInt::from(-10);
+ let y = BigInt::from(10);
+ let z = x.clone() - y.clone();
+ x -= y.clone();
+ assert_eq!(z, -20);
+ assert_ne!(x, y);
+
+ let mut x = BigInt::from(11);
+ let y = BigInt::from(10);
+ let z = x.clone() - y.clone();
+ x -= y.clone();
+ assert_eq!(z, 1);
+ assert_ne!(x, y);
+
+ let mut x = BigInt::from(-0);
+ let y = BigInt::from(0);
+ let z = x.clone() - y.clone();
+ x -= y.clone();
+ assert_eq!(z, 0);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(6);
+ let y = BigInt::from(4);
+ let z = x.clone() - y.clone();
+ x -= y.clone();
+ assert_eq!(z, 2);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(4);
+ let y = BigInt::from(15);
+ let z = x.clone() - y.clone();
+ x -= y.clone();
+ assert_eq!(z, -11);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(-15);
+ let y = BigInt::from(-4);
+ let z = x.clone() - y.clone();
+ x -= y.clone();
+ assert_eq!(z, -11);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(987654);
+ let y = BigInt::from(987653);
+ let z = x.clone() - y.clone();
+ x -= y.clone();
+ assert_eq!(z, 1);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(1);
+ let y = BigInt::from(1000);
+ let z = x.clone() - y.clone();
+ x -= y.clone();
+ assert_eq!(z, -999);
+ assert_eq!(x, z);
+}
+
+#[test]
+fn mul() {
+ let mut x: BigInt = BigInt::from(10);
+ let y = BigInt::from(10);
+ let z: BigInt = x.clone() * y.clone();
+ x *= y;
+ assert_eq!(z, 100);
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from(101);
+ let y = BigInt::from(101);
+ let z = x.clone() * y.clone();
+ x *= y;
+ assert_eq!(z, 10201);
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from(0);
+ let y = BigInt::from(0);
+ let z: BigInt = x.clone() * y.clone();
+ x *= y;
+ assert_eq!(z, 0);
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from(20100000100_u64);
+ let y = BigInt::from(0);
+ let z: BigInt = x.clone() * y.clone();
+ x *= y;
+ assert_eq!(z, 0);
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from(10);
+ let y = BigInt::from(-10);
+ let z: BigInt = x.clone() * y.clone();
+ x *= y.clone();
+ assert_eq!(z, -100);
+ assert_ne!(x, y);
+
+ let mut x = BigInt::from(11);
+ let y = BigInt::from(10);
+ let z: BigInt = x.clone() * y.clone();
+ x *= y.clone();
+ assert_eq!(z, 110);
+ assert_ne!(x, y);
+
+ let mut x = BigInt::from(-0);
+ let y = BigInt::from(0);
+ let z: BigInt = x.clone() * y.clone();
+ x *= y.clone();
+ assert_eq!(z, 0);
+ assert_eq!(x, y);
+
+ let mut x = BigInt::from(6);
+ let y = BigInt::from(4);
+ let z: BigInt = x.clone() * y.clone();
+ x *= y.clone();
+ assert_eq!(z, 24);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(-15);
+ let y = BigInt::from(-4);
+ let z: BigInt = x.clone() * y.clone();
+ x *= y.clone();
+ assert_eq!(z, 60);
+ assert_eq!(x, z);
+}
+
+#[test]
+fn div() {
+ let mut x: BigInt = BigInt::from(10000000);
+ let y = BigInt::from(10);
+ let z = x.clone() / y.clone();
+ x /= y;
+ assert_eq!(z, 1000000);
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from(101);
+ let y = BigInt::from(101);
+ let z = x.clone() / y.clone();
+ x /= y;
+ assert_eq!(z, 1);
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from(9999_u128);
+ let y = BigInt::from(2);
+ let z = x.clone() / y.clone();
+ x /= y;
+ assert_eq!(z, 4999_u128);
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from_str("999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999").unwrap();
+ let y = BigInt::from(2);
+ let z = x.clone() / y.clone();
+ x /= y;
+ assert_eq!(
+ z,
+ "499999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"
+ );
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from(0);
+ let y = BigInt::from(2);
+ let z = x.clone() / y.clone();
+ x /= y;
+ assert_eq!(z, 0);
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from(1);
+ let y = BigInt::from(2);
+ let z = x.clone() / y.clone();
+ x /= y;
+ assert_eq!(z, 0);
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from(1);
+ let y = BigInt::from(1);
+ let z = x.clone() / y.clone();
+ x /= y;
+ assert_eq!(z, 1);
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from(0);
+ let y = BigInt::from(666);
+ let z = x.clone() / y.clone();
+ x /= y;
+ assert_eq!(z, 0);
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from(0);
+ let y = BigInt::from(100);
+ let z = x.clone() / y.clone();
+ x /= y;
+ assert_eq!(z, 0);
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from(20100000100_u64);
+ let y = BigInt::from(20000000);
+ let z = x.clone() / y.clone();
+ x /= y;
+ assert_eq!(z, 1005);
+ assert_eq!(z, x);
+
+ let mut x = BigInt::from(10);
+ let y = BigInt::from(-10);
+ let z = x.clone() / y.clone();
+ x /= y.clone();
+ assert_eq!(z, -1);
+ assert_ne!(x, y);
+
+ let mut x = BigInt::from(110);
+ let y = BigInt::from(10);
+ let z = x.clone() / y.clone();
+ x /= y.clone();
+ assert_eq!(z, 11);
+ assert_ne!(x, y);
+
+ let mut x = BigInt::from(6);
+ let y = BigInt::from(2);
+ let z = x.clone() / y.clone();
+ x /= y.clone();
+ assert_eq!(z, 3);
+ assert_eq!(x, z);
+
+ let mut x = BigInt::from(-15);
+ let y = BigInt::from(-5);
+ let z = x.clone() / y.clone();
+ x /= y.clone();
+ assert_eq!(z, 3);
+ assert_eq!(x, z);
+}
+
+#[test]
+#[should_panic]
+fn div_by_zero() {
+ let mut x = BigInt::from(10);
+ let y = BigInt::from(0);
+ x /= y;
+}
+
+#[test]
+fn remainder() {
+ let mut x: BigInt = BigInt::from(10000);
+ let y = BigInt::from(10);
+ let z = x.clone() % y.clone();
+ x %= y;
+ assert_eq!(z, 0);
+ assert_eq!(z, x);
+
+ let mut x: BigInt = BigInt::from(10);
+ let y = BigInt::from(7);
+ let z = x.clone() % y.clone();
+ x %= y;
+ assert_eq!(z, 3);
+ assert_eq!(z, x);
+
+ let mut x: BigInt = BigInt::from(10000);
+ let y = BigInt::from(10);
+ let z = x.clone() % y.clone();
+ x %= y;
+ assert_eq!(z, 0);
+ assert_eq!(z, x);
+
+ let mut x: BigInt = BigInt::from(-104);
+ let y = BigInt::from(10);
+ let z = x.clone() % y.clone();
+ x %= y;
+ assert_eq!(z, -4);
+ assert_eq!(z, x);
+
+ let mut x: BigInt = BigInt::from(24);
+ let y = BigInt::from(3);
+ let z = x.clone() % y.clone();
+ x %= y;
+ assert_eq!(z, 0);
+ assert_eq!(z, x);
+
+ let mut x: BigInt = BigInt::from(33);
+ let y = BigInt::from(7);
+ let z = x.clone() % y.clone();
+ x %= y;
+ assert_eq!(z, 5);
+ assert_eq!(z, x);
+}
+
+#[test]
+fn power_of() {
+ let x: BigInt = BigInt::from(2);
+ let y = BigInt::from(2);
+ let z = x.pow(y);
+ assert_eq!(z, 4);
+
+ let x: BigInt = BigInt::from(2);
+ let y = BigInt::from(1);
+ let z = x.pow(y);
+ assert_eq!(z, 2);
+
+ let x: BigInt = BigInt::from(1);
+ let y = BigInt::from(1000000);
+ let z = x.pow(y);
+ assert_eq!(z, 1);
+
+ let x: BigInt = BigInt::from(3);
+ let y = BigInt::from(3);
+ let z = x.pow(y);
+ assert_eq!(z, 27);
+
+ let x: BigInt = BigInt::from(-3);
+ let y = BigInt::from(3);
+ let z = x.pow(y);
+ assert_eq!(z, -27);
+
+ let x: BigInt = BigInt::from(-3);
+ let y = BigInt::from(2);
+ let z = x.pow(y);
+ assert_eq!(z, 9);
+
+ let x: BigInt = BigInt::from(2);
+ let y = BigInt::from(-1);
+ let z = x.pow(y);
+ assert_eq!(z, 0);
+
+ let x: BigInt = BigInt::from(1);
+ let y = BigInt::from(-10);
+ let z = x.pow(y);
+ assert_eq!(z, 1);
+
+ let x: BigInt = BigInt::from(5);
+ let y = BigInt::from(-10);
+ let z = x.pow(y);
+ assert_eq!(z, 0);
+}
+
+#[test]
+#[should_panic]
+fn rem_of_zero() {
+ let mut x: BigInt = BigInt::from(10);
+ let y = BigInt::from(0);
+ let z = x.clone() % y.clone();
+ x %= y;
+ assert_eq!(z, 0);
+ assert_eq!(z, x);
+}
+
+#[test]
+fn binary() {
+ let x = BigInt::from(11);
+ assert_eq!(format!("{x:#10b}"), " 0b1011");
+ let x = BigInt::from(4);
+ assert_eq!(format!("{x:#b}"), "0b100");
+ let x = BigInt::from(4);
+ assert_eq!(format!("{x:b}"), "100");
+ let x = BigInt::from(4);
+ assert_eq!(format!("{x:0>10b}"), "0000000100");
+ let x = BigInt::from(10);
+ assert_eq!(format!("{x:#10b}"), " 0b1010");
+ let x = BigInt::from(10);
+ assert_eq!(format!("{x:x>#010b}"), "xxxx0b1010");
+ let x = BigInt::from(172);
+ assert_eq!(format!("{x:b}"), "10101100");
+ let x = BigInt::from(-17220003931_i64);
+ assert_eq!(format!("{x:#b}"), "-0b10000000010011001000110100001011011");
+}
+
+#[test]
+fn binary_transformation() {
+ let x: BigInt = BigInt::from(10);
+ let (positive, binary) = x.to_binary();
+ assert_eq!(x, BigInt::from_binary(positive, binary));
+
+ let x: BigInt = BigInt::from(-42);
+ let (positive, binary) = x.to_binary();
+ assert_eq!(x, BigInt::from_binary(positive, binary));
+
+ let x: BigInt = BigInt::from(-0);
+ let (positive, binary) = x.to_binary();
+ assert_eq!(x, BigInt::from_binary(positive, binary));
+
+ let x: BigInt = BigInt::from(0);
+ let (positive, binary) = x.to_binary();
+ assert_eq!(x, BigInt::from_binary(positive, binary));
+
+ let x: BigInt = BigInt::from(-9999);
+ let (positive, binary) = x.to_binary();
+ assert_eq!(x, BigInt::from_binary(positive, binary));
+
+ let x: BigInt = BigInt::from(666);
+ let (positive, binary) = x.to_binary();
+ assert_eq!(x, BigInt::from_binary(positive, binary));
+}
+
+#[test]
+fn bit_and() {
+ let mut x = BigInt::from(4); //100
+ let y = BigInt::from(12); //1100
+ let z = x.clone() & y.clone(); //0100
+ x &= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 4);
+
+ let mut x = BigInt::from(10); //1010
+ let y = BigInt::from(13); //1101
+ let z = x.clone() & y.clone(); //1000
+ x &= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 8);
+
+ let mut x = BigInt::from(172); //10101100
+ let y = BigInt::from(223); //11011111
+ let z = x.clone() & y.clone(); //10001100
+ x &= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 140);
+
+ let mut x = BigInt::from(172); //10101100
+ let y = BigInt::from(1); //1
+ let z = x.clone() & y.clone(); //0
+ x &= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 0);
+
+ let mut x = BigInt::from(173); //10101101
+ let y = BigInt::from(1); //1
+ let z = x.clone() & y.clone(); //1
+ x &= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 1);
+}
+
+#[test]
+fn bit_or() {
+ let mut x = BigInt::from(4); //100
+ let y = BigInt::from(12); //1100
+ let z = x.clone() | y.clone(); //1100
+ x |= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 12);
+
+ let mut x = BigInt::from(10); //1010
+ let y = BigInt::from(13); //1101
+ let z = x.clone() | y.clone(); //1111
+ x |= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 15);
+
+ let mut x = BigInt::from(172); //10101100
+ let y = BigInt::from(223); //11011111
+ let z = x.clone() | y.clone(); //11111111
+ x |= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 255);
+
+ let mut x = BigInt::from(172); //10101100
+ let y = BigInt::from(1); //1
+ let z = x.clone() | y.clone(); //10101101
+ x |= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 173);
+
+ let mut x = BigInt::from(173); //10101101
+ let y = BigInt::from(1); //1
+ let z = x.clone() | y.clone(); //10101101
+ x |= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 173);
+}
+
+#[test]
+fn bit_xor() {
+ let mut x = BigInt::from(4); //100
+ let y = BigInt::from(12); //1100
+ let z = x.clone() ^ y.clone(); //1000
+ x ^= y;
+ assert_eq!(x, z);
+ assert_eq!(z, -8);
+
+ let mut x = BigInt::from(10); //1010
+ let y = BigInt::from(13); //1101
+ let z = x.clone() ^ y.clone(); //0111
+ x ^= y;
+ assert_eq!(x, z);
+ assert_eq!(z, -7);
+
+ let mut x = BigInt::from(-172); //10101100
+ let y = BigInt::from(-223); //11011111
+ let z = x.clone() ^ y.clone(); //01110011
+ x ^= y;
+ assert_eq!(x, z);
+ assert_eq!(z, -115);
+
+ let mut x = BigInt::from(172); //10101100
+ let y = BigInt::from(-1); //1
+ let z = x.clone() ^ y.clone(); //10101101
+ x ^= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 173);
+
+ let mut x = BigInt::from(-173); //10101101
+ let y = BigInt::from(1); //1
+ let z = x.clone() ^ y.clone(); //10101100
+ x ^= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 172);
+}
+
+#[test]
+fn bit_shift_left() {
+ let mut x = BigInt::from(4); //100
+ let y = BigInt::from(2);
+ let z = x.clone() << y.clone(); //10000
+ x <<= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 16);
+
+ let mut x = BigInt::from(10); //1010
+ let y = BigInt::from(1);
+ let z = x.clone() << y.clone(); //10100
+ x <<= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 20);
+
+ let mut x = BigInt::from(172); //10101100
+ let y = BigInt::from(0);
+ let z = x.clone() << y.clone();
+ x <<= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 172);
+
+ let mut x = BigInt::from(172); //10101100
+ let y = BigInt::from(10);
+ let z = x.clone() << y.clone(); //101011000000000000
+ x <<= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 176128);
+
+ let mut x = BigInt::from(173); //10101101
+ let y = BigInt::from(1);
+ let z = x.clone() << y.clone(); //101011010
+ x <<= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 346);
+}
+
+#[test]
+fn bit_shift_right() {
+ let mut x = BigInt::from(4); //100
+ let y = BigInt::from(2);
+ let z = x.clone() >> y.clone(); //1
+ x >>= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 1);
+
+ let mut x = BigInt::from(10); //1010
+ let y = BigInt::from(1);
+ let z = x.clone() >> y.clone(); //101
+ x >>= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 5);
+
+ let mut x = BigInt::from(172); //10101100
+ let y = BigInt::from(0);
+ let z = x.clone() >> y.clone(); //10101100
+ x >>= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 172);
+
+ let mut x = BigInt::from(172); //10101100
+ let y = BigInt::from(10);
+ let z = x.clone() >> y.clone(); //0
+ x >>= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 0);
+
+ let mut x = BigInt::from(173); //10101101
+ let y = BigInt::from(1);
+ let z = x.clone() >> y.clone(); //1010110
+ x >>= y;
+ assert_eq!(x, z);
+ assert_eq!(z, 86);
+}
+
+#[test]
+fn hexadecimal() {
+ let x = BigInt::from(4);
+ assert_eq!(format!("{x:X}"), "4");
+ let x = BigInt::from(16);
+ assert_eq!(format!("{x:#X}"), "0x10");
+ let x = BigInt::from(-4);
+ assert_eq!(format!("{x:X}"), "-4");
+ let x = BigInt::from(-16);
+ assert_eq!(format!("{x:#X}"), "-0x10");
+
+ let x = BigInt::from(10);
+ assert_eq!(format!("{x:#X}"), "0xA");
+ let x = BigInt::from(172);
+ assert_eq!(format!("{x:X}"), "AC");
+ let x = BigInt::from(17220003931_u128);
+ assert_eq!(format!("{x:#X}"), "0x40264685B");
+
+ let x = BigInt::from(4);
+ assert_eq!(format!("{x:x}"), "4");
+ let x = BigInt::from(16);
+ assert_eq!(format!("{x:#x}"), "0x10");
+ let x = BigInt::from(10);
+ assert_eq!(format!("{x:#x}"), "0xa");
+ let x = BigInt::from(172);
+ assert_eq!(format!("{x:x}"), "ac");
+ let x = BigInt::from(17220003931_u128);
+ assert_eq!(format!("{x:#x}"), "0x40264685b");
+
+ let x = BigInt::from(11);
+ assert_eq!(format!("{x:#10X}"), " 0xB");
+ let x = BigInt::from(4);
+ assert_eq!(format!("{x:#x}"), "0x4");
+ let x = BigInt::from(4);
+ assert_eq!(format!("{x:X}"), "4");
+ let x = BigInt::from(4);
+ assert_eq!(format!("{x:0>10x}"), "0000000004");
+ let x = BigInt::from(10);
+ assert_eq!(format!("{x:#10x}"), " 0xa");
+ let x = BigInt::from(10);
+ assert_eq!(format!("{x:x>#010X}"), "xxxxxxx0xA");
+ let x = BigInt::from(172);
+ assert_eq!(format!("{x:X}"), "AC");
+ let x = BigInt::from(-17220003931_i64);
+ assert_eq!(format!("{x:#x}"), "-0x40264685b");
+}
+
+#[test]
+fn progtest_tests() {
+ let mut a = BigInt::from(10);
+ a += BigInt::from(20);
+ assert_eq!(a, 30);
+ a *= BigInt::from(5);
+ assert_eq!(a, 150);
+ let mut b = a.clone() + BigInt::from(3);
+ assert_eq!(b, 153);
+ b = a.clone() * BigInt::from(7);
+ assert_eq!(b, 1050);
+ assert_eq!(a, 150);
+ assert_eq!(format!("{a:X}"), "96");
+
+ a = BigInt::from(10);
+ a += BigInt::from(-20);
+ assert_eq!(a, -10);
+ a *= BigInt::from(5);
+ assert_eq!(a, -50);
+ b = a.clone() + BigInt::from(73);
+ assert_eq!(b, 23);
+ b = a.clone() * BigInt::from(-7);
+ assert_eq!(b, 350);
+ assert_eq!(a, -50);
+ assert_eq!(format!("{a:X}"), "-32");
+
+ a = BigInt::from(12345678901234567890_i128);
+ a += BigInt::from(-99999999999999999999_i128);
+ assert_eq!(a, -87654321098765432109_i128);
+ a *= BigInt::from(54321987654321987654_i128);
+ assert_eq!(a, "-4761556948575111126880627366067073182286");
+ a *= BigInt::from(0);
+ assert_eq!(a, 0);
+ a = BigInt::from(10);
+ b = a.clone() + 400;
+ assert_eq!(b, "410");
+ b = a.clone() * BigInt::from_str("15").unwrap_or_default();
+ assert_eq!(b, "150");
+ assert_eq!(a, "10");
+ assert_eq!(format!("{a:X}"), "A");
+
+ b = BigInt::from_str("1234").unwrap_or_default();
+ assert_eq!(format!("{b}"), "1234");
+ assert!(BigInt::from_str(" 12 34").is_err());
+ assert!(BigInt::from_str("999z").is_err());
+ assert!(BigInt::from_str("abcd").is_err());
+ assert!(BigInt::from_str("-xyz").is_err());
+ assert!(BigInt::from_str(":").is_err());
+ assert!(BigInt::from_str("%").is_err());
+ assert!(BigInt::from_str("- 758").is_err());
+ a = BigInt::from(42);
+ assert_eq!(a, 42);
+
+ a = BigInt::from(73786976294838206464_i128);
+ assert_eq!(a, 73786976294838206464_u128);
+ assert_eq!(format!("{a:X}"), "40000000000000000");
+ assert!(a < "1361129467683753853853498429727072845824");
+ assert!(a <= "1361129467683753853853498429727072845824");
+ assert!(a != "1361129467683753853853498429727072845824");
+ assert!(a <= 73786976294838206464_u128);
+ assert!(a >= 73786976294838206464_u128);
+ assert!(a == 73786976294838206464_u128);
+ assert!(!(a != 73786976294838206464_i128));
+ assert!(a <= 73786976294838206464_u128);
+ assert!(a >= 73786976294838206464_u128);
+ a = BigInt::from_str("2147483648").unwrap_or(BigInt::new());
+ assert!(a > -2147483648_i128);
+ assert!(a >= -2147483648_i128);
+ assert!(!(a == -2147483648_i128));
+ assert!(a != -2147483648_i128);
+ a = BigInt::from_str("-12345678").unwrap_or(BigInt::new());
+ assert!(a > -87654321);
+ assert!(a >= -87654321);
+ assert!(!(a == -87654321));
+ assert!(a != -87654321);
+}
diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs
new file mode 100644
index 0000000..242aad0
--- /dev/null
+++ b/tests/integration_tests.rs
@@ -0,0 +1,129 @@
+use rust_big_int::BigInt;
+use std::str::FromStr;
+
+#[test]
+fn catalan_number() {
+ let mut calculated_numbers: Vec = vec![1.into()];
+
+ for _i in 1..100 {
+ let number_pairs = calculated_numbers
+ .iter()
+ .zip(calculated_numbers.iter().rev());
+
+ let result: BigInt = number_pairs.fold(BigInt::default(), |result, (x, y)| {
+ x.clone() * y.clone() + result
+ });
+
+ calculated_numbers.push(result);
+ }
+
+ let catalan_numbers: Vec = vec![
+ BigInt::from_str("1").unwrap(),
+ BigInt::from_str("1").unwrap(),
+ BigInt::from_str("2").unwrap(),
+ BigInt::from_str("5").unwrap(),
+ BigInt::from_str("14").unwrap(),
+ BigInt::from_str("42").unwrap(),
+ BigInt::from_str("132").unwrap(),
+ BigInt::from_str("429").unwrap(),
+ BigInt::from_str("1430").unwrap(),
+ BigInt::from_str("4862").unwrap(),
+ BigInt::from_str("16796").unwrap(),
+ BigInt::from_str("58786").unwrap(),
+ BigInt::from_str("208012").unwrap(),
+ BigInt::from_str("742900").unwrap(),
+ BigInt::from_str("2674440").unwrap(),
+ BigInt::from_str("9694845").unwrap(),
+ BigInt::from_str("35357670").unwrap(),
+ BigInt::from_str("129644790").unwrap(),
+ BigInt::from_str("477638700").unwrap(),
+ BigInt::from_str("1767263190").unwrap(),
+ BigInt::from_str("6564120420").unwrap(),
+ BigInt::from_str("24466267020").unwrap(),
+ BigInt::from_str("91482563640").unwrap(),
+ BigInt::from_str("343059613650").unwrap(),
+ BigInt::from_str("1289904147324").unwrap(),
+ BigInt::from_str("4861946401452").unwrap(),
+ BigInt::from_str("18367353072152").unwrap(),
+ BigInt::from_str("69533550916004").unwrap(),
+ BigInt::from_str("263747951750360").unwrap(),
+ BigInt::from_str("1002242216651368").unwrap(),
+ BigInt::from_str("3814986502092304").unwrap(),
+ BigInt::from_str("14544636039226909").unwrap(),
+ BigInt::from_str("55534064877048198").unwrap(),
+ BigInt::from_str("212336130412243110").unwrap(),
+ BigInt::from_str("812944042149730764").unwrap(),
+ BigInt::from_str("3116285494907301262").unwrap(),
+ BigInt::from_str("11959798385860453492").unwrap(),
+ BigInt::from_str("45950804324621742364").unwrap(),
+ BigInt::from_str("176733862787006701400").unwrap(),
+ BigInt::from_str("680425371729975800390").unwrap(),
+ BigInt::from_str("2622127042276492108820").unwrap(),
+ BigInt::from_str("10113918591637898134020").unwrap(),
+ BigInt::from_str("39044429911904443959240").unwrap(),
+ BigInt::from_str("150853479205085351660700").unwrap(),
+ BigInt::from_str("583300119592996693088040").unwrap(),
+ BigInt::from_str("2257117854077248073253720").unwrap(),
+ BigInt::from_str("8740328711533173390046320").unwrap(),
+ BigInt::from_str("33868773757191046886429490").unwrap(),
+ BigInt::from_str("131327898242169365477991900").unwrap(),
+ BigInt::from_str("509552245179617138054608572").unwrap(),
+ BigInt::from_str("1978261657756160653623774456").unwrap(),
+ BigInt::from_str("7684785670514316385230816156").unwrap(),
+ BigInt::from_str("29869166945772625950142417512").unwrap(),
+ BigInt::from_str("116157871455782434250553845880").unwrap(),
+ BigInt::from_str("451959718027953471447609509424").unwrap(),
+ BigInt::from_str("1759414616608818870992479875972").unwrap(),
+ BigInt::from_str("6852456927844873497549658464312").unwrap(),
+ BigInt::from_str("26700952856774851904245220912664").unwrap(),
+ BigInt::from_str("104088460289122304033498318812080").unwrap(),
+ BigInt::from_str("405944995127576985730643443367112").unwrap(),
+ BigInt::from_str("1583850964596120042686772779038896").unwrap(),
+ BigInt::from_str("6182127958584855650487080847216336").unwrap(),
+ BigInt::from_str("24139737743045626825711458546273312").unwrap(),
+ BigInt::from_str("94295850558771979787935384946380125").unwrap(),
+ BigInt::from_str("368479169875816659479009042713546950").unwrap(),
+ BigInt::from_str("1440418573150919668872489894243865350").unwrap(),
+ BigInt::from_str("5632681584560312734993915705849145100").unwrap(),
+ BigInt::from_str("22033725021956517463358552614056949950").unwrap(),
+ BigInt::from_str("86218923998960285726185640663701108500").unwrap(),
+ BigInt::from_str("337485502510215975556783793455058624700").unwrap(),
+ BigInt::from_str("1321422108420282270489942177190229544600").unwrap(),
+ BigInt::from_str("5175569924646105559418940193995065716350").unwrap(),
+ BigInt::from_str("20276890389709399862928998568254641025700").unwrap(),
+ BigInt::from_str("79463489365077377841208237632349268884500").unwrap(),
+ BigInt::from_str("311496878311103321137536291518809134027240").unwrap(),
+ BigInt::from_str("1221395654430378811828760722007962130791020").unwrap(),
+ BigInt::from_str("4790408930363303911328386208394864461024520").unwrap(),
+ BigInt::from_str("18793142726809884575211361279087545193250040").unwrap(),
+ BigInt::from_str("73745243611532458459690151854647329239335600").unwrap(),
+ BigInt::from_str("289450081175264899454283846029490767264392230").unwrap(),
+ BigInt::from_str("1136359577947336271931632877004667456667613940").unwrap(),
+ BigInt::from_str("4462290049988320482463241297506133183499654740").unwrap(),
+ BigInt::from_str("17526585015616776834735140517915655636396234280").unwrap(),
+ BigInt::from_str("68854441132780194707888052034668647142985206100").unwrap(),
+ BigInt::from_str("270557451039395118028642463289168566420671280440").unwrap(),
+ BigInt::from_str("1063353702922273835973036658043476458723103404520").unwrap(),
+ BigInt::from_str("4180080073556524734514695828170907458428751314320").unwrap(),
+ BigInt::from_str("16435314834665426797069144960762886143367590394940").unwrap(),
+ BigInt::from_str("64633260585762914370496637486146181462681535261000").unwrap(),
+ BigInt::from_str("254224158304000796523953440778841647086547372026600").unwrap(),
+ BigInt::from_str("1000134600800354781929399250536541864362461089950800").unwrap(),
+ BigInt::from_str("3935312233584004685417853572763349509774031680023800").unwrap(),
+ BigInt::from_str("15487357822491889407128326963778343232013931127835600").unwrap(),
+ BigInt::from_str("60960876535340415751462563580829648891969728907438000").unwrap(),
+ BigInt::from_str("239993345518077005168915776623476723006280827488229600").unwrap(),
+ BigInt::from_str("944973797977428207852605870454939596837230758234904050").unwrap(),
+ BigInt::from_str("3721443204405954385563870541379246659709506697378694300").unwrap(),
+ BigInt::from_str("14657929356129575437016877846657032761712954950899755100").unwrap(),
+ BigInt::from_str("57743358069601357782187700608042856334020731624756611000").unwrap(),
+ BigInt::from_str("227508830794229349661819540395688853956041682601541047340").unwrap(),
+ BigInt::from_str("896519947090131496687170070074100632420837521538745909320").unwrap(),
+ ];
+
+ let result_check = calculated_numbers.iter().zip(catalan_numbers.iter());
+
+ for result in result_check {
+ assert_eq!(result.0, result.1);
+ }
+}