use num_traits::{Float, FromPrimitive, NumAssign};
use rustfft::FftNum;
use std::fmt::Debug;
use std::iter::Sum;
pub trait Bm3dFloat:
Float + FftNum + FromPrimitive + NumAssign + Sum + Debug + Send + Sync + 'static
{
const PI: Self;
const GAUSSIAN_TRUNCATE: Self;
fn from_f64_c(val: f64) -> Self;
fn usize_as(val: usize) -> Self;
fn isize_as(val: isize) -> Self;
}
impl Bm3dFloat for f32 {
const PI: Self = std::f32::consts::PI;
const GAUSSIAN_TRUNCATE: Self = 4.0;
#[inline]
fn from_f64_c(val: f64) -> Self {
val as f32
}
#[inline]
fn usize_as(val: usize) -> Self {
val as f32
}
#[inline]
fn isize_as(val: isize) -> Self {
val as f32
}
}
impl Bm3dFloat for f64 {
const PI: Self = std::f64::consts::PI;
const GAUSSIAN_TRUNCATE: Self = 4.0;
#[inline]
fn from_f64_c(val: f64) -> Self {
val
}
#[inline]
fn usize_as(val: usize) -> Self {
val as f64
}
#[inline]
fn isize_as(val: isize) -> Self {
val as f64
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_f32_trait_impl() {
let val: f32 = Bm3dFloat::from_f64_c(std::f64::consts::PI);
assert!((val - std::f32::consts::PI).abs() < 1e-5);
let usize_val: f32 = Bm3dFloat::usize_as(42);
assert_eq!(usize_val, 42.0f32);
let isize_val: f32 = Bm3dFloat::isize_as(-5);
assert_eq!(isize_val, -5.0f32);
}
#[test]
fn test_f64_trait_impl() {
let val: f64 = Bm3dFloat::from_f64_c(std::f64::consts::PI);
assert!((val - std::f64::consts::PI).abs() < 1e-14);
let usize_val: f64 = Bm3dFloat::usize_as(42);
assert_eq!(usize_val, 42.0f64);
let isize_val: f64 = Bm3dFloat::isize_as(-5);
assert_eq!(isize_val, -5.0f64);
}
#[test]
fn test_pi_constants() {
assert!((f32::PI - std::f32::consts::PI).abs() < 1e-10);
assert!((f64::PI - std::f64::consts::PI).abs() < 1e-15);
}
#[test]
fn test_gaussian_truncate() {
assert_eq!(f32::GAUSSIAN_TRUNCATE, 4.0f32);
assert_eq!(f64::GAUSSIAN_TRUNCATE, 4.0f64);
}
}