stock-trek 0.6.0

Stock Trek time-series analysis
Documentation
use crate::{
    error::{
        general::GeneralError,
        result::{StockTrekError, StockTrekResult},
    },
    resolved_context::ResolvedContext,
    values::value::{NumberValue, NumberValueTrait},
};
use serde::{Deserialize, Serialize};
use strum::Display;

#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum UnaryOperator {
    Abs,
    Neg,
    Floor,
    Ceil,
    RoundAway0,
    RoundToEven,
    Trunc,
    Frac,
    Sqrt,
    Exp,
    Exp2,
    Log2,
    LogE,
    Log10,
    Sin,
    Cos,
    Tan,
    Asin,
    Acos,
    Atan,
    Sinh,
    Cosh,
    Tanh,
    Asinh,
    Acosh,
    Atanh,
}

#[derive(Clone, Serialize, Deserialize)]
pub struct UnaryCalculationValue {
    number: NumberValue,
    operator: UnaryOperator,
}

impl UnaryCalculationValue {
    pub fn new(number: NumberValue, operator: UnaryOperator) -> NumberValue {
        Box::new(Self { number, operator })
    }
}

#[typetag::serde]
impl NumberValueTrait for UnaryCalculationValue {
    fn clone_box(&self) -> NumberValue {
        Box::new(self.clone())
    }
    fn number(&self, c: &ResolvedContext) -> StockTrekResult<f64> {
        let value = self.number.number(c)?;
        let calculation_result = match self.operator {
            UnaryOperator::Abs => value.abs(),
            UnaryOperator::Acos => {
                if value < -1.0 {
                    return Err(StockTrekError::General(GeneralError::Message(format!(
                        "Acos: A value <-1 {} is not supported, it would give a complex number",
                        value
                    ))));
                }
                if value > 1.0 {
                    return Err(StockTrekError::General(GeneralError::Message(format!(
                        "Acos: A value >1 {} is not supported, it would give a complex number",
                        value
                    ))));
                }
                value.acos()
            }
            UnaryOperator::Acosh => {
                if value < 1.0 {
                    return Err(StockTrekError::General(GeneralError::Message(format!(
                        "Acos: A value <1 {} is not supported, it would give a complex number",
                        value
                    ))));
                }
                value.acosh()
            }
            UnaryOperator::Asin => {
                if value < -1.0 {
                    return Err(StockTrekError::General(GeneralError::Message(format!(
                        "Asin: A value <-1 {} is not supported, it would give a complex number",
                        value
                    ))));
                }
                if value > 1.0 {
                    return Err(StockTrekError::General(GeneralError::Message(format!(
                        "Asin: A value >1 {} is not supported, it would give a complex number",
                        value
                    ))));
                }
                value.asin()
            }
            UnaryOperator::Asinh => value.asinh(),
            UnaryOperator::Atan => value.atan(),
            UnaryOperator::Atanh => {
                if value == -1.0 {
                    return Err(StockTrekError::General(GeneralError::Message(
                        "Atanh: A value =-1 is not supported, it would give negative infinity"
                            .to_string(),
                    )));
                }
                if value == 1.0 {
                    return Err(StockTrekError::General(GeneralError::Message(
                        "Atanh: A value =1 is not supported, it would give positive infinity"
                            .to_string(),
                    )));
                }
                if value < -1.0 {
                    return Err(StockTrekError::General(GeneralError::Message(format!(
                        "Atanh: A value <-1 {} is not supported, it would give a complex number",
                        value
                    ))));
                }
                if value > 1.0 {
                    return Err(StockTrekError::General(GeneralError::Message(format!(
                        "Atanh: A value >1 {} is not supported, it would give a complex number",
                        value
                    ))));
                }
                value.atanh()
            }
            UnaryOperator::Ceil => value.ceil(),
            UnaryOperator::Cos => value.cos(),
            UnaryOperator::Cosh => value.cosh(),
            UnaryOperator::Exp => value.exp(),
            UnaryOperator::Exp2 => value.exp2(),
            UnaryOperator::Floor => value.floor(),
            UnaryOperator::Frac => value.fract(),
            UnaryOperator::Log10 => {
                if value == 0.0 {
                    return Err(StockTrekError::General(GeneralError::Message(
                        "Log10: A value =0 is not supported, it would give undefined".to_string(),
                    )));
                }
                if value < 0.0 {
                    return Err(StockTrekError::General(GeneralError::Message(format!(
                        "Log10: A value <0 {} is not supported, it would give a complex number",
                        value
                    ))));
                }
                value.log10()
            }
            UnaryOperator::Log2 => {
                if value == 0.0 {
                    return Err(StockTrekError::General(GeneralError::Message(
                        "Log2: A value =0 is not supported, it would give undefined".to_string(),
                    )));
                }
                if value < 0.0 {
                    return Err(StockTrekError::General(GeneralError::Message(format!(
                        "Log2: A value <0 {} is not supported, it would give a complex number",
                        value
                    ))));
                }
                value.log2()
            }
            UnaryOperator::LogE => {
                if value == 0.0 {
                    return Err(StockTrekError::General(GeneralError::Message(
                        "LogE: A value =0 is not supported, it would give undefined".to_string(),
                    )));
                }
                if value < 0.0 {
                    return Err(StockTrekError::General(GeneralError::Message(format!(
                        "LogE: A value <0 {} is not supported, it would give a complex number",
                        value
                    ))));
                }
                value.ln()
            }
            UnaryOperator::Neg => -value,
            UnaryOperator::RoundAway0 => value.round(),
            UnaryOperator::RoundToEven => value.round_ties_even(),
            UnaryOperator::Sin => value.sin(),
            UnaryOperator::Sinh => value.sinh(),
            UnaryOperator::Sqrt => {
                if value < 0.0 {
                    return Err(StockTrekError::General(GeneralError::Message(format!(
                        "Sqrt: A value <0 {} is not supported, it would give a complex number",
                        value
                    ))));
                }
                value.sqrt()
            }
            UnaryOperator::Tan => value.tan(),
            UnaryOperator::Tanh => value.tanh(),
            UnaryOperator::Trunc => value.trunc(),
        };
        Ok(calculation_result)
    }
}