Some refactoring based on linting suggestions

This commit is contained in:
Timothy Warren 2021-12-08 09:57:27 -05:00
parent 4ac159c603
commit d77a136e5c
5 changed files with 81 additions and 62 deletions

4
Cargo.lock generated
View File

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "rusty-numbers"
version = "0.1.0"
version = "0.2.0"

View File

@ -1,8 +1,8 @@
[package]
name = "rusty-numbers"
version = "0.1.0"
version = "0.2.0"
authors = ["Timothy J. Warren <tim@timshomepage.net>"]
edition = "2018"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -1,7 +1,7 @@
#![allow(unused_variables)]
//! \[WIP\] Arbitrarily large integers
use crate::num::FracOp;
use crate::num::Sign::{self, Positive, Negative};
use crate::num::Sign::{self, Negative, Positive};
#[cfg(all(feature = "alloc", not(feature = "std")))]
extern crate alloc;
@ -84,6 +84,7 @@ impl BigInt {
}
/// Create a new BigInt, with the specified inner capacity
#[must_use]
pub fn with_capacity(size: usize) -> Self {
Self {
inner: Vec::with_capacity(size),
@ -250,6 +251,7 @@ impl BigInt {
impl Add for BigInt {
type Output = Self;
#[must_use]
fn add(self, rhs: Self) -> Self::Output {
// If the sign of one input differs,
// subtraction is equivalent
@ -297,6 +299,7 @@ impl Add for BigInt {
impl Sub for BigInt {
type Output = Self;
#[must_use]
fn sub(self, rhs: Self) -> Self::Output {
let digits = Self::get_ceil_digit_count(&self, &rhs);
let mut out = BigInt::with_capacity(digits);
@ -344,6 +347,7 @@ impl Sub for BigInt {
impl Mul for BigInt {
type Output = Self;
#[must_use]
fn mul(self, rhs: Self) -> Self::Output {
let input_digits = Self::get_ceil_digit_count(&self, &rhs);
@ -357,6 +361,7 @@ impl Mul for BigInt {
impl Div for BigInt {
type Output = Self;
#[must_use]
fn div(self, rhs: Self) -> Self::Output {
todo!()
}
@ -365,6 +370,7 @@ impl Div for BigInt {
impl Rem for BigInt {
type Output = Self;
#[must_use]
fn rem(self, rhs: Self) -> Self::Output {
todo!()
}
@ -409,6 +415,7 @@ impl Neg for BigInt {
type Output = Self;
/// Flip the sign of the current `BigInt` value
#[must_use]
fn neg(mut self) -> Self::Output {
self.sign = !self.sign;
@ -524,8 +531,7 @@ macro_rules! impl_from_larger {
if quotient == 0 {
Self::from(rem as usize)
} else {
let mut inner: Vec<usize> = Vec::new();
inner.push(rem as usize);
let mut inner: Vec<usize> = vec![rem as usize];
loop {
rem = quotient % target_radix;
@ -558,8 +564,7 @@ macro_rules! impl_from_larger {
if quotient == 0 {
Self::from(rem as usize)
} else {
let mut inner: Vec<usize> = Vec::new();
inner.push(rem as usize);
let mut inner: Vec<usize> = vec![rem as usize];
loop {
rem = quotient % target_radix;
@ -587,24 +592,28 @@ macro_rules! impl_ord_literal {
($($prim: ty),+) => {
$(
impl PartialEq<$prim> for BigInt {
#[must_use]
fn eq(&self, other: &$prim) -> bool {
self == &BigInt::from(*other)
}
}
impl PartialEq<BigInt> for $prim {
#[must_use]
fn eq(&self, other: &BigInt) -> bool {
&BigInt::from(*self) == other
}
}
impl PartialOrd<$prim> for BigInt {
#[must_use]
fn partial_cmp(&self, other: &$prim) -> Option<Ordering> {
self.partial_cmp(&BigInt::from(*other))
}
}
impl PartialOrd<BigInt> for $prim {
#[must_use]
fn partial_cmp(&self, other: &BigInt) -> Option<Ordering> {
(&BigInt::from(*self)).partial_cmp(other)
}
@ -763,7 +772,7 @@ mod tests {
a -= b;
assert_eq!(a.inner, vec![core::usize::MAX, core::usize::MAX]);
assert_eq!(a.inner, vec![usize::MAX, usize::MAX]);
}
#[test]
@ -936,7 +945,7 @@ mod tests {
#[should_panic]
fn test_from_str_large() {
let str = "ZYXWVUTSRQPONMLKJIHGFEDCBA987654321";
BigInt::from(str);
let _ = BigInt::from(str);
}
#[test]
@ -950,7 +959,7 @@ mod tests {
#[should_panic]
fn test_from_string_large() {
let str = String::from("ZYXWVUTSRQPONMLKJIHGFEDCBA987654321");
BigInt::from(str);
let _ = BigInt::from(str);
}
#[test]

View File

@ -16,4 +16,3 @@ extern crate std;
pub mod bigint;
pub mod num;
pub mod rational;

View File

@ -1,7 +1,7 @@
//! # Rational Numbers (fractions)
use crate::num::Sign::*;
use crate::num::*;
use crate::num::Sign::{Negative, Positive};
use crate::num::{FracOp, Int, Sign, Unsigned};
use core::cmp::{Ord, Ordering, PartialOrd};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
@ -25,8 +25,8 @@ use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAss
/// ```
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Frac<T: Unsigned = usize> {
numer: T,
denom: T,
numerator: T,
denominator: T,
sign: Sign,
}
@ -66,12 +66,18 @@ impl<T: Unsigned> Frac<T> {
///
/// Generally, you will probably prefer to use the [frac!](../macro.frac.html) macro
/// instead, as that is easier for mixed fractions and whole numbers
///
/// # Panics
/// if `d` is 0, this constructor will panic
pub fn new<N: Int<Un = T>>(n: N, d: N) -> Frac<T> {
Self::new_unreduced(n, d).reduce()
}
/// Create a new rational number from signed or unsigned arguments
/// where the resulting fraction is not reduced
///
/// # Panics
/// if `d` is 0, this constructor will panic
pub fn new_unreduced<N: Int<Un = T>>(n: N, d: N) -> Frac<T> {
if d.is_zero() {
panic!("Fraction can not have a zero denominator");
@ -88,21 +94,24 @@ impl<T: Unsigned> Frac<T> {
}
// Convert the possibly signed arguments to unsigned values
let numer = n.to_unsigned();
let denom = d.to_unsigned();
let numerator = n.to_unsigned();
let denominator = d.to_unsigned();
Frac { numer, denom, sign }
Frac { numerator, denominator, sign }
}
/// Create a new rational from all the raw parts
///
/// # Panics
/// if `d` is 0, this constructor will panic
fn raw(n: T, d: T, s: Sign) -> Frac<T> {
if d.is_zero() {
panic!("Fraction can not have a zero denominator");
}
Frac {
numer: n,
denom: d,
numerator: n,
denominator: d,
sign: s,
}
.reduce()
@ -129,9 +138,9 @@ impl<T: Unsigned> Frac<T> {
/// Convert the fraction to its simplest form
pub fn reduce(mut self) -> Self {
let gcd = T::gcd(self.numer, self.denom);
self.numer /= gcd;
self.denom /= gcd;
let gcd = T::gcd(self.numerator, self.denominator);
self.numerator /= gcd;
self.denominator /= gcd;
self
}
@ -153,28 +162,28 @@ impl<T: Unsigned> Ord for Frac<T> {
};
}
if self.denom == other.denom {
return self.numer.cmp(&other.numer);
if self.denominator == other.denominator {
return self.numerator.cmp(&other.numerator);
}
let mut a = self.reduce();
let mut b = other.reduce();
if a.denom == b.denom {
return a.numer.cmp(&b.numer);
if a.denominator == b.denominator {
return a.numerator.cmp(&b.numerator);
}
let lcm = T::lcm(self.denom, other.denom);
let x = lcm / self.denom;
let y = lcm / other.denom;
let lcm = T::lcm(self.denominator, other.denominator);
let x = lcm / self.denominator;
let y = lcm / other.denominator;
a.numer *= x;
a.denom *= x;
a.numerator *= x;
a.denominator *= x;
b.numer *= y;
b.denom *= y;
b.numerator *= y;
b.denominator *= y;
a.numer.cmp(&b.numer)
a.numerator.cmp(&b.numerator)
}
}
@ -182,17 +191,17 @@ impl<T: Unsigned> Mul for Frac<T> {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
let numer = self.numer * rhs.numer;
let denom = self.denom * rhs.denom;
let numerator = self.numerator * rhs.numerator;
let denominator = self.denominator * rhs.denominator;
let sign = Self::get_sign(self, rhs, FracOp::Other);
Self::raw(numer, denom, sign)
Self::raw(numerator, denominator, sign)
}
}
impl<T: Unsigned> MulAssign for Frac<T> {
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs
*self = *self * rhs;
}
}
@ -200,17 +209,17 @@ impl<T: Unsigned> Div for Frac<T> {
type Output = Self;
fn div(self, rhs: Self) -> Self {
let numer = self.numer * rhs.denom;
let denom = self.denom * rhs.numer;
let numerator = self.numerator * rhs.denominator;
let denominator = self.denominator * rhs.numerator;
let sign = Self::get_sign(self, rhs, FracOp::Other);
Self::raw(numer, denom, sign)
Self::raw(numerator, denominator, sign)
}
}
impl<T: Unsigned> DivAssign for Frac<T> {
fn div_assign(&mut self, rhs: Self) {
*self = *self / rhs
*self = *self / rhs;
}
}
@ -230,27 +239,27 @@ impl<T: Unsigned> Add for Frac<T> {
}
// Find a common denominator if needed
if a.denom != b.denom {
if a.denominator != b.denominator {
// Let's just use the simplest method, rather than
// worrying about reducing to the least common denominator
let numer = (a.numer * b.denom) + (b.numer * a.denom);
let denom = a.denom * b.denom;
let numerator = (a.numerator * b.denominator) + (b.numerator * a.denominator);
let denominator = a.denominator * b.denominator;
let sign = Self::get_sign(a, b, FracOp::Addition);
return Self::raw(numer, denom, sign);
return Self::raw(numerator, denominator, sign);
}
let numer = a.numer + b.numer;
let denom = self.denom;
let numerator = a.numerator + b.numerator;
let denominator = self.denominator;
let sign = Self::get_sign(a, b, FracOp::Addition);
Self::raw(numer, denom, sign)
Self::raw(numerator, denominator, sign)
}
}
impl<T: Unsigned> AddAssign for Frac<T> {
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs
*self = *self + rhs;
}
}
@ -267,20 +276,20 @@ impl<T: Unsigned> Sub for Frac<T> {
return -(b + -a);
}
if a.denom != b.denom {
let (numer, overflowed) = (a.numer * b.denom).left_overflowing_sub(b.numer * a.denom);
if a.denominator != b.denominator {
let (numerator, overflowed) = (a.numerator * b.denominator).left_overflowing_sub(b.numerator * a.denominator);
let denom = a.denom * b.denom;
let denominator = a.denominator * b.denominator;
let sign = Self::get_sign(a, b, FracOp::Subtraction);
let res = Self::raw(numer, denom, sign);
let res = Self::raw(numerator, denominator, sign);
return if overflowed { -res } else { res };
}
let (numer, overflowed) = a.numer.left_overflowing_sub(b.numer);
let (numerator, overflowed) = a.numerator.left_overflowing_sub(b.numerator);
let denom = a.denom;
let denominator = a.denominator;
let sign = Self::get_sign(a, b, FracOp::Subtraction);
let res = Self::raw(numer, denom, sign);
let res = Self::raw(numerator, denominator, sign);
if overflowed {
-res
@ -292,7 +301,7 @@ impl<T: Unsigned> Sub for Frac<T> {
impl<T: Unsigned> SubAssign for Frac<T> {
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs
*self = *self - rhs;
}
}
@ -314,13 +323,13 @@ mod tests {
#[test]
#[should_panic(expected = "Fraction can not have a zero denominator")]
fn zero_denom() {
fn zero_denominator() {
Frac::raw(1u8, 0u8, Sign::default());
}
#[test]
#[should_panic(expected = "Fraction can not have a zero denominator")]
fn zero_denom_new() {
fn zero_denominator_new() {
frac!(1 / 0);
}