use super::{BaseScalar, DivisibleScalar, FiniteScalar, MetricScalar, OrderedScalar};
use crate::error::SolverError;
macro_rules! impl_float_scalar {
($t:ty) => {
impl BaseScalar for $t {
#[inline]
fn zero() -> Self {
0.0
}
#[inline]
fn one() -> Self {
1.0
}
#[inline]
fn add(self, rhs: Self) -> Self {
self + rhs
}
#[inline]
fn sub(self, rhs: Self) -> Self {
self - rhs
}
#[inline]
fn mul(self, rhs: Self) -> Self {
self * rhs
}
#[inline]
fn neg(self) -> Self {
-self
}
}
impl OrderedScalar for $t {
#[inline]
fn min(self, rhs: Self) -> Self {
if self.is_nan() {
self
} else if rhs.is_nan() {
rhs
} else if self < rhs {
self
} else {
rhs
}
}
#[inline]
fn max(self, rhs: Self) -> Self {
if self.is_nan() {
self
} else if rhs.is_nan() {
rhs
} else if self > rhs {
self
} else {
rhs
}
}
}
impl FiniteScalar for $t {
#[inline]
fn is_finite(self) -> bool {
self.is_finite()
}
#[inline]
fn is_nan(self) -> bool {
self.is_nan()
}
#[inline]
fn is_infinite(self) -> bool {
self.is_infinite()
}
}
impl DivisibleScalar for $t {
#[inline]
fn checked_div(self, rhs: Self) -> Result<Self, SolverError> {
if rhs.is_zero() {
return Err(SolverError::NumericalDomain);
}
let q = self / rhs;
if !q.is_finite() {
return Err(SolverError::Overflow);
}
Ok(q)
}
}
impl MetricScalar for $t {
#[inline]
fn abs(self) -> Self {
self.abs()
}
#[inline]
fn epsilon() -> Self {
<$t>::EPSILON
}
}
};
}
impl_float_scalar!(f32);
impl_float_scalar!(f64);