use crate::Complex;
use core::{
cmp::Ordering,
hash::{Hash, Hasher},
};
#[derive(Clone, Debug)]
#[repr(transparent)]
pub struct OrdComplex {
inner: Complex,
}
static_assert_same_layout!(OrdComplex, Complex);
impl OrdComplex {
#[inline]
pub fn as_complex(&self) -> &Complex {
&self.inner
}
#[inline]
pub fn as_complex_mut(&mut self) -> &mut Complex {
&mut self.inner
}
}
impl Hash for OrdComplex {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner.real().as_ord().hash(state);
self.inner.imag().as_ord().hash(state);
}
}
impl Eq for OrdComplex {}
impl Ord for OrdComplex {
#[inline]
fn cmp(&self, other: &OrdComplex) -> Ordering {
let real = self.inner.real().as_ord().cmp(other.inner.real().as_ord());
let imag = self.inner.imag().as_ord().cmp(other.inner.imag().as_ord());
real.then(imag)
}
}
impl PartialEq for OrdComplex {
#[inline]
fn eq(&self, other: &OrdComplex) -> bool {
let real = self.inner.real().as_ord().eq(other.inner.real().as_ord());
let imag = self.inner.imag().as_ord().eq(other.inner.imag().as_ord());
real && imag
}
}
impl PartialOrd for OrdComplex {
#[inline]
fn partial_cmp(&self, other: &OrdComplex) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl From<Complex> for OrdComplex {
#[inline]
fn from(src: Complex) -> Self {
OrdComplex { inner: src }
}
}
impl From<OrdComplex> for Complex {
#[inline]
fn from(src: OrdComplex) -> Self {
src.inner
}
}
#[cfg(test)]
mod tests {
use crate::{
float::{self, FreeCache, Special},
Complex,
};
use core::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;
fn calculate_hash<T: Hash>(t: &T) -> u64 {
let mut s = DefaultHasher::new();
t.hash(&mut s);
s.finish()
}
#[test]
fn check_zero() {
let pp = Complex::with_val(53, (Special::Zero, Special::Zero));
let pn = Complex::with_val(53, (Special::Zero, Special::NegZero));
let np = Complex::with_val(53, (Special::NegZero, Special::Zero));
let nn = Complex::with_val(53, (Special::NegZero, Special::NegZero));
assert_eq!(pp, pn);
assert_eq!(pn, np);
assert_eq!(np, nn);
assert_eq!(nn, pp);
let ord_pp = pp.as_ord();
let ord_pn = pn.as_ord();
let ord_np = np.as_ord();
let ord_nn = nn.as_ord();
assert_eq!(ord_pp, ord_pp);
assert_eq!(ord_pn, ord_pn);
assert_eq!(ord_np, ord_np);
assert_eq!(ord_nn, ord_nn);
assert_eq!(calculate_hash(ord_pp), calculate_hash(ord_pp));
assert_eq!(calculate_hash(ord_pn), calculate_hash(ord_pn));
assert_eq!(calculate_hash(ord_np), calculate_hash(ord_np));
assert_eq!(calculate_hash(ord_nn), calculate_hash(ord_nn));
assert_ne!(ord_pp, ord_pn);
assert_ne!(ord_pn, ord_np);
assert_ne!(ord_np, ord_nn);
assert_ne!(ord_nn, ord_pp);
assert_ne!(calculate_hash(ord_pp), calculate_hash(ord_pn));
assert_ne!(calculate_hash(ord_pn), calculate_hash(ord_np));
assert_ne!(calculate_hash(ord_np), calculate_hash(ord_nn));
assert_ne!(calculate_hash(ord_nn), calculate_hash(ord_pp));
float::free_cache(FreeCache::All);
}
}