use std::collections::VecDeque;
use num_traits::Float;
use crate::{Norm, Distance};
use crate::desc::{Abs, PNorm};
use super::{NormEucl, DistanceEucl};
impl<T: Norm<Abs>> NormEucl for T {
type Output = <Self as Norm<Abs>>::Output;
fn norm_eucl(&self) -> <Self as NormEucl>::Output {
self.norm(Abs::new())
}
}
impl<T: Distance<Abs>> DistanceEucl for T {
type Output = <Self as Distance<Abs>>::Output;
fn distance_eucl(&self, other: &Self) -> <Self as DistanceEucl>::Output {
self.distance(other, Abs::new())
}
}
impl<T: Norm<Abs, Output = R>, R: Float + From<f32>> NormEucl for Vec<T> {
type Output = R;
fn norm_eucl(&self) -> R {
self.norm(PNorm::eucl())
}
}
impl<T: Distance<Abs, Output = R>, R: Float + From<f32>> DistanceEucl for Vec<T> {
type Output = R;
fn distance_eucl(&self, other: &Self) -> R {
self.distance(other, PNorm::eucl())
}
}
impl<T: Norm<Abs, Output = R>, R: Float + From<f32>> NormEucl for VecDeque<T> {
type Output = R;
fn norm_eucl(&self) -> R {
self.norm(PNorm::eucl())
}
}
impl<T: Distance<Abs, Output = R>, R: Float + From<f32>> DistanceEucl for VecDeque<T> {
type Output = R;
fn distance_eucl(&self, other: &Self) -> R {
self.distance(other, PNorm::eucl())
}
}
#[cfg(feature = "array")]
#[doc(hidden)]
pub mod array {
use num_traits::Float;
use ndarray::Array1;
use crate::{Norm, Distance};
use crate::desc::{Abs, PNorm};
use super::{NormEucl, DistanceEucl};
macro_rules! impl_array_eucl {
( $( $n:literal )* ) => ($(
impl<T: Norm<Abs, Output = R>, R: Float + From<f32>> NormEucl for [T; $n] {
type Output = R;
fn norm_eucl(&self) -> R {
self.norm(PNorm::eucl())
}
}
impl<T: Distance<Abs, Output = R>, R: Float + From<f32>> DistanceEucl for [T; $n] {
type Output = R;
fn distance_eucl(&self, other: &Self) -> R {
self.distance(other, PNorm::eucl())
}
}
)*)
}
impl_array_eucl!(
0
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
);
}
#[cfg(feature = "ndarray")]
#[doc(hidden)]
pub mod ndarray {
use num_traits::Float;
use ndarray::Array1;
use crate::{Norm, Distance};
use crate::desc::{Abs, PNorm};
use super::{NormEucl, DistanceEucl};
impl<T: Norm<Abs, Output = R>, R: Float + From<f32>> NormEucl for Array1<T> {
type Output = R;
fn norm_eucl(&self) -> R {
self.norm(PNorm::eucl())
}
}
impl<T: Distance<Abs, Output = R>, R: Float + From<f32>> DistanceEucl for Array1<T> {
type Output = R;
fn distance_eucl(&self, other: &Self) -> R {
self.distance(other, PNorm::eucl())
}
}
}
#[cfg(test)]
mod tests {
use std::collections::VecDeque;
use super::super::{DistanceEucl, NormEucl};
#[test]
fn norm_eucl_floating_point() {
assert_eq!((-2.0f32).norm_eucl(), 2.0);
assert_eq!((-3.0f64).norm_eucl(), 3.0);
}
#[test]
fn distance_eucl_floating_point() {
assert_eq!((5.0f32).distance_eucl(&3.0), 2.0);
assert_eq!((2.0f32).distance_eucl(&-3.0), 5.0);
assert_eq!((1.0f64).distance_eucl(&4.0), 3.0);
}
#[test]
fn norm_eucl_unsigned_integer() {
assert_eq!(2u8.norm_eucl(), 2);
assert_eq!(3u16.norm_eucl(), 3);
assert_eq!(4u32.norm_eucl(), 4);
assert_eq!(5u64.norm_eucl(), 5);
assert_eq!(6usize.norm_eucl(), 6);
}
#[test]
fn norm_eucl_signed_integer() {
assert_eq!((-2i8).norm_eucl(), 2);
assert_eq!((-3i16).norm_eucl(), 3);
assert_eq!((-4i32).norm_eucl(), 4);
assert_eq!((-5i64).norm_eucl(), 5);
assert_eq!((-6isize).norm_eucl(), 6);
}
#[test]
fn normalize() {
let mut a = 0.25f32;
super::super::normalize_eucl(&mut a);
assert_eq!(a, 1.0);
let mut a = -3.0f32;
super::super::normalize_eucl(&mut a);
assert_eq!(a, -1.0);
}
#[test]
fn normalized() {
assert_eq!(super::super::normalized_eucl(0.25f32), 1.0);
assert_eq!(super::super::normalized_eucl(-3.0f32), -1.0);
}
#[cfg(feature = "num-complex")]
mod num_complex {
use num_complex::Complex;
use crate::special::{NormEucl, DistanceEucl};
#[test]
fn norm_eucl_complex() {
assert_eq!(Complex::new(3.0f32, 4.0f32).norm_eucl(), 5.0);
assert_eq!(
Complex::new(3.0f32, 4.0f32).distance_eucl(&Complex::new(3.0f32, 1.0f32)),
3.0
);
}
}
#[test]
fn norm_eucl_vec() {
let a = vec![3.0f32, -4.0, 2.0];
assert_eq!(a.norm_eucl(), 29.0f32.sqrt());
let b = vec![2.0f32, 2.0, 2.0];
assert_eq!(a.distance_eucl(&b), 37.0f32.sqrt());
}
#[test]
fn norm_eucl_vec_deque() {
let a = VecDeque::from(vec![3.0f32, -4.0, 2.0]);
assert_eq!(a.norm_eucl(), 29.0f32.sqrt());
let b = VecDeque::from(vec![2.0f32, 2.0, 2.0]);
assert_eq!(a.distance_eucl(&b), 37.0f32.sqrt());
}
#[cfg(feature = "array")]
#[test]
fn norm_eucl_array() {
let a = [3.0f32, -4.0, 2.0];
assert_eq!(a.norm_eucl(), 29.0f32.sqrt());
let b = [2.0f32, 2.0, 2.0];
assert_eq!(a.distance_eucl(&b), 37.0f32.sqrt());
}
#[cfg(feature = "ndarray")]
mod ndarray {
use ndarray::Array1;
use crate::special::{NormEucl, DistanceEucl};
#[test]
fn norm_eucl_ndarray() {
let a = Array1::from(vec![3.0f32, -4.0, 2.0]);
assert_eq!(a.norm_eucl(), 29.0f32.sqrt());
let b = Array1::from(vec![2.0f32, 2.0, 2.0]);
assert_eq!(a.distance_eucl(&b), 37.0f32.sqrt());
}
}
}