pub struct Rat { /* private fields */ }Expand description
A bounded rational num / den: canonical (den > 0, gcd(|num|, den) == 1)
and bounded (|num|, den <= MAX_MAG), so structural equality is value
equality and Eq/Hash derive safely. Ord is hand-written by
cross-multiplication. The fields are private:
use the_q::Rat;
let _ = Rat { num: 1, den: 2 };use the_q::Rat;
let mut r = Rat::one();
r.den = 0;Implementations§
Source§impl Rat
impl Rat
Sourcepub fn numerator(&self) -> i64
pub fn numerator(&self) -> i64
The numerator of the canonical representation. Always coprime to
Rat::denominator.
use the_q::Rat;
let r = Rat::new(-3, 6).unwrap();
assert_eq!(r.numerator(), -1);
assert_eq!(r.denominator(), 2);Sourcepub fn denominator(&self) -> i64
pub fn denominator(&self) -> i64
The denominator of the canonical representation. Always >= 1.
use the_q::Rat;
let r = Rat::new(3, 6).unwrap();
assert_eq!(r.denominator(), 2);
assert_eq!(Rat::one().denominator(), 1);Source§impl Rat
impl Rat
Sourcepub fn zero() -> Rat
pub fn zero() -> Rat
0.
use the_q::Rat;
let z = Rat::zero();
assert_eq!(z.numerator(), 0);
assert_eq!(z.denominator(), 1);
assert!(z.is_zero());Sourcepub fn one() -> Rat
pub fn one() -> Rat
1.
use the_q::Rat;
let o = Rat::one();
assert_eq!(o.numerator(), 1);
assert_eq!(o.denominator(), 1);
assert!(o.is_one());Sourcepub fn neg_one() -> Rat
pub fn neg_one() -> Rat
-1.
use the_q::Rat;
let n = Rat::neg_one();
assert_eq!(n.numerator(), -1);
assert_eq!(n.denominator(), 1);
assert_eq!(n, Rat::one().neg());Sourcepub fn from_int(i: i64) -> Option<Rat>
pub fn from_int(i: i64) -> Option<Rat>
The integer i as a rational.
None when |i| > MAX_MAG — in particular for i64::MIN, whose
absolute value is not an i64 at all.
use the_q::{Rat, MAX_MAG};
let three = Rat::from_int(3).unwrap();
assert_eq!(three.numerator(), 3);
assert_eq!(three.denominator(), 1);
assert_eq!(Rat::from_int(MAX_MAG + 1), None);
assert_eq!(Rat::from_int(i64::MIN), None);Sourcepub fn new(num: i64, den: i64) -> Option<Rat>
pub fn new(num: i64, den: i64) -> Option<Rat>
The exact rational num / den, canonicalised. None when den == 0 or
the reduced form exceeds the budget (Rat::new(i64::MAX, 1));
Rat::new_rounded rounds instead.
use the_q::Rat;
let half = Rat::new(2, 4).unwrap();
assert_eq!(half.numerator(), 1);
assert_eq!(half.denominator(), 2);
assert_eq!(Rat::new(1, 0), None);
assert_eq!(Rat::new(i64::MAX, 1), None);Sourcepub fn new_rounded(num: i64, den: i64, dir: Dir) -> Option<Rat>
pub fn new_rounded(num: i64, den: i64, dir: Dir) -> Option<Rat>
num / den, rounded to the budget if it does not fit; None iff
den == 0. The sign is normalised onto the numerator before rounding.
use the_q::{Dir, Rat};
assert_eq!(Rat::new_rounded(6, 4, Dir::Nearest), Rat::new(3, 2));
// Sign normalisation: a negative denominator folds onto the numerator.
assert_eq!(Rat::new_rounded(-3, -4, Dir::Down), Rat::new(3, 4));
assert_eq!(Rat::new_rounded(1, 0, Dir::Nearest), None);Sourcepub fn from_decimal(mantissa: i64, dec_places: u8) -> Option<Rat>
pub fn from_decimal(mantissa: i64, dec_places: u8) -> Option<Rat>
The exact decimal mantissa · 10^-dec_places; (85, 2) is 0.85. None
when dec_places > 18 or |mantissa| > MAX_MAG.
use the_q::{Rat, MAX_DEC_PLACES};
assert_eq!(Rat::from_decimal(85, 2), Rat::new(17, 20));
assert_eq!(Rat::from_decimal(1, MAX_DEC_PLACES + 1), None);Source§impl Rat
impl Rat
Sourcepub fn add_dir(a: Rat, b: Rat, dir: Dir) -> Rat
pub fn add_dir(a: Rat, b: Rat, dir: Dir) -> Rat
a + b, rounded in direction dir.
use the_q::{Dir, Rat};
let a = Rat::new(1, 3).unwrap();
let b = Rat::new(1, 6).unwrap();
assert_eq!(Rat::add_dir(a, b, Dir::Down), Rat::new(1, 2).unwrap());
// `Down` and `Up` bracket the exact value; they agree on the exact path.
let a = Rat::new(1, 3_037_000_493).unwrap();
let b = Rat::new(1, 3_037_000_499).unwrap();
let lo = Rat::add_dir(a, b, Dir::Down);
let hi = Rat::add_dir(a, b, Dir::Up);
assert!(Rat::lt(lo, hi));Sourcepub fn sub_dir(a: Rat, b: Rat, dir: Dir) -> Rat
pub fn sub_dir(a: Rat, b: Rat, dir: Dir) -> Rat
a - b, rounded in direction dir.
use the_q::{Dir, Rat};
let a = Rat::new(3, 4).unwrap();
let b = Rat::new(1, 4).unwrap();
assert_eq!(Rat::sub_dir(a, b, Dir::Up), Rat::new(1, 2).unwrap());
// `Down` and `Up` bracket the exact value.
let lo = Rat::sub_dir(a, b, Dir::Down);
let hi = Rat::sub_dir(a, b, Dir::Up);
assert!(Rat::le(lo, hi));Sourcepub fn mul_dir(a: Rat, b: Rat, dir: Dir) -> Rat
pub fn mul_dir(a: Rat, b: Rat, dir: Dir) -> Rat
a * b, rounded in direction dir.
use the_q::{Dir, Rat};
let a = Rat::new(2, 3).unwrap();
let b = Rat::new(3, 4).unwrap();
assert_eq!(Rat::mul_dir(a, b, Dir::Down), Rat::new(1, 2).unwrap());
// `Down` and `Up` bracket the exact value.
let lo = Rat::mul_dir(a, b, Dir::Down);
let hi = Rat::mul_dir(a, b, Dir::Up);
assert!(Rat::le(lo, hi));Sourcepub fn div_dir(a: Rat, b: Rat, dir: Dir) -> Rat
pub fn div_dir(a: Rat, b: Rat, dir: Dir) -> Rat
a / b in direction dir. b != 0 is a precondition; an unverified caller
with a zero divisor panics here. Use Rat::checked_div or crate::Q::div.
use the_q::{Dir, Rat};
let a = Rat::new(1, 2).unwrap();
let b = Rat::new(1, 3).unwrap();
assert_eq!(Rat::div_dir(a, b, Dir::Down), Rat::new(3, 2).unwrap());use the_q::{Dir, Rat};
let a = Rat::new(1, 2).unwrap();
let _ = Rat::div_dir(a, Rat::zero(), Dir::Down);Sourcepub fn add(a: Rat, b: Rat) -> Rat
pub fn add(a: Rat, b: Rat) -> Rat
a + b, round to nearest (ties to even).
The error is a half grid step and not a whole one, thus this operation
achieves B = 62. That is one bit better than the B = 61 of the
directed modes. See round::lemma_r3_error_nearest.
use the_q::Rat;
let a = Rat::new(1, 3).unwrap();
let b = Rat::new(1, 6).unwrap();
assert_eq!(Rat::add(a, b), Rat::new(1, 2).unwrap());
assert_eq!(Rat::add(a, Rat::zero()), a);Sourcepub fn sub(a: Rat, b: Rat) -> Rat
pub fn sub(a: Rat, b: Rat) -> Rat
a - b, round to nearest (ties to even). Achieves B = 62, as add
does.
use the_q::Rat;
let a = Rat::new(3, 4).unwrap();
let b = Rat::new(1, 4).unwrap();
assert_eq!(Rat::sub(a, b), Rat::new(1, 2).unwrap());
assert_eq!(Rat::sub(a, a), Rat::zero());Sourcepub fn mul(a: Rat, b: Rat) -> Rat
pub fn mul(a: Rat, b: Rat) -> Rat
a * b, round to nearest (ties to even). Achieves B = 62, as add
does.
use the_q::Rat;
let a = Rat::new(2, 3).unwrap();
let b = Rat::new(3, 4).unwrap();
assert_eq!(Rat::mul(a, b), Rat::new(1, 2).unwrap());
assert_eq!(Rat::mul(a, Rat::one()), a);Sourcepub fn div(a: Rat, b: Rat) -> Rat
pub fn div(a: Rat, b: Rat) -> Rat
a / b, round to nearest (ties to even). Requires !b.is_zero().
Achieves B = 62, as add does.
use the_q::Rat;
let a = Rat::new(1, 2).unwrap();
let b = Rat::new(1, 3).unwrap();
assert_eq!(Rat::div(a, b), Rat::new(3, 2).unwrap());use the_q::Rat;
let a = Rat::new(1, 2).unwrap();
let _ = Rat::div(a, Rat::zero());Sourcepub fn checked_add(a: Rat, b: Rat) -> Option<Rat>
pub fn checked_add(a: Rat, b: Rat) -> Option<Rat>
a + b, or None if the exact sum is too large in magnitude to be
represented at all (|a + b| > MAX_MAG).
use the_q::{Rat, MAX_MAG};
let a = Rat::new(1, 3).unwrap();
let b = Rat::new(1, 6).unwrap();
assert_eq!(Rat::checked_add(a, b), Some(Rat::new(1, 2).unwrap()));
// `MAX_MAG + 1` is past the budget, not merely rounded.
let max = Rat::from_int(MAX_MAG).unwrap();
assert_eq!(Rat::checked_add(max, Rat::one()), None);Sourcepub fn checked_mul(a: Rat, b: Rat) -> Option<Rat>
pub fn checked_mul(a: Rat, b: Rat) -> Option<Rat>
a * b, or None if the exact product is too large in magnitude.
use the_q::{Rat, MAX_MAG};
let a = Rat::new(2, 3).unwrap();
let b = Rat::new(3, 4).unwrap();
assert_eq!(Rat::checked_mul(a, b), Some(Rat::new(1, 2).unwrap()));
let max = Rat::from_int(MAX_MAG).unwrap();
let two = Rat::from_int(2).unwrap();
assert_eq!(Rat::checked_mul(max, two), None);Sourcepub fn checked_sub(a: Rat, b: Rat) -> Option<Rat>
pub fn checked_sub(a: Rat, b: Rat) -> Option<Rat>
a - b, or None if the exact difference is too large in magnitude.
use the_q::{Rat, MAX_MAG};
let a = Rat::new(3, 4).unwrap();
let b = Rat::new(1, 4).unwrap();
assert_eq!(Rat::checked_sub(a, b), Some(Rat::new(1, 2).unwrap()));
let neg_max = Rat::from_int(-MAX_MAG).unwrap();
assert_eq!(Rat::checked_sub(neg_max, Rat::one()), None);Sourcepub fn checked_sub_dir(a: Rat, b: Rat, dir: Dir) -> Option<Rat>
pub fn checked_sub_dir(a: Rat, b: Rat, dir: Dir) -> Option<Rat>
a - b, rounded in dir, or None if the exact difference is too
large in magnitude. Unlike Rat::checked_sub, this preserves the
requested rounding direction when the result is not exact.
use the_q::{Dir, Rat, MAX_MAG};
let a = Rat::new(3, 4).unwrap();
let b = Rat::new(1, 4).unwrap();
assert_eq!(Rat::checked_sub_dir(a, b, Dir::Down), Some(Rat::new(1, 2).unwrap()));
let neg_max = Rat::from_int(-MAX_MAG).unwrap();
assert_eq!(Rat::checked_sub_dir(neg_max, Rat::one(), Dir::Down), None);Sourcepub fn checked_div(a: Rat, b: Rat) -> Option<Rat>
pub fn checked_div(a: Rat, b: Rat) -> Option<Rat>
a / b, or None on a zero divisor or a quotient past the budget.
use the_q::{Rat, MAX_MAG};
let a = Rat::new(1, 2).unwrap();
let b = Rat::new(1, 3).unwrap();
assert_eq!(Rat::checked_div(a, b), Some(Rat::new(3, 2).unwrap()));
assert_eq!(Rat::checked_div(a, Rat::zero()), None);
let max = Rat::from_int(MAX_MAG).unwrap();
let half = Rat::new(1, 2).unwrap();
assert_eq!(Rat::checked_div(max, half), None);Sourcepub fn neg(self) -> Rat
pub fn neg(self) -> Rat
-a. Always exact: the budget is symmetric in sign.
use the_q::Rat;
let a = Rat::new(3, 4).unwrap();
assert_eq!(a.neg(), Rat::new(-3, 4).unwrap());
assert_eq!(a.neg().neg(), a);Sourcepub fn abs(self) -> Rat
pub fn abs(self) -> Rat
|a|. Always exact.
use the_q::Rat;
let a = Rat::new(-3, 4).unwrap();
assert_eq!(a.abs(), Rat::new(3, 4).unwrap());
assert_eq!(a.abs().abs(), a.abs());Sourcepub fn recip(self) -> Rat
pub fn recip(self) -> Rat
1 / a, exact (a swap of a canonical pair). Zero is a precondition and
panics for an unverified caller; crate::Q::recip gives PosInf.
use the_q::Rat;
let a = Rat::new(-2, 3).unwrap();
assert_eq!(a.recip(), Rat::new(-3, 2).unwrap());
assert_eq!(Rat::mul(a, a.recip()), Rat::one());use the_q::Rat;
let _ = Rat::zero().recip();Source§impl Rat
impl Rat
Sourcepub fn compare(a: Rat, b: Rat) -> i32
pub fn compare(a: Rat, b: Rat) -> i32
Three-way comparison, -1/0/1, exact by i128 cross-multiplication.
use the_q::Rat;
let a = Rat::new(1, 3).unwrap();
let b = Rat::new(1, 2).unwrap();
assert_eq!(Rat::compare(a, b), -1);
assert_eq!(Rat::compare(b, a), 1);
assert_eq!(Rat::compare(a, a), 0);Sourcepub fn eq_q(a: Rat, b: Rat) -> bool
pub fn eq_q(a: Rat, b: Rat) -> bool
a == b. Because Rat is canonical this is also structural equality.
use the_q::Rat;
let a = Rat::new(1, 2).unwrap();
let b = Rat::new(2, 4).unwrap();
assert!(Rat::eq_q(a, b));
assert!(!Rat::eq_q(a, Rat::one()));Sourcepub fn lt(a: Rat, b: Rat) -> bool
pub fn lt(a: Rat, b: Rat) -> bool
a < b.
use the_q::Rat;
let a = Rat::new(1, 3).unwrap();
let b = Rat::new(1, 2).unwrap();
assert!(Rat::lt(a, b));
assert!(!Rat::lt(a, a));Sourcepub fn le(a: Rat, b: Rat) -> bool
pub fn le(a: Rat, b: Rat) -> bool
a <= b.
use the_q::Rat;
let a = Rat::new(1, 3).unwrap();
let b = Rat::new(1, 2).unwrap();
assert!(Rat::le(a, b));
assert!(Rat::le(a, a));
assert!(!Rat::le(b, a));Sourcepub fn gt(a: Rat, b: Rat) -> bool
pub fn gt(a: Rat, b: Rat) -> bool
a > b.
use the_q::Rat;
let a = Rat::new(1, 2).unwrap();
let b = Rat::new(1, 3).unwrap();
assert!(Rat::gt(a, b));
assert!(!Rat::gt(a, a));Sourcepub fn ge(a: Rat, b: Rat) -> bool
pub fn ge(a: Rat, b: Rat) -> bool
a >= b.
use the_q::Rat;
let a = Rat::new(1, 2).unwrap();
let b = Rat::new(1, 3).unwrap();
assert!(Rat::ge(a, b));
assert!(Rat::ge(a, a));
assert!(!Rat::ge(b, a));Sourcepub fn is_zero(&self) -> bool
pub fn is_zero(&self) -> bool
a == 0.
use the_q::Rat;
assert!(Rat::zero().is_zero());
assert!(!Rat::one().is_zero());Sourcepub fn is_one(&self) -> bool
pub fn is_one(&self) -> bool
a == 1.
use the_q::Rat;
assert!(Rat::one().is_one());
assert!(!Rat::zero().is_one());Sourcepub fn signum(&self) -> i32
pub fn signum(&self) -> i32
-1, 0 or 1 according to the sign.
use the_q::Rat;
assert_eq!(Rat::new(-3, 4).unwrap().signum(), -1);
assert_eq!(Rat::zero().signum(), 0);
assert_eq!(Rat::new(3, 4).unwrap().signum(), 1);Sourcepub fn in_unit_interval(&self) -> bool
pub fn in_unit_interval(&self) -> bool
0 <= a <= 1.
The consuming engine checks this constantly on beliefs, disbeliefs and uncertainties, so it is a first-class predicate rather than two comparisons.
use the_q::Rat;
assert!(Rat::new(1, 2).unwrap().in_unit_interval());
assert!(Rat::one().in_unit_interval());
assert!(!Rat::new(-1, 2).unwrap().in_unit_interval());
assert!(!Rat::new(3, 2).unwrap().in_unit_interval());Sourcepub fn min(a: Rat, b: Rat) -> Rat
pub fn min(a: Rat, b: Rat) -> Rat
The smaller of a and b. Exact.
use the_q::Rat;
let a = Rat::new(1, 3).unwrap();
let b = Rat::new(1, 2).unwrap();
assert_eq!(Rat::min(a, b), a);
assert_eq!(Rat::min(b, a), a);Sourcepub fn max(a: Rat, b: Rat) -> Rat
pub fn max(a: Rat, b: Rat) -> Rat
The larger of a and b. Exact.
use the_q::Rat;
let a = Rat::new(1, 3).unwrap();
let b = Rat::new(1, 2).unwrap();
assert_eq!(Rat::max(a, b), b);
assert_eq!(Rat::max(b, a), b);Sourcepub fn clamp(a: Rat, lo: Rat, hi: Rat) -> Rat
pub fn clamp(a: Rat, lo: Rat, hi: Rat) -> Rat
a clamped into [lo, hi]. Exact. Requires lo <= hi.
use the_q::Rat;
let lo = Rat::zero();
let hi = Rat::one();
let mid = Rat::new(1, 2).unwrap();
assert_eq!(Rat::clamp(mid, lo, hi), mid);
assert_eq!(Rat::clamp(Rat::new(-1, 2).unwrap(), lo, hi), lo);
assert_eq!(Rat::clamp(Rat::new(3, 2).unwrap(), lo, hi), hi);Trait Implementations§
impl Copy for Rat
Source§impl<'de> Deserialize<'de> for Rat
Available on crate feature serde only.
impl<'de> Deserialize<'de> for Rat
serde only.Source§fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Rat, D::Error>
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Rat, D::Error>
impl Eq for Rat
Source§impl Ord for Rat
impl Ord for Rat
1.21.0 (const: unstable) · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
1.21.0 (const: unstable) · Source§fn min(self, other: Self) -> Selfwhere
Self: Sized,
fn min(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl PartialOrd for Rat
impl PartialOrd for Rat
Source§impl Serialize for Rat
Available on crate feature serde only.The (num, den) pair, exact; decoding re-canonicalises through Rat::new
and rejects a malformed payload.
impl Serialize for Rat
serde only.The (num, den) pair, exact; decoding re-canonicalises through Rat::new
and rejects a malformed payload.