From 1697cd5c7f915024cc8036230d62cffffb266c78 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 20 Jul 2023 12:33:23 -0600 Subject: [PATCH] add log10, hyperbolic tan and inverse hyperbolic tan functions (#1898) --- build/instructions_template.rs | 35 +++++++++++++++++ src/arithmetic.rs | 7 ++++ src/machine/arithmetic_ops.rs | 68 ++++++++++++++++++++++++++++++++++ src/machine/dispatch.rs | 63 +++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+) diff --git a/build/instructions_template.rs b/build/instructions_template.rs index 9b965750..8ec818e6 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -747,6 +747,20 @@ enum InstructionTemplate { Neg(ArithmeticTerm, usize), #[strum_discriminants(strum(props(Arity = "1", Name = "plus")))] Plus(ArithmeticTerm, usize), + #[strum_discriminants(strum(props(Arity = "1", Name = "acosh")))] + ACosh(ArithmeticTerm, usize), + #[strum_discriminants(strum(props(Arity = "1", Name = "asinh")))] + ASinh(ArithmeticTerm, usize), + #[strum_discriminants(strum(props(Arity = "1", Name = "atanh")))] + ATanh(ArithmeticTerm, usize), + #[strum_discriminants(strum(props(Arity = "1", Name = "cosh")))] + Cosh(ArithmeticTerm, usize), + #[strum_discriminants(strum(props(Arity = "1", Name = "sinh")))] + Sinh(ArithmeticTerm, usize), + #[strum_discriminants(strum(props(Arity = "1", Name = "tanh")))] + Tanh(ArithmeticTerm, usize), + #[strum_discriminants(strum(props(Arity = "1", Name = "log10")))] + Log10(ArithmeticTerm, usize), #[strum_discriminants(strum(props(Arity = "1", Name = "bitwise_complement")))] BitwiseComplement(ArithmeticTerm, usize), // control instructions @@ -1407,9 +1421,30 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::ATan(ref at, t) => { arith_instr_unary_functor(h, atom!("atan"), arena, at, t) } + &Instruction::ACosh(ref at, t) => { + arith_instr_unary_functor(h, atom!("acosh"), arena, at, t) + } + &Instruction::ASinh(ref at, t) => { + arith_instr_unary_functor(h, atom!("asinh"), arena, at, t) + } + &Instruction::ATanh(ref at, t) => { + arith_instr_unary_functor(h, atom!("atanh"), arena, at, t) + } + &Instruction::Cosh(ref at, t) => { + arith_instr_unary_functor(h, atom!("cosh"), arena, at, t) + } + &Instruction::Sinh(ref at, t) => { + arith_instr_unary_functor(h, atom!("sinh"), arena, at, t) + } + &Instruction::Tanh(ref at, t) => { + arith_instr_unary_functor(h, atom!("tanh"), arena, at, t) + } &Instruction::Sqrt(ref at, t) => { arith_instr_unary_functor(h, atom!("sqrt"), arena, at, t) } + &Instruction::Log10(ref at, t) => { + arith_instr_unary_functor(h, atom!("log10"), arena, at, t) + } &Instruction::Abs(ref at, t) => { arith_instr_unary_functor(h, atom!("abs"), arena, at, t) } diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 7f15a7f1..bc58da50 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -195,6 +195,13 @@ impl<'a> ArithmeticEvaluator<'a> { atom!("sin") => Ok(Instruction::Sin(a1, t)), atom!("tan") => Ok(Instruction::Tan(a1, t)), atom!("log") => Ok(Instruction::Log(a1, t)), + atom!("asinh") => Ok(Instruction::ASinh(a1, t)), + atom!("acosh") => Ok(Instruction::ACosh(a1, t)), + atom!("atanh") => Ok(Instruction::ATanh(a1, t)), + atom!("sinh") => Ok(Instruction::Sinh(a1, t)), + atom!("cosh") => Ok(Instruction::Cosh(a1, t)), + atom!("tanh") => Ok(Instruction::Tanh(a1, t)), + atom!("log10") => Ok(Instruction::Log10(a1, t)), atom!("exp") => Ok(Instruction::Exp(a1, t)), atom!("sqrt") => Ok(Instruction::Sqrt(a1, t)), atom!("acos") => Ok(Instruction::ACos(a1, t)), diff --git a/src/machine/arithmetic_ops.rs b/src/machine/arithmetic_ops.rs index 8eae327d..6af111b2 100644 --- a/src/machine/arithmetic_ops.rs +++ b/src/machine/arithmetic_ops.rs @@ -1006,6 +1006,53 @@ pub(crate) fn atan(n1: Number) -> Result { unary_float_fn_template(n1, |f| f.atan()) } +#[inline] +pub(crate) fn asinh(n1: Number) -> Result { + unary_float_fn_template(n1, |f| f.asinh()) +} + +#[inline] +pub(crate) fn acosh(n1: Number) -> Result { + unary_float_fn_template(n1, |f| f.acosh()) +} + +#[inline] +pub(crate) fn atanh(n1: Number) -> Result { + let stub_gen = || { + let is_atom = atom!("is"); + functor_stub(is_atom, 2) + }; + + let f1 = try_numeric_result!(result_f(&n1), stub_gen)?; + + try_numeric_result!(if f1 == 1.0 || f1 == -1.0 { + Err(EvalError::Undefined) + } else { + result_f(&Number::Float(OrderedFloat(f1.atanh()))) + }, + stub_gen) +} + +#[inline] +pub(crate) fn sinh(n1: Number) -> Result { + unary_float_fn_template(n1, |f| f.sinh()) +} + +#[inline] +pub(crate) fn cosh(n1: Number) -> Result { + unary_float_fn_template(n1, |f| f.cosh()) +} + +#[inline] +pub(crate) fn tanh(n1: Number) -> Result { + unary_float_fn_template(n1, |f| f.tanh()) +} + +#[inline] +pub(crate) fn log10(n1: Number) -> Result { + unary_float_fn_template(n1, |f| f.log(10f64)) +} + #[inline] pub(crate) fn sqrt(n1: Number) -> Result { if n1.is_negative() { @@ -1255,6 +1302,27 @@ impl MachineState { atom!("tan") => self.interms.push(Number::Float(OrderedFloat( drop_iter_on_err!(self, iter, tan(a1)) ))), + atom!("cosh") => self.interms.push(Number::Float(OrderedFloat( + drop_iter_on_err!(self, iter, cosh(a1)) + ))), + atom!("sinh") => self.interms.push(Number::Float(OrderedFloat( + drop_iter_on_err!(self, iter, sinh(a1)) + ))), + atom!("tanh") => self.interms.push(Number::Float(OrderedFloat( + drop_iter_on_err!(self, iter, tanh(a1)) + ))), + atom!("acosh") => self.interms.push(Number::Float(OrderedFloat( + drop_iter_on_err!(self, iter, acosh(a1)) + ))), + atom!("asinh") => self.interms.push(Number::Float(OrderedFloat( + drop_iter_on_err!(self, iter, asinh(a1)) + ))), + atom!("atanh") => self.interms.push(Number::Float(OrderedFloat( + drop_iter_on_err!(self, iter, atanh(a1)) + ))), + atom!("log10") => self.interms.push(Number::Float(OrderedFloat( + drop_iter_on_err!(self, iter, log10(a1)) + ))), atom!("sqrt") => self.interms.push(Number::Float(OrderedFloat( drop_iter_on_err!(self, iter, sqrt(a1)) ))), diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index f853dc7f..8f7e3e91 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -930,6 +930,69 @@ impl Machine { self.machine_st.p += 1; } + &Instruction::ACosh(ref a1, t) => { + let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); + + self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( + try_or_throw_gen!(&mut self.machine_st, acosh(n1)) + )); + + self.machine_st.p += 1; + } + &Instruction::ASinh(ref a1, t) => { + let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); + + self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( + try_or_throw_gen!(&mut self.machine_st, asinh(n1)) + )); + + self.machine_st.p += 1; + } + &Instruction::ATanh(ref a1, t) => { + let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); + + self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( + try_or_throw_gen!(&mut self.machine_st, atanh(n1)) + )); + + self.machine_st.p += 1; + } + &Instruction::Cosh(ref a1, t) => { + let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); + + self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( + try_or_throw_gen!(&mut self.machine_st, cosh(n1)) + )); + + self.machine_st.p += 1; + } + &Instruction::Sinh(ref a1, t) => { + let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); + + self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( + try_or_throw_gen!(&mut self.machine_st, sinh(n1)) + )); + + self.machine_st.p += 1; + } + &Instruction::Tanh(ref a1, t) => { + let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); + + self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( + try_or_throw_gen!(&mut self.machine_st, tanh(n1)) + )); + + self.machine_st.p += 1; + } + &Instruction::Log10(ref a1, t) => { + let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); + + self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( + try_or_throw_gen!(&mut self.machine_st, log10(n1)) + )); + + self.machine_st.p += 1; + } &Instruction::Float(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); -- 2.54.0