From: Mark Thom Date: Sat, 20 Feb 2021 00:34:26 +0000 (-0700) Subject: move to a local num-rug-adapter crate addressing #822 X-Git-Tag: v0.9.0~150^2~32 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=f2db0886dd16b60dfb8c5d54dd62c711a7f32338;p=scryer-prolog.git move to a local num-rug-adapter crate addressing #822 --- diff --git a/Cargo.lock b/Cargo.lock index 42246954..360181de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -679,9 +679,7 @@ dependencies = [ [[package]] name = "num-rug-adapter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7470b6acf85abce0771203112db4181d03f7b8a6be49f0e842a78030192f8a58" +version = "0.1.5" dependencies = [ "libc", "num-bigint", diff --git a/Cargo.toml b/Cargo.toml index 708125ec..0d8dbee1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ categories = ["command-line-utilities"] build = "build.rs" [workspace] -members = ["crates/prolog_parser"] +members = ["crates/prolog_parser", "crates/num-rug-adapter"] [build-dependencies] indexmap = "1.0.2" @@ -33,7 +33,7 @@ indexmap = "1.0.2" lazy_static = "1.4.0" libc = "0.2.62" nix = "0.15.0" -num-rug-adapter = { optional = true, version = "0.1.4" } +num-rug-adapter = { optional = true, path = "./crates/num-rug-adapter" } ordered-float = "0.5.0" prolog_parser = { path = "./crates/prolog_parser", default-features = false } ref_thread_local = "0.0.0" diff --git a/crates/num-rug-adapter/Cargo.toml b/crates/num-rug-adapter/Cargo.toml new file mode 100644 index 00000000..8693ac47 --- /dev/null +++ b/crates/num-rug-adapter/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "num-rug-adapter" +version = "0.1.5" +authors = ["Marco A L Barbosa "] +edition = "2018" +description = "An adapter to use num crate where rug is needed." +license = "MIT/Apache-2.0" +repository = "https://github.com/malbarbo/num-rug-adapter" +keywords = ["mathematics", "numerics", "bignum"] +categories = ["api-bindings", "science"] +readme = "README.md" + +[dependencies] +libc = "0.2" +num-bigint = "0.2" +num-integer = "0.1.41" +num-rational = "0.2" +num-traits = "0.2" diff --git a/crates/num-rug-adapter/src/lib.rs b/crates/num-rug-adapter/src/lib.rs new file mode 100644 index 00000000..a95d42c8 --- /dev/null +++ b/crates/num-rug-adapter/src/lib.rs @@ -0,0 +1,883 @@ +use num_bigint::{BigInt, ParseBigIntError}; +use num_integer::Integer as _; +use num_rational::BigRational; +use num_traits::{FromPrimitive, Num, Signed, ToPrimitive}; +use num_traits::identities::One; + +use std::cmp::Ordering; +use std::fmt::{self, Display, Formatter}; +use std::ops::*; + +use std::str::FromStr; + +#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct Integer(BigInt); + +impl Integer { + #[inline] + pub fn new() -> Self { + Integer(BigInt::default()) + } + + #[inline] + pub fn from_str_radix(s: &str, radix: u32) -> Result { + BigInt::from_str_radix(s, radix).map(Integer) + } + + #[inline] + pub fn to_u8(&self) -> Option { + self.0.to_u8() + } + + #[inline] + pub fn to_u32(&self) -> Option { + self.0.to_u32() + } + + #[inline] + pub fn to_u64(&self) -> Option { + self.0.to_u64() + } + + #[inline] + pub fn to_usize(&self) -> Option { + self.0.to_usize() + } + + #[inline] + pub fn to_i32(&self) -> Option { + self.0.to_i32() + } + + #[inline] + pub fn to_isize(&self) -> Option { + self.0.to_isize() + } + + #[inline] + pub fn to_f64(&self) -> f64 { + self.0.to_f64().unwrap() + } + + #[inline] + pub fn abs(&self) -> Self { + Integer(self.0.abs()) + } + + #[inline] + pub fn abs_ref(&self) -> Self { + Integer(self.0.abs()) + } + + #[inline] + pub fn div_rem(&self, other: Self) -> (Self, Self) { + let (a, b) = num_integer::Integer::div_rem(&self.0, &other.0); + (Integer(a), Integer(b)) + } + + #[inline] + pub fn div_rem_ref(&self, other: &Self) -> (Self, Self) { + let (a, b) = num_integer::Integer::div_rem(&self.0, &other.0); + (Integer(a), Integer(b)) + } + + #[inline] + pub fn div_rem_floor(&self, other: Self) -> (Self, Self) { + let (a, b) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + (Integer(a), Integer(b)) + } + + #[inline] + pub fn div_rem_floor_ref(&self, other: &Self) -> (Self, Self) { + let (a, b) = num_integer::Integer::div_mod_floor(&self.0, &other.0); + (Integer(a), Integer(b)) + } + + #[inline] + pub fn mod_u(&self, modulo: u32) -> u32 { + (self.0.abs() % modulo).to_u32().unwrap() + } + + #[inline] + pub fn is_odd(&self) -> bool { + num_integer::Integer::is_odd(&self.0) + } + + #[inline] + pub fn from_f64(v: f64) -> Option { + BigInt::from_f64(v).map(Integer) + } + + #[inline] + pub fn gcd_ref(&self, other: &Self) -> Self { + Integer(num_integer::Integer::gcd(&self.0, &other.0)) + } + + #[inline] + pub fn gcd(&self, other: &Self) -> Self { + Integer(num_integer::Integer::gcd(&self.0, &other.0)) + } +} + +impl From<&Integer> for Integer { + #[inline] + fn from(s: &Integer) -> Self { + s.clone() + } +} + +impl From for Integer { + #[inline] + fn from(s: i32) -> Self { + Integer(BigInt::from(s)) + } +} + +impl From for Integer { + #[inline] + fn from(s: isize) -> Self { + Integer(BigInt::from(s)) + } +} + +impl From for Integer { + #[inline] + fn from(s: u8) -> Self { + Integer(BigInt::from(s)) + } +} + +impl From for Integer { + #[inline] + fn from(s: u32) -> Self { + Integer(BigInt::from(s)) + } +} + +impl From for Integer { + #[inline] + fn from(s: u64) -> Self { + Integer(BigInt::from(s)) + } +} + +impl From for Integer { + #[inline] + fn from(s: usize) -> Self { + Integer(BigInt::from(s)) + } +} + +impl Mul for Integer { + type Output = Integer; + + #[inline] + fn mul(self, other: Integer) -> Self::Output { + Integer(self.0 * other.0) + } +} + +impl Mul for Integer { + type Output = Integer; + + #[inline] + fn mul(self, other: u32) -> Self::Output { + Integer(self.0 * other) + } +} + +impl Mul<&Integer> for Integer { + type Output = Integer; + + fn mul(self, other: &Integer) -> Self::Output { + Integer(self.0 * &other.0) + } +} + +impl MulAssign<&Integer> for Integer { + #[inline] + fn mul_assign(&mut self, other: &Integer) { + self.0 *= &other.0; + } +} + +impl Add for Integer { + type Output = Integer; + + #[inline] + fn add(self, other: Integer) -> Self::Output { + Integer(self.0 + other.0) + } +} + +impl Add for &Integer { + type Output = Integer; + + #[inline] + fn add(self, other: Integer) -> Self::Output { + Integer(&self.0 + other.0) + } +} + +impl Add<&Integer> for Integer { + type Output = Integer; + + #[inline] + fn add(self, other: &Integer) -> Self::Output { + Integer(self.0 + &other.0) + } +} + +impl Add<&Integer> for &Integer { + type Output = Integer; + + #[inline] + fn add(self, other: &Integer) -> Self::Output { + Integer(&self.0 + &other.0) + } +} + +impl AddAssign for Integer { + #[inline] + fn add_assign(&mut self, other: i64) { + self.0 += other; + } +} + +impl AddAssign<&Integer> for Integer { + #[inline] + fn add_assign(&mut self, other: &Integer) { + self.0 += &other.0; + } +} + +impl Div for Integer { + type Output = Integer; + + #[inline] + fn div(self, other: Integer) -> Integer { + Integer(self.0 / other.0) + } +} + +impl Div<&Integer> for Integer { + type Output = Integer; + + #[inline] + fn div(self, other: &Integer) -> Integer { + Integer(self.0 / &other.0) + } +} + +impl Div for &Integer { + type Output = Integer; + + #[inline] + fn div(self, other: Integer) -> Integer { + Integer(&self.0 / &other.0) + } +} + +impl Shr for Integer { + type Output = Integer; + + #[inline] + fn shr(self, rhs: u32) -> Self::Output { + Integer(self.0 >> rhs as usize) + } +} + +impl Shr for &Integer { + type Output = Integer; + + #[inline] + fn shr(self, rhs: u32) -> Self::Output { + Integer(&self.0 >> rhs as usize) + } +} + +impl ShrAssign for Integer { + #[inline] + fn shr_assign(&mut self, rhs: u32) { + self.0 >>= rhs as usize; + } +} + +impl Shl for Integer { + type Output = Integer; + + #[inline] + fn shl(self, rhs: u32) -> Self::Output { + Integer(self.0 << rhs as usize) + } +} + +impl Shl for &Integer { + type Output = Integer; + + #[inline] + fn shl(self, rhs: u32) -> Self::Output { + Integer(&self.0 << rhs as usize) + } +} + +impl Not for Integer { + type Output = Integer; + + #[inline] + fn not(self) -> Self::Output { + Integer(!self.0) + } +} + +impl Not for &Integer { + type Output = Integer; + + #[inline] + fn not(self) -> Self::Output { + Integer(!&self.0) + } +} + +impl Rem for Integer { + type Output = Integer; + + #[inline] + fn rem(self, other: Integer) -> Self::Output { + Integer(self.0.mod_floor(&other.0)) + } +} + +impl Rem<&Integer> for Integer { + type Output = Integer; + + #[inline] + fn rem(self, other: &Integer) -> Self::Output { + Integer(self.0.mod_floor(&other.0)) + } +} + +impl Rem<&Integer> for &Integer { + type Output = Integer; + + #[inline] + fn rem(self, other: &Integer) -> Self::Output { + Integer(self.0.mod_floor(&other.0)) + } +} + +impl Rem for &Integer { + type Output = Integer; + + #[inline] + fn rem(self, other: Integer) -> Self::Output { + Integer(self.0.mod_floor(&other.0)) + } +} + +impl BitAnd for Integer { + type Output = Integer; + + #[inline] + fn bitand(self, other: Integer) -> Self::Output { + Integer(self.0 & &other.0) + } +} + +impl BitAnd<&Integer> for Integer { + type Output = Integer; + + #[inline] + fn bitand(self, other: &Integer) -> Self::Output { + Integer(self.0 & &other.0) + } +} + +impl BitAnd for &Integer { + type Output = Integer; + + #[inline] + fn bitand(self, other: Integer) -> Self::Output { + Integer(&self.0 & other.0) + } +} + +impl BitAnd for &Integer { + type Output = Integer; + + #[inline] + fn bitand(self, other: &Integer) -> Self::Output { + Integer(&self.0 & &other.0) + } +} + +impl BitOr for Integer { + type Output = Integer; + + #[inline] + fn bitor(self, other: Integer) -> Self::Output { + Integer(self.0 | other.0) + } +} + +impl BitOr<&Integer> for Integer { + type Output = Integer; + + #[inline] + fn bitor(self, other: &Integer) -> Self::Output { + Integer(self.0 | &other.0) + } +} + +impl BitOr for &Integer { + type Output = Integer; + + #[inline] + fn bitor(self, other: Integer) -> Self::Output { + Integer(&self.0 | other.0) + } +} + +impl BitOr for &Integer { + type Output = Integer; + + #[inline] + fn bitor(self, other: &Integer) -> Self::Output { + Integer(&self.0 | &other.0) + } +} + +impl BitXor for Integer { + type Output = Integer; + + #[inline] + fn bitxor(self, other: Integer) -> Self::Output { + Integer(self.0 ^ other.0) + } +} + +impl BitXor<&Integer> for Integer { + type Output = Integer; + + #[inline] + fn bitxor(self, other: &Integer) -> Self::Output { + Integer(self.0 ^ &other.0) + } +} + +impl BitXor for &Integer { + type Output = Integer; + + #[inline] + fn bitxor(self, other: Integer) -> Self::Output { + Integer(&self.0 ^ other.0) + } +} + +impl BitXor<&Integer> for &Integer { + type Output = Integer; + + #[inline] + fn bitxor(self, other: &Integer) -> Self::Output { + Integer(&self.0 ^ &other.0) + } +} + +impl PartialEq for Integer { + #[inline] + fn eq(&self, other: &i32) -> bool { + self.0 == BigInt::from(*other) + } +} + +impl PartialEq for Integer { + #[inline] + fn eq(&self, other: &i64) -> bool { + self.0 == BigInt::from(*other) + } +} + +impl PartialEq for Integer { + #[inline] + fn eq(&self, other: &isize) -> bool { + self.0 == BigInt::from(*other) + } +} + +impl PartialEq for Integer { + #[inline] + fn eq(&self, other: &usize) -> bool { + self.0 == BigInt::from(*other) + } +} + +impl PartialEq for isize { + #[inline] + fn eq(&self, other: &Integer) -> bool { + other.0 == BigInt::from(*self) + } +} + +impl PartialOrd for Integer { + #[inline] + fn partial_cmp(&self, other: &i32) -> Option { + self.0.partial_cmp(&BigInt::from(*other)) + } +} + +impl PartialOrd for Integer { + #[inline] + fn partial_cmp(&self, other: &i64) -> Option { + self.0.partial_cmp(&BigInt::from(*other)) + } +} + +impl PartialOrd for Integer { + #[inline] + fn partial_cmp(&self, other: &isize) -> Option { + self.0.partial_cmp(&BigInt::from(*other)) + } +} + +impl PartialOrd for Integer { + #[inline] + fn partial_cmp(&self, other: &usize) -> Option { + self.0.partial_cmp(&BigInt::from(*other)) + } +} + +impl FromStr for Integer { + type Err = ::Err; + + #[inline] + fn from_str(s: &str) -> Result { + Ok(Integer(s.parse()?)) + } +} + +impl Neg for Integer { + type Output = Integer; + + #[inline] + fn neg(self) -> Self { + Integer(-self.0) + } +} + +impl Display for Integer { + #[inline] + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +// Rational + +#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct Rational(BigRational); + +impl Rational { + #[inline] + pub fn new() -> Self { + Rational(BigRational::from(BigInt::default())) + } + + #[inline] + pub fn from_f64(v: f64) -> Option { + BigRational::from_f64(v).map(Rational) + } + + #[inline] + pub fn to_f64(&self) -> f64 { + self.0.numer().to_f64().unwrap() / self.0.denom().to_f64().unwrap() + } + + #[inline] + pub fn numer(&self) -> &Integer { + unsafe { ::std::mem::transmute(self.0.numer()) } + } + + #[inline] + pub fn denom(&self) -> &Integer { + unsafe { ::std::mem::transmute(self.0.denom()) } + } + + #[inline] + pub fn abs(self) -> Self { + Rational(self.0.abs()) + } + + #[inline] + pub fn abs_ref(&self) -> Self { + Rational(self.0.abs()) + } + + #[inline] + pub fn fract_floor_ref(&self) -> &Self { + panic!() + } +} + +impl From for Rational { + #[inline] + fn from(s: isize) -> Self { + Rational(BigRational::new_raw(BigInt::from(s), One::one())) + } +} + +impl From<&Integer> for Rational { + #[inline] + fn from(s: &Integer) -> Self { + Rational::from(s.clone()) + } +} + +impl From<&Rational> for Rational { + #[inline] + fn from(s: &Rational) -> Self { + s.clone() + } +} + +impl From for Rational { + #[inline] + fn from(i: Integer) -> Self { + Rational(BigRational::from(i.0)) + } +} + +impl Add for Rational { + type Output = Rational; + + #[inline] + fn add(self, other: Rational) -> Self::Output { + Rational(self.0 + other.0) + } +} + +impl Add<&Rational> for Rational { + type Output = Rational; + + #[inline] + fn add(self, other: &Rational) -> Self::Output { + Rational(self.0 + &other.0) + } +} + +impl PartialEq for Rational { + #[inline] + fn eq(&self, other: &i32) -> bool { + self.0 == BigRational::from(BigInt::from(*other)) + } +} + +impl PartialEq for Rational { + #[inline] + fn eq(&self, other: &i64) -> bool { + self.0 == BigRational::from(BigInt::from(*other)) + } +} + +impl PartialEq for Rational { + #[inline] + fn eq(&self, other: &isize) -> bool { + self == &Rational::from(*other) + } +} + +impl PartialEq for isize { + #[inline] + fn eq(&self, other: &Rational) -> bool { + other == &Rational::from(*self) + } +} + +impl PartialOrd for Rational { + #[inline] + fn partial_cmp(&self, other: &isize) -> Option { + self.0.partial_cmp(&BigRational::from(BigInt::from(*other))) + } +} + +impl PartialOrd for Rational { + #[inline] + fn partial_cmp(&self, other: &i64) -> Option { + self.0.partial_cmp(&BigRational::from(BigInt::from(*other))) + } +} + +impl PartialOrd for Rational { + #[inline] + fn partial_cmp(&self, other: &i32) -> Option { + self.0.partial_cmp(&BigRational::from(BigInt::from(*other))) + } +} + +impl Neg for Rational { + type Output = Rational; + + #[inline] + fn neg(self) -> Self { + Rational(-self.0) + } +} + +impl Mul for Rational { + type Output = Rational; + + #[inline] + fn mul(self, other: Rational) -> Self::Output { + Rational(self.0 * other.0) + } +} + +impl Mul<&Rational> for Rational { + type Output = Rational; + + fn mul(self, other: &Rational) -> Self::Output { + Rational(self.0 * &other.0) + } +} + +impl Div for Rational { + type Output = Rational; + + #[inline] + fn div(self, other: Rational) -> Self::Output { + Rational(self.0 / other.0) + } +} + +impl Div<&Rational> for &Rational { + type Output = Rational; + + #[inline] + fn div(self, other: &Rational) -> Self::Output { + Rational(&self.0 / &other.0) + } +} + +impl Display for Rational { + #[inline] + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +pub trait Assign { + fn assign(&mut self, src: Src); +} + +impl Assign<&Rational> for (&mut Rational, &mut Integer) { + fn assign(&mut self, _src: &Rational) { + panic!() + } +} + +pub mod ops { + use super::{Integer, Rational}; + + pub trait Pow { + type Output; + fn pow(self, rhs: Rhs) -> Self::Output; + } + + impl Pow for Integer { + type Output = Integer; + + fn pow(self, rhs: u32) -> Self::Output { + Integer(num_traits::Pow::pow(&self.0, rhs)) + } + } + + pub trait PowAssign { + fn pow_assign(&mut self, rhs: Rhs); + } + + impl PowAssign for Integer { + fn pow_assign(&mut self, rhs: u32) { + // FIXME: make it efficient + self.0 = num_traits::Pow::pow(&self.0, rhs); + } + } + + pub trait NegAssign { + fn neg_assign(&mut self); + } + + impl NegAssign for Integer { + fn neg_assign(&mut self) { + self.0 = -std::mem::replace(self, Integer::new()).0; + } + } + + impl NegAssign for Rational { + #[inline] + fn neg_assign(&mut self) { + self.0 = -std::mem::replace(self, Rational::new()).0; + } + } +} + +pub mod rand { + use super::Integer; + use std::marker::PhantomData; + + pub struct RandState<'a>{ + _marker: PhantomData<&'a ()>, + } + + impl<'a> RandState<'a> { + pub fn new() -> Self { + unsafe { libc::srand(libc::time(std::ptr::null_mut()) as _) }; + RandState { _marker: PhantomData } + } + + pub fn borrow_mut(&self) -> &Self { + self + } + + pub fn bits(&mut self, bits: u32) -> u32 { + assert!(bits <= 32); + (unsafe { libc::rand() } as u32) & (u32::max_value() >> (32 - bits)) + } + + pub fn seed(&mut self, seed: &Integer) { + unsafe { libc::srand(seed.to_f64() as _)} + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use super::ops::NegAssign; + + #[test] + fn bits() { + let mut rand = rand::RandState::new(); + for bits in 1..32 { + for _ in 0..100 { + let r = rand.bits(bits); + let max = 1 << bits; + assert!(max > r, "{} > {}", max, r); + } + } + } + + #[test] + fn neg_rational() { + let mut x = Rational::from_f64(5.0).unwrap(); + let x_neg = Rational::from_f64(-5.0).unwrap(); + x.neg_assign(); + assert_eq!(x, x_neg); + } + + #[test] + fn neg_integer() { + let mut x = Integer::from(5); + let x_neg = Integer::from(-5); + x.neg_assign(); + assert_eq!(x, x_neg); + } +} diff --git a/crates/prolog_parser/Cargo.toml b/crates/prolog_parser/Cargo.toml index b9dab9fd..8946bf27 100644 --- a/crates/prolog_parser/Cargo.toml +++ b/crates/prolog_parser/Cargo.toml @@ -12,7 +12,7 @@ indexmap = "1.0.2" lexical = "2.1.0" ordered-float = "0.5.0" rug = { optional = true, version = "1.4.0" } -num-rug-adapter = { optional = true, version = "0.1.3" } +num-rug-adapter = { optional = true, path = "../num-rug-adapter" } unicode_reader = "1.0.0" [lib]