use crate::{CausalTensor, CausalTensorError, CausalTensorMathExt};
impl CausalTensorMathExt<f64> for CausalTensor<f64> {
fn log_nat(&self) -> Result<CausalTensor<f64>, CausalTensorError> {
if self.is_empty() {
return CausalTensor::new(vec![], self.shape().to_vec()); }
let new_data = self.as_slice().iter().map(|&val| val.ln()).collect();
CausalTensor::new(new_data, self.shape().to_vec())
}
fn log2(&self) -> Result<CausalTensor<f64>, CausalTensorError> {
if self.is_empty() {
return CausalTensor::new(vec![], self.shape().to_vec()); }
let new_data = self.as_slice().iter().map(|&val| val.log2()).collect();
CausalTensor::new(new_data, self.shape().to_vec())
}
fn log10(&self) -> Result<CausalTensor<f64>, CausalTensorError> {
if self.is_empty() {
return CausalTensor::new(vec![], self.shape().to_vec()); }
let new_data = self.as_slice().iter().map(|&val| val.log10()).collect();
CausalTensor::new(new_data, self.shape().to_vec())
}
fn surd_log2(&self) -> Result<CausalTensor<f64>, CausalTensorError> {
if self.is_empty() {
return CausalTensor::new(vec![], self.shape().to_vec());
}
let new_data = self
.as_slice()
.iter()
.map(|&val| if val == 0.0 { 0.0 } else { val.log2() })
.collect();
CausalTensor::new(new_data, self.shape().to_vec())
}
fn safe_div(&self, rhs: &CausalTensor<f64>) -> Result<CausalTensor<f64>, CausalTensorError> {
self.broadcast_op(rhs, |numerator, denominator| {
if denominator.abs() < 1e-14 {
if numerator.abs() < 1e-14 {
Ok(0.0) } else {
Err(CausalTensorError::DivisionByZero)
}
} else {
Ok(numerator / denominator)
}
})
}
}