use std::num::{Float, SignedInt};
use std::ops::Mul;
use std::cmp::Ordering;
use traits::structure::SquareMat;
#[derive(Eq, PartialEq, RustcEncodable, RustcDecodable, Clone, Debug, Copy)]
pub enum POrdering {
PartialLess,
PartialEqual,
PartialGreater,
NotComparable
}
impl POrdering {
pub fn is_eq(&self) -> bool {
*self == POrdering::PartialEqual
}
pub fn is_lt(&self) -> bool {
*self == POrdering::PartialLess
}
pub fn is_le(&self) -> bool {
*self == POrdering::PartialLess || *self == POrdering::PartialEqual
}
pub fn is_gt(&self) -> bool {
*self == POrdering::PartialGreater
}
pub fn is_ge(&self) -> bool {
*self == POrdering::PartialGreater || *self == POrdering::PartialEqual
}
pub fn is_not_comparable(&self) -> bool {
*self == POrdering::NotComparable
}
pub fn from_ordering(ord: Ordering) -> POrdering {
match ord {
Ordering::Less => POrdering::PartialLess,
Ordering::Equal => POrdering::PartialEqual,
Ordering::Greater => POrdering::PartialGreater
}
}
pub fn to_ordering(self) -> Option<Ordering> {
match self {
POrdering::PartialLess => Some(Ordering::Less),
POrdering::PartialEqual => Some(Ordering::Equal),
POrdering::PartialGreater => Some(Ordering::Greater),
POrdering::NotComparable => None
}
}
}
pub trait POrd {
fn inf(&self, other: &Self) -> Self;
fn sup(&self, other: &Self) -> Self;
fn partial_cmp(&self, other: &Self) -> POrdering;
#[inline]
fn partial_le(&self, other: &Self) -> bool {
POrd::partial_cmp(self, other).is_le()
}
#[inline]
fn partial_lt(&self, other: &Self) -> bool {
POrd::partial_cmp(self, other).is_lt()
}
#[inline]
fn partial_ge(&self, other: &Self) -> bool {
POrd::partial_cmp(self, other).is_ge()
}
#[inline]
fn partial_gt(&self, other: &Self) -> bool {
POrd::partial_cmp(self, other).is_gt()
}
#[inline]
fn partial_min<'a>(&'a self, other: &'a Self) -> Option<&'a Self> {
match POrd::partial_cmp(self, other) {
POrdering::PartialLess | POrdering::PartialEqual => Some(self),
POrdering::PartialGreater => Some(other),
POrdering::NotComparable => None
}
}
#[inline]
fn partial_max<'a>(&'a self, other: &'a Self) -> Option<&'a Self> {
match POrd::partial_cmp(self, other) {
POrdering::PartialGreater | POrdering::PartialEqual => Some(self),
POrdering::PartialLess => Some(other),
POrdering::NotComparable => None
}
}
#[inline]
fn partial_clamp<'a>(&'a self, min: &'a Self, max: &'a Self) -> Option<&'a Self> {
let v_min = self.partial_cmp(min);
let v_max = self.partial_cmp(max);
if v_min.is_not_comparable() || v_max.is_not_comparable() {
None
}
else {
if v_min.is_lt() {
Some(min)
}
else if v_max.is_gt() {
Some(max)
}
else {
Some(self)
}
}
}
}
pub trait ApproxEq<Eps>: Sized {
fn approx_epsilon(unused_mut: Option<Self>) -> Eps;
fn approx_eq_eps(&self, other: &Self, epsilon: &Eps) -> bool;
fn approx_ulps(unused_mut: Option<Self>) -> u32;
fn approx_eq_ulps(&self, other: &Self, ulps: u32) -> bool;
#[inline]
fn approx_eq(&self, other: &Self) -> bool {
self.approx_eq_eps(other, &ApproxEq::approx_epsilon(None::<Self>))
}
}
impl ApproxEq<f32> for f32 {
#[inline]
fn approx_epsilon(_: Option<f32>) -> f32 {
1.0e-6
}
#[inline]
fn approx_eq_eps(&self, other: &f32, epsilon: &f32) -> bool {
::abs(&(*self - *other)) < *epsilon
}
fn approx_ulps(_: Option<f32>) -> u32 {
8
}
fn approx_eq_ulps(&self, other: &f32, ulps: u32) -> bool {
if *self == *other { return true; }
if self.signum() != other.signum() { return false; }
let iself: i32 = unsafe { ::std::mem::transmute(*self) };
let iother: i32 = unsafe { ::std::mem::transmute(*other) };
(iself - iother).abs() < ulps as i32
}
}
impl ApproxEq<f64> for f64 {
#[inline]
fn approx_epsilon(_: Option<f64>) -> f64 {
1.0e-6
}
#[inline]
fn approx_eq_eps(&self, other: &f64, approx_epsilon: &f64) -> bool {
::abs(&(*self - *other)) < *approx_epsilon
}
fn approx_ulps(_: Option<f64>) -> u32 {
8
}
fn approx_eq_ulps(&self, other: &f64, ulps: u32) -> bool {
if *self == *other { return true; }
if self.signum() != other.signum() { return false; }
let iself: i64 = unsafe { ::std::mem::transmute(*self) };
let iother: i64 = unsafe { ::std::mem::transmute(*other) };
(iself - iother).abs() < ulps as i64
}
}
impl<'a, N, T: ApproxEq<N>> ApproxEq<N> for &'a T {
fn approx_epsilon(_: Option<&'a T>) -> N {
ApproxEq::approx_epsilon(None::<T>)
}
fn approx_eq_eps(&self, other: &&'a T, approx_epsilon: &N) -> bool {
ApproxEq::approx_eq_eps(*self, *other, approx_epsilon)
}
fn approx_ulps(_: Option<&'a T>) -> u32 {
ApproxEq::approx_ulps(None::<T>)
}
fn approx_eq_ulps(&self, other: &&'a T, ulps: u32) -> bool {
ApproxEq::approx_eq_ulps(*self, *other, ulps)
}
}
impl<'a, N, T: ApproxEq<N>> ApproxEq<N> for &'a mut T {
fn approx_epsilon(_: Option<&'a mut T>) -> N {
ApproxEq::approx_epsilon(None::<T>)
}
fn approx_eq_eps(&self, other: &&'a mut T, approx_epsilon: &N) -> bool {
ApproxEq::approx_eq_eps(*self, *other, approx_epsilon)
}
fn approx_ulps(_: Option<&'a mut T>) -> u32 {
ApproxEq::approx_ulps(None::<T>)
}
fn approx_eq_ulps(&self, other: &&'a mut T, ulps: u32) -> bool {
ApproxEq::approx_eq_ulps(*self, *other, ulps)
}
}
pub trait Absolute<A> {
fn abs(&Self) -> A;
}
pub trait Inv {
fn inv(&self) -> Option<Self>;
fn inv_mut(&mut self) -> bool;
}
pub trait Det<N> {
fn det(&self) -> N;
}
pub trait Transpose {
fn transpose(&self) -> Self;
fn transpose_mut(&mut self);
}
pub trait Outer<M> {
fn outer(&self, other: &Self) -> M;
}
pub trait Cov<M> {
fn cov(&self) -> M;
fn cov_to(&self, out: &mut M) {
*out = self.cov()
}
}
pub trait Mean<N> {
fn mean(&self) -> N;
}
pub trait EigenQR<N, V>: SquareMat<N, V> {
fn eigen_qr(&self, eps: &N, niter: usize) -> (Self, V);
}
pub trait RMul<V> {
fn rmul(&self, v: &V) -> V;
}
impl<M: Copy + Mul<T, Output = T>, T: Copy> RMul<T> for M {
fn rmul(&self, v: &T) -> T {
*self * *v
}
}
pub trait LMul<V> {
fn lmul(&self, &V) -> V;
}
impl<T: Copy + Mul<M, Output = T>, M: Copy> LMul<T> for M {
fn lmul(&self, v: &T) -> T {
*v * *self
}
}
pub trait ScalarAdd<N> {
fn add_s(&self, n: &N) -> Self;
}
pub trait ScalarSub<N> {
fn sub_s(&self, n: &N) -> Self;
}
pub trait ScalarMul<N> {
fn mul_s(&self, n: &N) -> Self;
}
pub trait ScalarDiv<N> {
fn div_s(&self, n: &N) -> Self;
}
pub trait Axpy<N> {
fn axpy(&mut self, a: &N, x: &Self);
}
macro_rules! impl_absolute(
($n: ty) => {
impl Absolute<$n> for $n {
#[inline]
fn abs(n: &$n) -> $n {
n.abs()
}
}
}
);
macro_rules! impl_absolute_id(
($n: ty) => {
impl Absolute<$n> for $n {
#[inline]
fn abs(n: &$n) -> $n {
*n
}
}
}
);
impl_absolute!(f32);
impl_absolute!(f64);
impl_absolute!(i8);
impl_absolute!(i16);
impl_absolute!(i32);
impl_absolute!(i64);
impl_absolute!(isize);
impl_absolute_id!(u8);
impl_absolute_id!(u16);
impl_absolute_id!(u32);
impl_absolute_id!(u64);
impl_absolute_id!(usize);
macro_rules! impl_axpy(
($n: ty) => {
impl Axpy<$n> for $n {
#[inline]
fn axpy(&mut self, a: &$n, x: &$n) {
*self = *self + *a * *x
}
}
}
);
impl_axpy!(f32);
impl_axpy!(f64);
impl_axpy!(i8);
impl_axpy!(i16);
impl_axpy!(i32);
impl_axpy!(i64);
impl_axpy!(isize);
impl_axpy!(u8);
impl_axpy!(u16);
impl_axpy!(u32);
impl_axpy!(u64);
impl_axpy!(usize);