use crate::{FunctionData, FunctionDataAccessors, FunctionLogic, FunctionType, Interpolation, ValueCode, LOAD_ERROR_TOLERANCE};
use anchor_lang::prelude::*;
use num_traits::Inv;
use rust_decimal::{Decimal, MathematicalOps};
use crate::error::ErrorCode;
pub struct Exp {}
impl FunctionLogic for Exp {
const FUNCTION_TYPE: FunctionType = FunctionType::Exp;
fn validate_load(x_in: Decimal, y_in: Decimal) -> Result<(Decimal, ValueCode)> {
let diff = Self::proportion_difference(x_in, y_in.ln())?;
if diff > LOAD_ERROR_TOLERANCE {
return err!(ErrorCode::InvalidValue);
}
Ok((y_in, ValueCode::Valid))
}
fn eval(fd: &FunctionData, x_in: Decimal, interp: Interpolation, saturating: bool) -> Result<Decimal> {
let mut x = x_in;
let is_negative = x.is_sign_negative();
if is_negative {
x.set_sign_positive(true);
}
let domain_end = fd.get_domain_end()?;
if x > domain_end {
if saturating {
x = domain_end;
} else {
return err!(ErrorCode::OutOfDomainBounds);
}
}
let mut y = Self::interpolate(fd, x, interp)?;
if is_negative {
y = y.inv();
}
Ok(y)
}
}