Add makefile for code coverage operations, increase code coverage
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
cbf66916f9
commit
3323c2ff23
14
Makefile
Normal file
14
Makefile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
coverage: coverage.html
|
||||||
|
|
||||||
|
coverage.html: coverage-report
|
||||||
|
|
||||||
|
generate-coverage:
|
||||||
|
cargo tarpaulin --out Xml
|
||||||
|
|
||||||
|
coverage-report: generate-coverage
|
||||||
|
pycobertura show --format html --output coverage.html cobertura.xml
|
||||||
|
|
||||||
|
clean:
|
||||||
|
cargo clean
|
||||||
|
rm cobertura.xml
|
||||||
|
rm coverage.html
|
@ -3,6 +3,7 @@
|
|||||||
//! Playin' with Numerics in Rust
|
//! Playin' with Numerics in Rust
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
pub mod bigint;
|
pub mod bigint;
|
||||||
pub mod num;
|
pub mod num;
|
||||||
pub mod rational;
|
pub mod rational;
|
||||||
@ -99,6 +100,7 @@ fn _factorial(n: usize, table: &mut Vec<u128>) -> Option<u128> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
59
src/num.rs
59
src/num.rs
@ -9,6 +9,7 @@ use core::ops::{
|
|||||||
|
|
||||||
/// Represents the sign of a rational number
|
/// Represents the sign of a rational number
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum Sign {
|
pub enum Sign {
|
||||||
/// Greater than zero, or zero
|
/// Greater than zero, or zero
|
||||||
Positive,
|
Positive,
|
||||||
@ -51,17 +52,11 @@ pub trait Num:
|
|||||||
+ Sub
|
+ Sub
|
||||||
+ SubAssign
|
+ SubAssign
|
||||||
{
|
{
|
||||||
/// Is this number type signed?
|
fn abs(self) -> Self {
|
||||||
fn is_signed(&self) -> bool {
|
self
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Float primitive
|
|
||||||
pub trait Float: Num {
|
|
||||||
fn is_neg(self) -> bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Integer primitive
|
/// Integer primitive
|
||||||
pub trait Int:
|
pub trait Int:
|
||||||
Num
|
Num
|
||||||
@ -95,10 +90,6 @@ pub trait Int:
|
|||||||
/// overflow would occur. If an overflow would have occurred then the wrapped value is returned.
|
/// overflow would occur. If an overflow would have occurred then the wrapped value is returned.
|
||||||
fn left_overflowing_sub(self, rhs: Self) -> (Self, bool);
|
fn left_overflowing_sub(self, rhs: Self) -> (Self, bool);
|
||||||
|
|
||||||
/// Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic
|
|
||||||
/// overflow would occur. If an overflow would have occurred then the wrapped value is returned.
|
|
||||||
fn left_overflowing_mul(self, rhs: Self) -> (Self, bool);
|
|
||||||
|
|
||||||
/// Convert to an unsigned number
|
/// Convert to an unsigned number
|
||||||
///
|
///
|
||||||
/// A meaningless operation when implemented on an
|
/// A meaningless operation when implemented on an
|
||||||
@ -114,14 +105,6 @@ pub trait Unsigned: Int {
|
|||||||
|
|
||||||
/// Find the least common multiple of two numbers
|
/// Find the least common multiple of two numbers
|
||||||
fn lcm(a: Self, b: Self) -> Self;
|
fn lcm(a: Self, b: Self) -> Self;
|
||||||
|
|
||||||
fn is_signed(self) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_unsigned(self) -> Self {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Trait representing signed integer primitives
|
/// A Trait representing signed integer primitives
|
||||||
@ -135,18 +118,6 @@ macro_rules! impl_num {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_float {
|
|
||||||
($( $Type: ty ),* ) => {
|
|
||||||
$(
|
|
||||||
impl Float for $Type {
|
|
||||||
fn is_neg(self) -> bool {
|
|
||||||
self < 0.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_int {
|
macro_rules! impl_int {
|
||||||
($(($type: ty, $un_type: ty)),* ) => {
|
($(($type: ty, $un_type: ty)),* ) => {
|
||||||
$(
|
$(
|
||||||
@ -163,29 +134,15 @@ macro_rules! impl_int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_neg(self) -> bool {
|
fn is_neg(self) -> bool {
|
||||||
if self.is_signed() == false {
|
self < 0
|
||||||
false
|
|
||||||
} else {
|
|
||||||
self < 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_unsigned(self) -> $un_type {
|
fn to_unsigned(self) -> $un_type {
|
||||||
|
let abs = <$type>::abs(self);
|
||||||
// Converting from signed to unsigned should always be safe
|
// Converting from signed to unsigned should always be safe
|
||||||
// when using the absolute value, especially since I'm converting
|
// when using the absolute value, especially since I'm converting
|
||||||
// between the same bit size
|
// between the same bit size
|
||||||
<$un_type>::try_from(self).unwrap()
|
<$un_type>::try_from(abs).unwrap()
|
||||||
}
|
|
||||||
|
|
||||||
fn left_overflowing_mul(self, rhs: Self) -> (Self, bool) {
|
|
||||||
let (res, overflow) = <$type>::overflowing_mul(self, rhs);
|
|
||||||
let res = if overflow {
|
|
||||||
<$type>::max_value() - res + 1
|
|
||||||
} else {
|
|
||||||
res
|
|
||||||
};
|
|
||||||
|
|
||||||
(res, overflow)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn left_overflowing_sub(self, rhs: Self) -> (Self, bool) {
|
fn left_overflowing_sub(self, rhs: Self) -> (Self, bool) {
|
||||||
@ -263,8 +220,7 @@ macro_rules! impl_signed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_num!(i8, u8, i16, u16, f32, i32, u32, f64, i64, u64, i128, u128, isize, usize);
|
impl_num!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
|
||||||
impl_float!(f32, f64);
|
|
||||||
impl_int!(
|
impl_int!(
|
||||||
(i8, u8),
|
(i8, u8),
|
||||||
(u8, u8),
|
(u8, u8),
|
||||||
@ -306,5 +262,6 @@ mod tests {
|
|||||||
assert_eq!(u16::lcm(2, 3), 6);
|
assert_eq!(u16::lcm(2, 3), 6);
|
||||||
assert_eq!(usize::lcm(15, 30), 30);
|
assert_eq!(usize::lcm(15, 30), 30);
|
||||||
assert_eq!(u128::lcm(1, 5), 5);
|
assert_eq!(u128::lcm(1, 5), 5);
|
||||||
|
assert_eq!(0u8, u8::lcm(0, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,23 +117,21 @@ impl<T: Unsigned> Frac<T> {
|
|||||||
|
|
||||||
/// Determine the output sign given the two input signs
|
/// Determine the output sign given the two input signs
|
||||||
fn get_sign(a: Self, b: Self, op: FracOp) -> Sign {
|
fn get_sign(a: Self, b: Self, op: FracOp) -> Sign {
|
||||||
if op == FracOp::Addition {
|
let mut output = Sign::default();
|
||||||
return if a.sign == Positive && b.sign == Positive {
|
|
||||||
Positive
|
if op == FracOp::Addition && !(a.sign == Positive && b.sign == Positive) {
|
||||||
} else {
|
output = Negative;
|
||||||
Negative
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.sign != b.sign {
|
if a.sign != b.sign {
|
||||||
if op == FracOp::Subtraction && b.sign == Negative {
|
output = if op == FracOp::Subtraction && b.sign == Negative {
|
||||||
Positive
|
Positive
|
||||||
} else {
|
} else {
|
||||||
Negative
|
Negative
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Positive
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the fraction to its simplest form
|
/// Convert the fraction to its simplest form
|
||||||
@ -189,12 +187,6 @@ where
|
|||||||
b.numer *= y;
|
b.numer *= y;
|
||||||
b.denom *= y;
|
b.denom *= y;
|
||||||
|
|
||||||
debug_assert_eq!(
|
|
||||||
a.denom, b.denom,
|
|
||||||
"Denominators should be equal here. \n{:#?}\n{:#?}\n{:?}\n{:?}",
|
|
||||||
a, b, x, y
|
|
||||||
);
|
|
||||||
|
|
||||||
a.numer.cmp(&b.numer)
|
a.numer.cmp(&b.numer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -352,8 +344,17 @@ impl<T: Unsigned> Neg for Frac<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "Fraction can not have a zero denominator")]
|
||||||
|
fn zero_denom() {
|
||||||
|
Frac::raw(1u8, 0u8, Sign::default());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn macro_test() {
|
fn macro_test() {
|
||||||
let frac1 = frac!(1 / 3);
|
let frac1 = frac!(1 / 3);
|
||||||
@ -366,5 +367,9 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(frac!(3 / 2), frac!(1 1/2));
|
assert_eq!(frac!(3 / 2), frac!(1 1/2));
|
||||||
assert_eq!(frac!(3 / 1), frac!(3));
|
assert_eq!(frac!(3 / 1), frac!(3));
|
||||||
|
|
||||||
|
assert_eq!(-frac!(1/2), frac!(-1/2));
|
||||||
|
assert_eq!(-frac!(1/2), frac!(1/-2));
|
||||||
|
assert_eq!(frac!(1/2), frac!(-1/-2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#![cfg_attr(tarpaulin, skip)]
|
||||||
|
|
||||||
use rusty_numbers::frac;
|
use rusty_numbers::frac;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -33,6 +35,7 @@ fn sub_test() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cmp_test() {
|
fn cmp_test() {
|
||||||
|
assert!(frac!(1/2) <= frac!(1/2));
|
||||||
assert!(frac!(0) < frac!(1));
|
assert!(frac!(0) < frac!(1));
|
||||||
assert!(-frac!(5 / 3) < frac!(1 / 10_000));
|
assert!(-frac!(5 / 3) < frac!(1 / 10_000));
|
||||||
assert!(frac!(1 / 10_000) > -frac!(10));
|
assert!(frac!(1 / 10_000) > -frac!(10));
|
||||||
@ -54,3 +57,32 @@ 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));
|
assert_eq!(frac!(1 / 12), -frac!(1 / 3) * -frac!(1 / 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "Fraction can not have a zero denominator")]
|
||||||
|
fn zero_denom() {
|
||||||
|
frac!(1 / 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn op_assign() {
|
||||||
|
// Addition
|
||||||
|
let mut quart = frac!(1/4);
|
||||||
|
quart += frac!(1/4);
|
||||||
|
assert_eq!(frac!(1/2), quart);
|
||||||
|
|
||||||
|
// Subtraction
|
||||||
|
let mut half = frac!(1/2);
|
||||||
|
half -= frac!(1/4);
|
||||||
|
assert_eq!(frac!(1/4), half);
|
||||||
|
|
||||||
|
// Multiplication
|
||||||
|
let mut half = frac!(1/2);
|
||||||
|
half *= frac!(1/2);
|
||||||
|
assert_eq!(frac!(1/4), half);
|
||||||
|
|
||||||
|
// Division
|
||||||
|
let mut quart = frac!(1/4);
|
||||||
|
quart /= frac!(4);
|
||||||
|
assert_eq!(frac!(1/16), quart);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user