1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
use num_bigint::{BigInt, BigUint};
use num_complex::Complex64;
use num_irrational::QuadraticSurd;
use num_modular::{MontgomeryBigint, MontgomeryInt};
use num_rational::{BigRational, Rational64};
use num_traits::FromPrimitive;
use std::{rc::Rc, ops::Sub, convert::TryInto};
/// A general `suan` object (su-bject) containing all possible numeric types involved in the calculation
pub enum Subject {
/// Small integer
Int(i64),
/// Multi-precision integer
BInt(Rc<BigInt>),
/// Small real number
Real(f64),
/// Multi-precision real number
BReal(), // TODO: available if enable rug feature
/// Rational number
Rational(Rational64),
/// Multi-precision Rational number
BRational(BigRational),
/// Complex number
Complex(Complex64),
/// Multi-precision Complex number
BComplex(), // TODO: available if enable rug feature
/// Small integer in modulo ring
IntMod(MontgomeryInt<u64>),
/// Multi-precision integer in modulo ring
BIntMod(), // TODO: MontgomeryBigint<BigUint>
/// Quadratic number
Quad(QuadraticSurd<i64>), // TODO: Quadratic64
/// Multi-precision Quadratic number
BQuad(QuadraticSurd<BigInt>), // TODO: BigQuadratic
}
impl From<i64> for Subject {
fn from(v: i64) -> Self {
Subject::Int(v)
}
}
impl From<u64> for Subject {
fn from(v: u64) -> Self {
match v.try_into() {
Ok(u) => Subject::Int(u),
Err(_) => Subject::BInt(Rc::new(BigInt::from_u64(v).unwrap()))
}
}
}
impl From<usize> for Subject {
fn from(v: usize) -> Self {
match v.try_into() {
Ok(u) => Subject::Int(u),
Err(_) => Subject::BInt(Rc::new(BigInt::from_usize(v).unwrap()))
}
}
}
impl From<BigInt> for Subject {
fn from(v: BigInt) -> Self {
Subject::BInt(Rc::new(v))
}
}
impl From<BigUint> for Subject {
fn from(v: BigUint) -> Self {
Subject::BInt(Rc::new(BigInt::from(v)))
}
}
// TODO: add method to convert between the variants:
// .int(), .real(), .rational(), .intmod(), .quad(), .complex()
// .int should accept a 'rounding' parameter with default mode as nearest.
// .real and .rational should accept a 'precision' parameter for determine the (least) precision (in bits)
// .real and .rational should also accept a 'digits' parameter for determine the (least) decimal precision
// .intmod shoud accept a 'modulus' parameter to specify the modulus
// TODO: add method .precision() to set precision, .digits() to set decimal precision. If None is given as the argument, then fallback to f64.
// these two methods should also have a rounding mode parameter.