Reorganize somewhat, add more fraction tests
All checks were successful
timw4mail/rusty-numbers/pipeline/head This commit looks good
All checks were successful
timw4mail/rusty-numbers/pipeline/head This commit looks good
This commit is contained in:
parent
44467df38f
commit
cbf66916f9
@ -1,4 +1,4 @@
|
|||||||
//! Arbitrarily large integers
|
//! \[WIP\] Arbitrarily large integers
|
||||||
//!
|
//!
|
||||||
//! Traits to implement:
|
//! Traits to implement:
|
||||||
//! * Add
|
//! * Add
|
||||||
@ -14,7 +14,7 @@
|
|||||||
//! * SubAssign
|
//! * SubAssign
|
||||||
use crate::num::*;
|
use crate::num::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct BigInt {
|
pub struct BigInt {
|
||||||
inner: Vec<usize>,
|
inner: Vec<usize>,
|
||||||
sign: Sign,
|
sign: Sign,
|
||||||
@ -41,6 +41,18 @@ impl<T: Unsigned> From<T> for BigInt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&str> for BigInt {
|
||||||
|
fn from(_: &str) -> Self {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for BigInt {
|
||||||
|
fn from(_: String) -> Self {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl BigInt {
|
impl BigInt {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
123
src/lib.rs
123
src/lib.rs
@ -6,4 +6,125 @@
|
|||||||
pub mod bigint;
|
pub mod bigint;
|
||||||
pub mod num;
|
pub mod num;
|
||||||
pub mod rational;
|
pub mod rational;
|
||||||
pub mod seq;
|
|
||||||
|
/// Calculate a number in the fibonacci sequence,
|
||||||
|
/// using a lookup table for better worst-case performance.
|
||||||
|
///
|
||||||
|
/// Can calculate up to 186 using native unsigned 128 bit integers.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```rust
|
||||||
|
/// use rusty_numbers::fibonacci;
|
||||||
|
///
|
||||||
|
/// let valid = fibonacci(45); // Some(1134903170)
|
||||||
|
/// # assert_eq!(1134903170, fibonacci(45).unwrap());
|
||||||
|
/// # assert!(valid.is_some());
|
||||||
|
///
|
||||||
|
/// let invalid = fibonacci(187); // None
|
||||||
|
/// # assert!(invalid.is_none());
|
||||||
|
/// ```
|
||||||
|
pub fn fibonacci(n: usize) -> Option<u128> {
|
||||||
|
let mut table: Vec<u128> = vec![0, 1, 1, 2, 3, 5];
|
||||||
|
|
||||||
|
_fibonacci(n, &mut table)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Actual calculating function for `fibonacci`
|
||||||
|
#[inline]
|
||||||
|
fn _fibonacci(n: usize, table: &mut Vec<u128>) -> Option<u128> {
|
||||||
|
match table.get(n) {
|
||||||
|
Some(x) => Some(*x),
|
||||||
|
None => {
|
||||||
|
let a = _fibonacci(n - 1, table)?;
|
||||||
|
let b = _fibonacci(n - 2, table)?;
|
||||||
|
|
||||||
|
// Check for overflow when adding
|
||||||
|
let attempt = a.checked_add(b);
|
||||||
|
|
||||||
|
if let Some(current) = attempt {
|
||||||
|
table.insert(n, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
attempt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculate the value of a factorial,
|
||||||
|
/// using a lookup table for better worst-case performance.
|
||||||
|
///
|
||||||
|
/// Can calculate up to 34! using native unsigned 128 bit integers.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```rust
|
||||||
|
/// use rusty_numbers::factorial;
|
||||||
|
///
|
||||||
|
/// let valid = factorial(3); // Some(6)
|
||||||
|
/// # assert_eq!(6, valid.unwrap());
|
||||||
|
///
|
||||||
|
/// let invalid = factorial(35); // None
|
||||||
|
/// # assert!(invalid.is_none());
|
||||||
|
/// ```
|
||||||
|
pub fn factorial(n: usize) -> Option<u128> {
|
||||||
|
let mut table: Vec<u128> = vec![1, 1, 2];
|
||||||
|
|
||||||
|
_factorial(n, &mut table)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Actual Calculation function for factoral
|
||||||
|
#[inline]
|
||||||
|
fn _factorial(n: usize, table: &mut Vec<u128>) -> Option<u128> {
|
||||||
|
match table.get(n) {
|
||||||
|
// Vec<T>.get returns a Option with a reference to the value,
|
||||||
|
// so deref and wrap in Some() for proper return type
|
||||||
|
Some(x) => Some(*x),
|
||||||
|
None => {
|
||||||
|
// The ? suffix passes along the Option value
|
||||||
|
// to be handled later
|
||||||
|
// See: https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator
|
||||||
|
let prev = _factorial(n - 1, table)?;
|
||||||
|
|
||||||
|
// Do an overflow-checked multiply
|
||||||
|
let attempt = (n as u128).checked_mul(prev);
|
||||||
|
|
||||||
|
// If there isn't an overflow, add the result
|
||||||
|
// to the calculation table
|
||||||
|
if let Some(current) = attempt {
|
||||||
|
table.insert(n, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
attempt // Some(x) if no overflow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_factorial() {
|
||||||
|
assert_eq!(1, factorial(0).unwrap());
|
||||||
|
assert_eq!(1, factorial(1).unwrap());
|
||||||
|
assert_eq!(6, factorial(3).unwrap());
|
||||||
|
|
||||||
|
let res = factorial(34);
|
||||||
|
assert!(res.is_some());
|
||||||
|
|
||||||
|
let res = factorial(35);
|
||||||
|
assert!(res.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fibonacci() {
|
||||||
|
assert_eq!(0, fibonacci(0).unwrap());
|
||||||
|
assert_eq!(1, fibonacci(1).unwrap());
|
||||||
|
assert_eq!(1, fibonacci(2).unwrap());
|
||||||
|
|
||||||
|
let res = fibonacci(186);
|
||||||
|
assert!(res.is_some());
|
||||||
|
|
||||||
|
let res = fibonacci(187);
|
||||||
|
assert!(res.is_none());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@ use core::ops::{
|
|||||||
Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
|
Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Represents the sign of a rational number
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum Sign {
|
pub enum Sign {
|
||||||
/// Greater than zero, or zero
|
/// Greater than zero, or zero
|
||||||
@ -285,6 +286,12 @@ impl_signed!(i8, i16, i32, i64, i128, isize);
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_los() {
|
||||||
|
assert_eq!(4u8.left_overflowing_sub(2).0, 2u8);
|
||||||
|
assert_eq!(0u8.left_overflowing_sub(2).0, 2u8);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_gcd() {
|
fn test_gcd() {
|
||||||
assert_eq!(u8::gcd(2, 3), 1);
|
assert_eq!(u8::gcd(2, 3), 1);
|
||||||
|
@ -6,6 +6,23 @@ use std::cmp::{Ord, Ordering, PartialOrd};
|
|||||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||||
|
|
||||||
/// Type representing a fraction
|
/// Type representing a fraction
|
||||||
|
///
|
||||||
|
/// There are three basic constructors:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use rusty_numbers::frac;
|
||||||
|
/// use rusty_numbers::rational::Frac;
|
||||||
|
///
|
||||||
|
/// // Macro
|
||||||
|
/// let reduced_macro = frac!(3 / 4);
|
||||||
|
///
|
||||||
|
/// // Frac::new (called by the macro)
|
||||||
|
/// let reduced = Frac::new(3, 4);
|
||||||
|
/// # assert_eq!(reduced_macro, reduced);
|
||||||
|
///
|
||||||
|
/// // Frac::new_unreduced
|
||||||
|
/// let unreduced = Frac::new_unreduced(4, 16);
|
||||||
|
/// ```
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub struct Frac<T: Unsigned = usize> {
|
pub struct Frac<T: Unsigned = usize> {
|
||||||
numer: T,
|
numer: T,
|
||||||
@ -16,12 +33,16 @@ pub struct Frac<T: Unsigned = usize> {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
/// Create a [Frac](rational/struct.Frac.html) type with signed or unsigned number literals
|
/// Create a [Frac](rational/struct.Frac.html) type with signed or unsigned number literals
|
||||||
///
|
///
|
||||||
/// Accepts:
|
/// Example:
|
||||||
|
/// ```
|
||||||
|
/// use rusty_numbers::frac;
|
||||||
///
|
///
|
||||||
/// ```no-run
|
/// // Proper fractions
|
||||||
/// // Fractions
|
|
||||||
/// frac!(1 / 3);
|
/// frac!(1 / 3);
|
||||||
///
|
///
|
||||||
|
/// // Improper fractions
|
||||||
|
/// frac!(4 / 3);
|
||||||
|
///
|
||||||
/// // Whole numbers
|
/// // Whole numbers
|
||||||
/// frac!(5u8);
|
/// frac!(5u8);
|
||||||
///
|
///
|
||||||
@ -116,7 +137,7 @@ impl<T: Unsigned> Frac<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the fraction to its simplest form
|
/// Convert the fraction to its simplest form
|
||||||
fn reduce(mut self) -> Self {
|
pub fn reduce(mut self) -> Self {
|
||||||
let gcd = T::gcd(self.numer, self.denom);
|
let gcd = T::gcd(self.numer, self.denom);
|
||||||
self.numer /= gcd;
|
self.numer /= gcd;
|
||||||
self.denom /= gcd;
|
self.denom /= gcd;
|
||||||
@ -198,7 +219,7 @@ where
|
|||||||
T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>,
|
T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>,
|
||||||
{
|
{
|
||||||
fn mul_assign(&mut self, rhs: Self) {
|
fn mul_assign(&mut self, rhs: Self) {
|
||||||
*self = self.clone() * rhs
|
*self = *self * rhs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +243,7 @@ where
|
|||||||
T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>,
|
T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>,
|
||||||
{
|
{
|
||||||
fn div_assign(&mut self, rhs: Self) {
|
fn div_assign(&mut self, rhs: Self) {
|
||||||
*self = self.clone() / rhs
|
*self = *self / rhs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +289,7 @@ where
|
|||||||
T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>,
|
T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>,
|
||||||
{
|
{
|
||||||
fn add_assign(&mut self, rhs: Self) {
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
*self = self.clone() + rhs
|
*self = *self + rhs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +324,11 @@ where
|
|||||||
let sign = Self::get_sign(a, b, FracOp::Subtraction);
|
let sign = Self::get_sign(a, b, FracOp::Subtraction);
|
||||||
let res = Self::raw(numer, denom, sign);
|
let res = Self::raw(numer, denom, sign);
|
||||||
|
|
||||||
if overflowed { -res } else { res }
|
if overflowed {
|
||||||
|
-res
|
||||||
|
} else {
|
||||||
|
res
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +337,7 @@ where
|
|||||||
T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>,
|
T: Unsigned + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>,
|
||||||
{
|
{
|
||||||
fn sub_assign(&mut self, rhs: Self) {
|
fn sub_assign(&mut self, rhs: Self) {
|
||||||
*self = self.clone() - rhs
|
*self = *self - rhs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,47 +354,6 @@ impl<T: Unsigned> Neg for Frac<T> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mul_test() {
|
|
||||||
let frac1 = frac!(1 / 3u8);
|
|
||||||
let frac2 = frac!(2u8 / 3);
|
|
||||||
|
|
||||||
let expected = frac!(2u8 / 9);
|
|
||||||
|
|
||||||
assert_eq!(frac1 * frac2, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn add_test() {
|
|
||||||
assert_eq!(frac!(5 / 6), frac!(1 / 3) + frac!(1 / 2), "1/3 + 1/2");
|
|
||||||
assert_eq!(frac!(1 / 3), frac!(2 / 3) + -frac!(1 / 3), "2/3 + -1/3");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn sub_test() {
|
|
||||||
assert_eq!(4u8.left_overflowing_sub(2).0, 2u8);
|
|
||||||
assert_eq!(0u8.left_overflowing_sub(2).0, 2u8);
|
|
||||||
assert_eq!(frac!(1 / 6), frac!(1 / 2) - frac!(1 / 3), "1/2 - 1/3");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn cmp_test() {
|
|
||||||
assert!(-frac!(5 / 3) < frac!(1 / 10_000));
|
|
||||||
assert!(frac!(1 / 10_000) > -frac!(10));
|
|
||||||
assert!(frac!(1 / 3) < frac!(1 / 2));
|
|
||||||
assert_eq!(frac!(1 / 2), frac!(3 / 6));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn negative_fractions() {
|
|
||||||
assert_eq!(-frac!(1 / 3), -frac!(2 / 3) + frac!(1 / 3), "-2/3 + 1/3");
|
|
||||||
assert_eq!(frac!(1), frac!(1 / 3) - -frac!(2 / 3), "1/3 - -2/3");
|
|
||||||
assert_eq!(-frac!(1), -frac!(2 / 3) - frac!(1 / 3), "-2/3 - +1/3");
|
|
||||||
assert_eq!(-frac!(1), -frac!(2 / 3) + -frac!(1 / 3), "-2/3 + -1/3");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn macro_test() {
|
fn macro_test() {
|
||||||
let frac1 = frac!(1 / 3);
|
let frac1 = frac!(1 / 3);
|
||||||
|
123
src/seq.rs
123
src/seq.rs
@ -1,123 +0,0 @@
|
|||||||
//! Sequences and other 'stock' math functions
|
|
||||||
|
|
||||||
/// Calculate a number in the fibonacci sequence,
|
|
||||||
/// using a lookup table for better worst-case performance.
|
|
||||||
///
|
|
||||||
/// Can calculate up to 186 using native unsigned 128 bit integers.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
/// ```rust
|
|
||||||
/// use rusty_numbers::seq::fibonacci;
|
|
||||||
///
|
|
||||||
/// let valid = fibonacci(45); // Some(1134903170)
|
|
||||||
/// # assert_eq!(1134903170, fibonacci(45).unwrap());
|
|
||||||
/// # assert!(valid.is_some());
|
|
||||||
///
|
|
||||||
/// let invalid = fibonacci(187); // None
|
|
||||||
/// # assert!(invalid.is_none());
|
|
||||||
/// ```
|
|
||||||
pub fn fibonacci(n: usize) -> Option<u128> {
|
|
||||||
let mut table: Vec<u128> = vec![0, 1, 1, 2, 3, 5];
|
|
||||||
|
|
||||||
_fibonacci(n, &mut table)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Actual calculating function for `fibonacci`
|
|
||||||
#[inline]
|
|
||||||
fn _fibonacci(n: usize, table: &mut Vec<u128>) -> Option<u128> {
|
|
||||||
match table.get(n) {
|
|
||||||
Some(x) => Some(*x),
|
|
||||||
None => {
|
|
||||||
let a = _fibonacci(n - 1, table)?;
|
|
||||||
let b = _fibonacci(n - 2, table)?;
|
|
||||||
|
|
||||||
// Check for overflow when adding
|
|
||||||
let attempt = a.checked_add(b);
|
|
||||||
|
|
||||||
if let Some(current) = attempt {
|
|
||||||
table.insert(n, current);
|
|
||||||
}
|
|
||||||
|
|
||||||
attempt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Calculate the value of a factorial,
|
|
||||||
/// using a lookup table for better worst-case performance.
|
|
||||||
///
|
|
||||||
/// Can calculate up to 34! using native unsigned 128 bit integers.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
/// ```rust
|
|
||||||
/// use rusty_numbers::seq::factorial;
|
|
||||||
///
|
|
||||||
/// let valid = factorial(3); // Some(6)
|
|
||||||
/// # assert_eq!(6, valid.unwrap());
|
|
||||||
///
|
|
||||||
/// let invalid = factorial(35); // None
|
|
||||||
/// # assert!(invalid.is_none());
|
|
||||||
/// ```
|
|
||||||
pub fn factorial(n: usize) -> Option<u128> {
|
|
||||||
let mut table: Vec<u128> = vec![1, 1, 2];
|
|
||||||
|
|
||||||
_factorial(n, &mut table)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Actual Calculation function for factoral
|
|
||||||
#[inline]
|
|
||||||
fn _factorial(n: usize, table: &mut Vec<u128>) -> Option<u128> {
|
|
||||||
match table.get(n) {
|
|
||||||
// Vec<T>.get returns a Option with a reference to the value,
|
|
||||||
// so deref and wrap in Some() for proper return type
|
|
||||||
Some(x) => Some(*x),
|
|
||||||
None => {
|
|
||||||
// The ? suffix passes along the Option value
|
|
||||||
// to be handled later
|
|
||||||
// See: https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator
|
|
||||||
let prev = _factorial(n - 1, table)?;
|
|
||||||
|
|
||||||
// Do an overflow-checked multiply
|
|
||||||
let attempt = (n as u128).checked_mul(prev);
|
|
||||||
|
|
||||||
// If there isn't an overflow, add the result
|
|
||||||
// to the calculation table
|
|
||||||
if let Some(current) = attempt {
|
|
||||||
table.insert(n, current);
|
|
||||||
}
|
|
||||||
|
|
||||||
attempt // Some(x) if no overflow
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_factorial() {
|
|
||||||
assert_eq!(1, factorial(0).unwrap());
|
|
||||||
assert_eq!(1, factorial(1).unwrap());
|
|
||||||
assert_eq!(6, factorial(3).unwrap());
|
|
||||||
|
|
||||||
let res = factorial(34);
|
|
||||||
assert!(res.is_some());
|
|
||||||
|
|
||||||
let res = factorial(35);
|
|
||||||
assert!(res.is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_fibonacci() {
|
|
||||||
assert_eq!(0, fibonacci(0).unwrap());
|
|
||||||
assert_eq!(1, fibonacci(1).unwrap());
|
|
||||||
assert_eq!(1, fibonacci(2).unwrap());
|
|
||||||
|
|
||||||
let res = fibonacci(186);
|
|
||||||
assert!(res.is_some());
|
|
||||||
|
|
||||||
let res = fibonacci(187);
|
|
||||||
assert!(res.is_none());
|
|
||||||
}
|
|
||||||
}
|
|
56
tests/fractions.rs
Normal file
56
tests/fractions.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
use rusty_numbers::frac;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mul_test() {
|
||||||
|
let frac1 = frac!(1 / 3u8);
|
||||||
|
let frac2 = frac!(2u8 / 3);
|
||||||
|
|
||||||
|
let expected = frac!(2u8 / 9);
|
||||||
|
|
||||||
|
assert_eq!(frac1 * frac2, expected);
|
||||||
|
|
||||||
|
assert_eq!(frac!(0), frac!(0) * frac!(5 / 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn div_test() {
|
||||||
|
assert_eq!(frac!(1), frac!(1 / 3) / frac!(1 / 3));
|
||||||
|
assert_eq!(frac!(1 / 9), frac!(1 / 3) / frac!(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add_test() {
|
||||||
|
assert_eq!(frac!(5 / 8), frac!(5 / 8) + frac!(0));
|
||||||
|
assert_eq!(frac!(5 / 6), frac!(1 / 3) + frac!(1 / 2), "1/3 + 1/2");
|
||||||
|
assert_eq!(frac!(1 / 3), frac!(2 / 3) + -frac!(1 / 3), "2/3 + -1/3");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sub_test() {
|
||||||
|
assert_eq!(frac!(5 / 8), frac!(5 / 8) - frac!(0));
|
||||||
|
assert_eq!(frac!(1 / 6), frac!(1 / 2) - frac!(1 / 3), "1/2 - 1/3");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cmp_test() {
|
||||||
|
assert!(frac!(0) < frac!(1));
|
||||||
|
assert!(-frac!(5 / 3) < frac!(1 / 10_000));
|
||||||
|
assert!(frac!(1 / 10_000) > -frac!(10));
|
||||||
|
assert!(frac!(1 / 3) < frac!(1 / 2));
|
||||||
|
assert_eq!(frac!(1 / 2), frac!(3 / 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn negative_fractions() {
|
||||||
|
assert_eq!(-frac!(1 / 3), -frac!(2 / 3) + frac!(1 / 3), "-2/3 + 1/3");
|
||||||
|
assert_eq!(frac!(1), frac!(1 / 3) - -frac!(2 / 3), "1/3 - -2/3");
|
||||||
|
assert_eq!(-frac!(1), -frac!(2 / 3) - frac!(1 / 3), "-2/3 - +1/3");
|
||||||
|
assert_eq!(-frac!(1), -frac!(2 / 3) + -frac!(1 / 3), "-2/3 + -1/3");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn negative_mul_div() {
|
||||||
|
assert_eq!(-frac!(1 / 12), -frac!(1 / 3) * frac!(1 / 4));
|
||||||
|
assert_eq!(-frac!(1 / 12), frac!(1 / 3) * -frac!(1 / 4));
|
||||||
|
assert_eq!(frac!(1 / 12), -frac!(1 / 3) * -frac!(1 / 4));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user