Keep working on Numbers and stuff -- trying to get integrated with the new sibillexer crate
This commit is contained in:
parent
fc947280ae
commit
4d7d709b2f
3 changed files with 78 additions and 19 deletions
|
@ -3,6 +3,10 @@ mod char;
|
||||||
mod number;
|
mod number;
|
||||||
mod value;
|
mod value;
|
||||||
|
|
||||||
|
pub use bool::Bool;
|
||||||
|
pub use char::Char;
|
||||||
|
pub use number::Number;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use bool::Bool;
|
use bool::Bool;
|
||||||
|
|
|
@ -15,10 +15,7 @@ pub use self::real::Real;
|
||||||
pub use self::complex::Complex;
|
pub use self::complex::Complex;
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fmt::Debug;
|
use value::*;
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
use super::value::*;
|
|
||||||
|
|
||||||
type Int = i64;
|
type Int = i64;
|
||||||
type Flt = f64;
|
type Flt = f64;
|
||||||
|
@ -44,6 +41,29 @@ impl Number {
|
||||||
Number::new(Real::Integer(value), None, exact)
|
Number::new(Real::Integer(value), None, exact)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_quotient(p: Int, q: Int, exact: bool) -> Number {
|
||||||
|
let real = if exact {
|
||||||
|
// Make an exact rational an integer if possible.
|
||||||
|
Real::Rational(p, q).demote()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Make an inexact rational an irrational.
|
||||||
|
Real::Rational(p, q).promote_once()
|
||||||
|
};
|
||||||
|
Number::new(real, None, exact)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_float(value: Flt, exact: bool) -> Number {
|
||||||
|
let real = if exact {
|
||||||
|
// Attempt to demote irrationals.
|
||||||
|
Real::Irrational(value).demote()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Real::Irrational(value)
|
||||||
|
};
|
||||||
|
Number::new(real, None, exact)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_exact(&self) -> bool { self.exact }
|
pub fn is_exact(&self) -> bool { self.exact }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,3 +81,21 @@ impl ValueEq for Number {
|
||||||
impl IsBool for Number { }
|
impl IsBool for Number { }
|
||||||
impl IsChar for Number { }
|
impl IsChar for Number { }
|
||||||
impl IsNumber for Number { }
|
impl IsNumber for Number { }
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::Number;
|
||||||
|
use super::real::Real;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exact_numbers_are_exact() {
|
||||||
|
assert!(Number::from_int(3, true).is_exact());
|
||||||
|
assert!(!Number::from_int(3, false).is_exact());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exact_irrationals_are_reduced() {
|
||||||
|
let real = Real::Rational(3, 2);
|
||||||
|
assert_eq!(Number::from_float(1.5, true), Number::new(real, None, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,10 +2,8 @@
|
||||||
* Eryn Wells <eryn@erynwells.me>
|
* Eryn Wells <eryn@erynwells.me>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use std::any::Any;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use number::math::*;
|
use number::math::*;
|
||||||
use value::*;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum Real {
|
pub enum Real {
|
||||||
|
@ -27,7 +25,7 @@ impl Real {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Promote a Real to the next highest type.
|
/// Promote a Real to the next highest type.
|
||||||
fn promote(self) -> Real {
|
pub fn promote_once(self) -> Real {
|
||||||
match self {
|
match self {
|
||||||
Real::Integer(v) => Real::Rational(v, 1),
|
Real::Integer(v) => Real::Rational(v, 1),
|
||||||
Real::Rational(p, q) => Real::Irrational(p as Flt / q as Flt),
|
Real::Rational(p, q) => Real::Irrational(p as Flt / q as Flt),
|
||||||
|
@ -35,10 +33,29 @@ impl Real {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Demote a Real as far down the tower as possible.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use number::real::Real;
|
||||||
|
///
|
||||||
|
/// assert_eq!(Real::Integer(3).demote(), Real::Integer(3));
|
||||||
|
/// assert_eq!(Real::Rational(3, 1).demote(), Real::Integer(3));
|
||||||
|
/// assert_eq!(Real::Irrational(3.2).demote(), Real::Rational(32, 100));
|
||||||
|
/// assert_eq!(Real::Irrational(3.0).demote(), Real::Integer(3));
|
||||||
|
/// ```
|
||||||
|
pub fn demote(self) -> Real {
|
||||||
|
match self.demote_once() {
|
||||||
|
Some(demoted) => demoted.demote(),
|
||||||
|
None => self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Demote a Real to the next lowest type, if possible.
|
/// Demote a Real to the next lowest type, if possible.
|
||||||
fn demote(self) -> Option<Real> {
|
pub fn demote_once(self) -> Option<Real> {
|
||||||
match self {
|
match self {
|
||||||
Real::Integer(v) => None,
|
Real::Integer(_) => None,
|
||||||
Real::Rational(p, q) => if q == 1 {
|
Real::Rational(p, q) => if q == 1 {
|
||||||
Some(Real::Integer(p))
|
Some(Real::Integer(p))
|
||||||
}
|
}
|
||||||
|
@ -46,7 +63,7 @@ impl Real {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
// TODO: Convert an irrational into a fraction.
|
// TODO: Convert an irrational into a fraction.
|
||||||
Real::Irrational(mut v) => {
|
Real::Irrational(v) => {
|
||||||
let whole_part = v.trunc();
|
let whole_part = v.trunc();
|
||||||
let mut p = v.fract();
|
let mut p = v.fract();
|
||||||
let mut q = 1.0;
|
let mut q = 1.0;
|
||||||
|
@ -91,12 +108,12 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn promote_to_rationals() {
|
fn promote_to_rationals() {
|
||||||
assert_eq!(Real::Integer(6).promote(), Real::Rational(6, 1));
|
assert_eq!(Real::Integer(6).promote_once(), Real::Rational(6, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn demote_to_nothing() {
|
fn demote_to_themselves() {
|
||||||
assert_eq!(Real::Integer(6).demote(), None);
|
assert_eq!(Real::Integer(6).demote(), Real::Integer(6));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,13 +133,13 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn promote_to_irrationals() {
|
fn promote_to_irrationals() {
|
||||||
assert_eq!(Real::Rational(3, 2).promote(), Real::Irrational(1.5));
|
assert_eq!(Real::Rational(3, 2).promote_once(), Real::Irrational(1.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn demote_to_integers_if_possible() {
|
fn demote_to_integers_if_possible() {
|
||||||
assert_eq!(Real::Rational(3, 2).demote(), None);
|
assert_eq!(Real::Rational(3, 2).demote(), Real::Rational(3, 2));
|
||||||
assert_eq!(Real::Rational(4, 1).demote(), Some(Real::Integer(4)));
|
assert_eq!(Real::Rational(4, 1).demote(), Real::Integer(4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,13 +159,13 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn promote_to_themselves() {
|
fn promote_to_themselves() {
|
||||||
assert_eq!(Real::Irrational(3.2).promote(), Real::Irrational(3.2));
|
assert_eq!(Real::Irrational(3.2).promote_once(), Real::Irrational(3.2));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn demote_to_rationals() {
|
fn demote_to_rationals() {
|
||||||
assert_eq!(Real::Irrational(3.2).demote(), Some(Real::Rational(16, 5)));
|
assert_eq!(Real::Irrational(3.2).demote(), Real::Rational(16, 5));
|
||||||
assert_eq!(Real::Irrational(3.5).demote(), Some(Real::Rational(7, 2)));
|
assert_eq!(Real::Irrational(3.5).demote(), Real::Rational(7, 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue