[types] Add GCD and LCM to Int; implement Rem on Int
This commit is contained in:
parent
45bc366a41
commit
1aabce4f60
5 changed files with 116 additions and 96 deletions
37
types/src/number/arith.rs
Normal file
37
types/src/number/arith.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/* types/src/number/arith.rs
|
||||||
|
* Eryn Wells <eryn@erynwells.me>
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub trait GCD {
|
||||||
|
/// Find the greatest common divisor of `self` and another number.
|
||||||
|
fn gcd(self, other: Self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait LCM {
|
||||||
|
/// Find the least common multiple of `self` and another number.
|
||||||
|
fn lcm(self, other: Self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
//impl Rational for Int {
|
||||||
|
// fn to_rational(self) -> (Int, Int) { (self, 1) }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//impl Rational for Flt {
|
||||||
|
// fn to_rational(self) -> (Int, Int) {
|
||||||
|
// // Convert the float to a fraction by iteratively multiplying by 10 until the fractional part of the float is 0.0.
|
||||||
|
// let whole_part = self.trunc();
|
||||||
|
// let mut p = self.fract();
|
||||||
|
// let mut q = 1.0;
|
||||||
|
// while p.fract() != 0.0 {
|
||||||
|
// p *= 10.0;
|
||||||
|
// q *= 10.0;
|
||||||
|
// }
|
||||||
|
// p += whole_part * q;
|
||||||
|
//
|
||||||
|
// // Integers from here down. Reduce the fraction before returning.
|
||||||
|
// let p = p as Int;
|
||||||
|
// let q = q as Int;
|
||||||
|
// let gcd = p.gcd(q);
|
||||||
|
// (p / gcd, q / gcd)
|
||||||
|
// }
|
||||||
|
//}
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::ops::{Add, Mul};
|
||||||
use number::{Int, Number};
|
use number::{Int, Number};
|
||||||
use object::{Obj, Object};
|
use object::{Obj, Object};
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::{Add, Mul};
|
use std::ops::{Add, Mul, Rem};
|
||||||
|
use number::arith::{GCD, LCM};
|
||||||
use number::{Frac, Number};
|
use number::{Frac, Number};
|
||||||
use object::{Obj, Object};
|
use object::{Obj, Object};
|
||||||
|
|
||||||
|
@ -38,6 +39,32 @@ impl fmt::Display for Int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GCD for Int {
|
||||||
|
fn gcd(self, other: Int) -> Int {
|
||||||
|
let (mut a, mut b) = if self.0 > other.0 {
|
||||||
|
(self.0, other.0)
|
||||||
|
} else {
|
||||||
|
(other.0, self.0)
|
||||||
|
};
|
||||||
|
while b != 0 {
|
||||||
|
let r = a % b;
|
||||||
|
a = b;
|
||||||
|
b = r;
|
||||||
|
}
|
||||||
|
Int(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LCM for Int {
|
||||||
|
fn lcm(self, other: Int) -> Int {
|
||||||
|
if self.0 == 0 && other.0 == 0 {
|
||||||
|
Int(0)
|
||||||
|
} else {
|
||||||
|
Int(self.0 * other.0 / self.gcd(other).0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Object for Int {
|
impl Object for Int {
|
||||||
fn as_any(&self) -> &Any { self }
|
fn as_any(&self) -> &Any { self }
|
||||||
fn as_num(&self) -> Option<&Number> { Some(self) }
|
fn as_num(&self) -> Option<&Number> { Some(self) }
|
||||||
|
@ -87,6 +114,27 @@ impl<'a> PartialEq<Number + 'a> for Int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Rem for Int {
|
||||||
|
type Output = Int;
|
||||||
|
fn rem(self, rhs: Self) -> Self::Output {
|
||||||
|
Int(self.0 % rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Rem<Int> for &'a Int {
|
||||||
|
type Output = Int;
|
||||||
|
fn rem(self, rhs: Int) -> Self::Output {
|
||||||
|
Int(self.0 % rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> Rem<&'a Int> for &'b Int {
|
||||||
|
type Output = Int;
|
||||||
|
fn rem(self, rhs: &Int) -> Self::Output {
|
||||||
|
Int(self.0 % rhs.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -113,4 +161,32 @@ mod tests {
|
||||||
fn integers_add() {
|
fn integers_add() {
|
||||||
assert_eq!(Int(4) + Int(8), Int(12));
|
assert_eq!(Int(4) + Int(8), Int(12));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn integers_multiply() {
|
||||||
|
assert_eq!(Int(4) * Int(5), Int(20));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn integer_modulo_divide() {
|
||||||
|
assert_eq!(Int(20) % Int(5), Int(0));
|
||||||
|
assert_eq!(Int(20) % Int(6), Int(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn finding_int_gcd() {
|
||||||
|
assert_eq!(Int(0), Int(0).gcd(Int(0)));
|
||||||
|
assert_eq!(Int(10), Int(10).gcd(Int(0)));
|
||||||
|
assert_eq!(Int(10), Int(0).gcd(Int(10)));
|
||||||
|
assert_eq!(Int(10), Int(10).gcd(Int(20)));
|
||||||
|
assert_eq!(Int(44), Int(2024).gcd(Int(748)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn finding_int_lcm() {
|
||||||
|
assert_eq!(Int(0), Int(0).lcm(Int(0)));
|
||||||
|
assert_eq!(Int(0), Int(10).lcm(Int(0)));
|
||||||
|
assert_eq!(Int(0), Int(10).lcm(Int(0)));
|
||||||
|
assert_eq!(Int(42), Int(21).lcm(Int(6)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
/* types/src/number/math.rs
|
|
||||||
* Eryn Wells <eryn@erynwells.me>
|
|
||||||
*/
|
|
||||||
|
|
||||||
use number::{Int, Flt};
|
|
||||||
|
|
||||||
pub trait GCD {
|
|
||||||
/// Find the greatest common divisor of `self` and another number.
|
|
||||||
fn gcd(self, other: Self) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait LCM {
|
|
||||||
/// Find the least common multiple of `self` and another number.
|
|
||||||
fn lcm(self, other: Self) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Rational {
|
|
||||||
/// Convert `self` into a rational number -- the quotient of two whole numbers.
|
|
||||||
fn to_rational(self) -> (Int, Int);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GCD for Int {
|
|
||||||
fn gcd(self, other: Int) -> Int {
|
|
||||||
let (mut a, mut b) = if self > other {
|
|
||||||
(self, other)
|
|
||||||
} else {
|
|
||||||
(other, self)
|
|
||||||
};
|
|
||||||
|
|
||||||
while b != 0 {
|
|
||||||
let r = a % b;
|
|
||||||
a = b;
|
|
||||||
b = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
a
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LCM for Int {
|
|
||||||
fn lcm(self, other: Int) -> Int {
|
|
||||||
if self == 0 && other == 0 {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self * other / self.gcd(other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Rational for Int {
|
|
||||||
fn to_rational(self) -> (Int, Int) { (self, 1) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Rational for Flt {
|
|
||||||
fn to_rational(self) -> (Int, Int) {
|
|
||||||
// Convert the float to a fraction by iteratively multiplying by 10 until the fractional part of the float is 0.0.
|
|
||||||
let whole_part = self.trunc();
|
|
||||||
let mut p = self.fract();
|
|
||||||
let mut q = 1.0;
|
|
||||||
while p.fract() != 0.0 {
|
|
||||||
p *= 10.0;
|
|
||||||
q *= 10.0;
|
|
||||||
}
|
|
||||||
p += whole_part * q;
|
|
||||||
|
|
||||||
// Integers from here down. Reduce the fraction before returning.
|
|
||||||
let p = p as Int;
|
|
||||||
let q = q as Int;
|
|
||||||
let gcd = p.gcd(q);
|
|
||||||
(p / gcd, q / gcd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::{LCM, GCD};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn gcd_works() {
|
|
||||||
assert_eq!(0, 0.gcd(0));
|
|
||||||
assert_eq!(10, 10.gcd(0));
|
|
||||||
assert_eq!(10, 0.gcd(10));
|
|
||||||
assert_eq!(10, 10.gcd(20));
|
|
||||||
assert_eq!(44, 2024.gcd(748));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn lcm_works() {
|
|
||||||
assert_eq!(0, 0.lcm(0));
|
|
||||||
assert_eq!(0, 10.lcm(0));
|
|
||||||
assert_eq!(0, 10.lcm(0));
|
|
||||||
assert_eq!(42, 21.lcm(6));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,6 +11,7 @@
|
||||||
//! Integer can be cast as a Rational (by putting its value over 1), but a Rational like 1/2 cannot
|
//! Integer can be cast as a Rational (by putting its value over 1), but a Rational like 1/2 cannot
|
||||||
//! be represented as an Integer.
|
//! be represented as an Integer.
|
||||||
|
|
||||||
|
mod arith;
|
||||||
mod integer;
|
mod integer;
|
||||||
mod frac;
|
mod frac;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue