From acb90fbb9df8561071cbf47b3127541511d8b12e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Hatcher?= Date: Wed, 19 Nov 2025 19:25:14 +0100 Subject: [PATCH] FIX: Issues with trigonometric functions * Right branch for ACOT for negative numbers * correct error for ACOTH * Correct approx for COTH for x > 20 --- base/src/functions/mathematical.rs | 18 +++++++++++++++--- .../calc_tests/trigonometric_functions.xlsx | Bin 14302 -> 18731 bytes 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/base/src/functions/mathematical.rs b/base/src/functions/mathematical.rs index 025e109..2bc0c51 100644 --- a/base/src/functions/mathematical.rs +++ b/base/src/functions/mathematical.rs @@ -1278,9 +1278,18 @@ impl Model { Ok((f * PI).sqrt()) }); - single_number_fn!(fn_acot, |f| Ok(f64::atan(1.0 / f))); + single_number_fn!(fn_acot, |f| { + let v = f64::atan(1.0 / f); + if f >= 0.0 { + Ok(v) + } else { + // To be compatible with Excel we need a different branch + // when f < 0 + Ok(v + PI) + } + }); single_number_fn!(fn_acoth, |f: f64| if f.abs() == 1.0 { - Err(Error::DIV) + Err(Error::NUM) } else { Ok(0.5 * (f64::ln((f + 1.0) / (f - 1.0)))) }); @@ -1289,8 +1298,11 @@ impl Model { } else { Ok(f64::cos(f) / f64::sin(f)) }); - single_number_fn!(fn_coth, |f| if f == 0.0 { + single_number_fn!(fn_coth, |f: f64| if f == 0.0 { Err(Error::DIV) + } else if f.abs() > 20.0 { + // for values > 20.0 this is exact in f64 + Ok(f.signum()) } else { Ok(f64::cosh(f) / f64::sinh(f)) }); diff --git a/xlsx/tests/calc_tests/trigonometric_functions.xlsx b/xlsx/tests/calc_tests/trigonometric_functions.xlsx index 65def212a567c3ca03a9ffe131e327c176585d24..c8cb524131fe18305399780075032e4c4a346292 100644 GIT binary patch delta 14298 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 delta 9920 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