use std::fmt;
use std::ops;
use std::str::FromStr;
pub use num::bigint::Sign;
use num::{self, BigInt, BigRational};
use num::{FromPrimitive, ToPrimitive, Integer as NumInteger, Signed, Num, Zero, One};
#[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
pub struct Integer(BigInt);
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Ratio(BigRational);
#[derive(Debug, PartialEq)]
pub struct FromStrIntError(<BigInt as FromStr>::Err);
#[derive(Debug, PartialEq)]
pub struct FromStrRatioError(<BigRational as FromStr>::Err);
#[derive(Debug, PartialEq)]
pub struct FromStrRadixError(<BigInt as Num>::FromStrRadixErr);
impl fmt::Display for FromStrIntError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl fmt::Display for FromStrRatioError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl fmt::Display for FromStrRadixError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl Integer {
#[inline]
pub fn bits(&self) -> usize {
self.0.bits()
}
#[inline]
pub fn from_bytes_be(sign: Sign, bytes: &[u8]) -> Integer {
Integer(BigInt::from_bytes_be(sign, bytes))
}
#[inline]
pub fn from_bytes_le(sign: Sign, bytes: &[u8]) -> Integer {
Integer(BigInt::from_bytes_le(sign, bytes))
}
#[inline]
pub fn from_f64(f: f64) -> Option<Integer> {
BigInt::from_f64(f).map(Integer)
}
#[inline]
pub fn from_i8(i: i8) -> Integer {
Integer(BigInt::from_i8(i).unwrap())
}
#[inline]
pub fn from_i16(i: i16) -> Integer {
Integer(BigInt::from_i16(i).unwrap())
}
#[inline]
pub fn from_i32(i: i32) -> Integer {
Integer(BigInt::from_i32(i).unwrap())
}
#[inline]
pub fn from_i64(i: i64) -> Integer {
Integer(BigInt::from_i64(i).unwrap())
}
#[inline]
pub fn from_isize(i: isize) -> Integer {
Integer(BigInt::from_isize(i).unwrap())
}
#[inline]
pub fn from_u8(i: u8) -> Integer {
Integer(BigInt::from_u8(i).unwrap())
}
#[inline]
pub fn from_u16(i: u16) -> Integer {
Integer(BigInt::from_u16(i).unwrap())
}
#[inline]
pub fn from_u32(i: u32) -> Integer {
Integer(BigInt::from_u32(i).unwrap())
}
#[inline]
pub fn from_u64(i: u64) -> Integer {
Integer(BigInt::from_u64(i).unwrap())
}
#[inline]
pub fn from_usize(u: usize) -> Integer {
Integer(BigInt::from_usize(u).unwrap())
}
#[inline]
pub fn from_str_radix(s: &str, radix: u32) -> Result<Integer, FromStrRadixError> {
BigInt::from_str_radix(s, radix)
.map(Integer).map_err(FromStrRadixError)
}
#[inline]
pub fn to_bytes_be(&self) -> (Sign, Vec<u8>) {
self.0.to_bytes_be()
}
#[inline]
pub fn to_bytes_le(&self) -> (Sign, Vec<u8>) {
self.0.to_bytes_le()
}
pub fn to_str_radix(&self, radix: u32) -> String {
self.0.to_str_radix(radix)
}
#[inline]
pub fn to_i8(&self) -> Option<i8> {
self.0.to_i8()
}
#[inline]
pub fn to_i16(&self) -> Option<i16> {
self.0.to_i16()
}
#[inline]
pub fn to_i32(&self) -> Option<i32> {
self.0.to_i32()
}
#[inline]
pub fn to_i64(&self) -> Option<i64> {
self.0.to_i64()
}
#[inline]
pub fn to_isize(&self) -> Option<isize> {
self.0.to_isize()
}
#[inline]
pub fn to_u8(&self) -> Option<u8> {
self.0.to_u8()
}
#[inline]
pub fn to_u16(&self) -> Option<u16> {
self.0.to_u16()
}
#[inline]
pub fn to_u32(&self) -> Option<u32> {
self.0.to_u32()
}
#[inline]
pub fn to_u64(&self) -> Option<u64> {
self.0.to_u64()
}
#[inline]
pub fn to_usize(&self) -> Option<usize> {
self.0.to_usize()
}
#[inline]
pub fn to_f32(&self) -> Option<f32> {
self.0.to_f32()
}
#[inline]
pub fn to_f64(&self) -> Option<f64> {
self.0.to_f64()
}
#[inline]
pub fn pow(self, exp: usize) -> Integer {
Integer(num::pow(self.0, exp))
}
#[inline]
pub fn abs(&self) -> Integer {
Integer(self.0.abs())
}
#[inline]
pub fn is_multiple_of(&self, rhs: &Integer) -> bool {
self.0.is_multiple_of(&rhs.0)
}
#[inline]
pub fn is_negative(&self) -> bool {
self.0.is_negative()
}
#[inline]
pub fn is_positive(&self) -> bool {
self.0.is_positive()
}
#[inline]
pub fn is_zero(&self) -> bool {
self.0.is_zero()
}
#[inline]
pub fn zero() -> Integer {
Integer(BigInt::zero())
}
#[inline]
pub fn is_one(&self) -> bool {
self.to_u32() == Some(1)
}
#[inline]
pub fn one() -> Integer {
Integer(BigInt::one())
}
fn from_bigint_ref(i: &BigInt) -> &Integer {
unsafe { &*(i as *const _ as *const Integer) }
}
}
impl Ratio {
#[inline]
pub fn new(numer: Integer, denom: Integer) -> Ratio {
Ratio(BigRational::new(numer.0, denom.0))
}
#[inline]
pub fn from_f32(f: f32) -> Option<Ratio> {
BigRational::from_float(f).map(Ratio)
}
#[inline]
pub fn from_f64(f: f64) -> Option<Ratio> {
BigRational::from_float(f).map(Ratio)
}
#[inline]
pub fn from_integer(i: Integer) -> Ratio {
Ratio(BigRational::from_integer(i.0))
}
#[inline]
pub fn to_f32(&self) -> Option<f32> {
self.numer().to_f32().and_then(
|n| self.denom().to_f32().map(|d| n / d))
}
#[inline]
pub fn to_f64(&self) -> Option<f64> {
self.numer().to_f64().and_then(
|n| self.denom().to_f64().map(|d| n / d))
}
#[inline]
pub fn to_integer(&self) -> Integer {
Integer(self.0.to_integer())
}
#[inline]
pub fn is_integer(&self) -> bool {
self.denom().is_one()
}
#[inline]
pub fn abs(&self) -> Ratio {
Ratio(self.0.abs())
}
#[inline]
pub fn ceil(&self) -> Ratio {
Ratio(self.0.ceil())
}
#[inline]
pub fn floor(&self) -> Ratio {
Ratio(self.0.floor())
}
#[inline]
pub fn fract(&self) -> Ratio {
Ratio(self.0.fract())
}
#[inline]
pub fn round(&self) -> Ratio {
Ratio(self.0.round())
}
#[inline]
pub fn trunc(&self) -> Ratio {
Ratio(self.0.trunc())
}
#[inline]
pub fn recip(&self) -> Ratio {
Ratio(self.0.recip())
}
#[inline]
pub fn numer(&self) -> &Integer {
Integer::from_bigint_ref(self.0.numer())
}
#[inline]
pub fn denom(&self) -> &Integer {
Integer::from_bigint_ref(self.0.denom())
}
pub fn is_zero(&self) -> bool {
self.numer().is_zero()
}
pub fn is_negative(&self) -> bool {
self.numer().is_negative()
}
pub fn is_positive(&self) -> bool {
self.numer().is_positive()
}
pub fn zero() -> Ratio {
Ratio(BigRational::zero())
}
pub fn one() -> Ratio {
Ratio(BigRational::one())
}
}
impl PartialEq<Integer> for Ratio {
fn eq(&self, rhs: &Integer) -> bool {
self.denom().is_one() && self.numer() == rhs
}
}
impl PartialEq<Ratio> for Integer {
fn eq(&self, rhs: &Ratio) -> bool { rhs == self }
}
impl fmt::Display for Integer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl FromStr for Integer {
type Err = FromStrIntError;
#[inline]
fn from_str(s: &str) -> Result<Integer, FromStrIntError> {
s.parse().map(Integer).map_err(FromStrIntError)
}
}
impl ops::Shl<usize> for Integer {
type Output = Integer;
#[inline]
fn shl(self, rhs: usize) -> Integer {
Integer(self.0.shl(rhs))
}
}
impl<'a> ops::Shl<usize> for &'a Integer {
type Output = Integer;
#[inline]
fn shl(self, rhs: usize) -> Integer {
Integer(self.0.clone().shl(rhs))
}
}
impl ops::Shr<usize> for Integer {
type Output = Integer;
#[inline]
fn shr(self, rhs: usize) -> Integer {
Integer(self.0.shr(rhs))
}
}
impl<'a> ops::Shr<usize> for &'a Integer {
type Output = Integer;
#[inline]
fn shr(self, rhs: usize) -> Integer {
Integer(self.0.clone().shr(rhs))
}
}
macro_rules! impl_un_op {
( $ty:ident , $trait:ident , $meth:ident ) => {
impl ::std::ops::$trait for $ty {
type Output = $ty;
#[inline]
fn $meth(self) -> $ty {
$ty((self.0).$meth())
}
}
impl<'a> ::std::ops::$trait for &'a $ty {
type Output = $ty;
#[inline]
fn $meth(self) -> $ty {
$ty((&self.0).$meth())
}
}
}
}
macro_rules! impl_bin_op {
( $ty:ident , $trait:ident , $meth:ident ) => {
impl ::std::ops::$trait<$ty> for $ty {
type Output = $ty;
#[inline]
fn $meth(self, rhs: $ty) -> $ty {
$ty((self.0).$meth(rhs.0))
}
}
impl<'a> ::std::ops::$trait<&'a $ty> for $ty {
type Output = $ty;
#[inline]
fn $meth(self, rhs: &$ty) -> $ty {
$ty((self.0).$meth(&rhs.0))
}
}
impl<'a> ::std::ops::$trait<$ty> for &'a $ty {
type Output = $ty;
#[inline]
fn $meth(self, rhs: $ty) -> $ty {
$ty((&self.0).$meth(rhs.0))
}
}
impl<'a, 'b> ::std::ops::$trait<&'b $ty> for &'a $ty {
type Output = $ty;
#[inline]
fn $meth(self, rhs: &$ty) -> $ty {
$ty((&self.0).$meth(&rhs.0))
}
}
}
}
macro_rules! impl_assign_op {
( $ty:ident , $trait:ident , $meth:ident ) => {
impl ::std::ops::$trait<$ty> for $ty {
#[inline]
fn $meth(&mut self, rhs: $ty) {
(self.0).$meth(rhs.0);
}
}
impl<'a> ::std::ops::$trait<&'a $ty> for $ty {
#[inline]
fn $meth(&mut self, rhs: &$ty) {
(self.0).$meth(&rhs.0);
}
}
}
}
macro_rules! impl_ops {
( $ty:ident ) => {
impl_bin_op!{ $ty, Add, add }
impl_bin_op!{ $ty, Sub, sub }
impl_bin_op!{ $ty, Mul, mul }
impl_bin_op!{ $ty, Div, div }
impl_bin_op!{ $ty, Rem, rem }
impl_assign_op!{ $ty, AddAssign, add_assign }
impl_assign_op!{ $ty, SubAssign, sub_assign }
impl_assign_op!{ $ty, MulAssign, mul_assign }
impl_assign_op!{ $ty, DivAssign, div_assign }
impl_assign_op!{ $ty, RemAssign, rem_assign }
impl_un_op!{ $ty, Neg, neg }
impl ::num::Zero for $ty {
#[inline]
fn is_zero(&self) -> bool { self.0.is_zero() }
#[inline]
fn zero() -> $ty { $ty(Zero::zero()) }
}
}
}
macro_rules! impl_integer_ops {
( $ty:ident ) => {
impl_ops!{ $ty }
impl_bin_op!{ $ty, BitAnd, bitand }
impl_bin_op!{ $ty, BitOr, bitor }
impl_bin_op!{ $ty, BitXor, bitxor }
impl_assign_op!{ $ty, BitAndAssign, bitand_assign }
impl_assign_op!{ $ty, BitOrAssign, bitor_assign }
impl_assign_op!{ $ty, BitXorAssign, bitxor_assign }
impl_un_op!{ $ty, Not, not }
}
}
impl_integer_ops!{Integer}
impl_ops!{Ratio}
impl fmt::Display for Ratio {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl FromStr for Ratio {
type Err = FromStrRatioError;
#[inline]
fn from_str(s: &str) -> Result<Ratio, FromStrRatioError> {
s.parse().map(Ratio).map_err(FromStrRatioError)
}
}