use rand::rngs::SmallRng;
use rand::{RngExt, SeedableRng};
use num_traits::Float;
use crate::numbers::basenum::Number;
use crate::rand_custom::get_rng_impl;
pub trait RealNumber: Number + Float {
fn copysign(self, sign: Self) -> Self;
fn ln_1pe(self) -> Self;
fn sigmoid(self) -> Self;
fn rand() -> Self;
fn two() -> Self;
fn half() -> Self;
fn square(self) -> Self {
self * self
}
fn to_f32_bits(self) -> u32;
fn to_f64_bits(self) -> u64;
}
impl RealNumber for f64 {
fn copysign(self, sign: Self) -> Self {
self.copysign(sign)
}
fn ln_1pe(self) -> f64 {
if self > 15. {
self
} else {
self.exp().ln_1p()
}
}
fn sigmoid(self) -> f64 {
if self < -40. {
0.
} else if self > 40. {
1.
} else {
1. / (1. + f64::exp(-self))
}
}
fn rand() -> f64 {
let mut small_rng = get_rng_impl(None);
let mut rngs: Vec<SmallRng> = (0..3).map(|_| SmallRng::from_rng(&mut small_rng)).collect();
rngs[0].random::<f64>()
}
fn two() -> Self {
2f64
}
fn half() -> Self {
0.5f64
}
fn to_f32_bits(self) -> u32 {
self.to_bits() as u32
}
fn to_f64_bits(self) -> u64 {
self.to_bits()
}
}
impl RealNumber for f32 {
fn copysign(self, sign: Self) -> Self {
self.copysign(sign)
}
fn ln_1pe(self) -> f32 {
if self > 15. {
self
} else {
self.exp().ln_1p()
}
}
fn sigmoid(self) -> f32 {
if self < -40. {
0.
} else if self > 40. {
1.
} else {
1. / (1. + f32::exp(-self))
}
}
fn rand() -> f32 {
let mut small_rng = get_rng_impl(None);
let mut rngs: Vec<SmallRng> = (0..3).map(|_| SmallRng::from_rng(&mut small_rng)).collect();
rngs[0].random::<f32>()
}
fn two() -> Self {
2f32
}
fn half() -> Self {
0.5f32
}
fn to_f32_bits(self) -> u32 {
self.to_bits()
}
fn to_f64_bits(self) -> u64 {
self.to_bits() as u64
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn sigmoid() {
assert_eq!(1.0.sigmoid(), 0.7310585786300049);
assert_eq!(41.0.sigmoid(), 1.);
assert_eq!((-41.0).sigmoid(), 0.);
}
#[test]
fn f32_from_string() {
assert_eq!(f32::from_str("1.111111").unwrap(), 1.111111)
}
#[test]
fn f64_from_string() {
assert_eq!(f64::from_str("1.111111111").unwrap(), 1.111111111)
}
#[test]
fn f64_rand() {
f64::rand();
}
#[test]
fn f32_rand() {
f32::rand();
}
}