Skip to main content

decimal_scaled/types/traits/
transcendental.rs

1// SPDX-FileCopyrightText: 2026 John Moxley
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! The [`DecimalTranscendental`] trait — the width-generic
5//! transcendental + root surface shared by every decimal type.
6//!
7//! Implemented by every width (`D18`, `D38`, `D57`, `D76`,
8//! `D115`, `D153`, `D230`, `D307`, `D462`, `D616`, `D924`, `D1232`).
9//! Each impl is a one-line delegator to the inherent method of the
10//! same name, so the trait costs nothing at runtime — `#[inline]` on
11//! every method lets LLVM erase the trait dispatch.
12//!
13//! Use it for width-generic helpers:
14//!
15//! ```ignore
16//! use decimal_scaled::{DecimalTranscendental, DecimalConstants};
17//! use decimal_scaled::rounding::RoundingMode;
18//!
19//! fn area_of_disc<T>(radius: T) -> T
20//! where
21//!     T: DecimalTranscendental + DecimalConstants
22//!         + Copy + std::ops::Mul<Output = T>,
23//! {
24//!     T::pi() * radius * radius
25//! }
26//! ```
27//!
28//! # Scope
29//!
30//! Every transcendental and root that has an inherent method on every
31//! width is exposed here in its **four-variant** form (where
32//! applicable):
33//!
34//! - `<fn>_strict` — crate-default guard width + crate-default mode
35//! - `<fn>_strict_with(mode)` — crate-default guard, caller mode
36//! - `<fn>_approx(working_digits)` — caller guard, crate-default mode
37//! - `<fn>_approx_with(working_digits, mode)` — both caller-chosen
38//!
39//! Roots (`sqrt` / `cbrt` / `hypot`) only ship the `_strict` /
40//! `_strict_with` pair — the exact-integer-root path is precision-
41//! independent, so there's no `working_digits` parameter to expose.
42//!
43//! # What's NOT on the trait
44//!
45//! - Joint kernels like `sin_cos` / `sinh_cosh` exist only on the
46//!   wide-tier macros and aren't available on D18 / D38. Access
47//!   them via the concrete type.
48//! - Mathematical constants (`pi`, `tau`, `e`, …) live on the
49//!   separate [`DecimalConstants`] trait so callers can opt in to just
50//!   constants without pulling in the full transcendental surface.
51//!
52//! [`DecimalConstants`]: crate::DecimalConstants
53
54use crate::support::rounding::RoundingMode;
55
56/// Width-generic transcendental + root surface shared by every
57/// decimal width. See the module-level docs for the four-variant
58/// matrix convention and the per-method delegation contract.
59pub trait DecimalTranscendental: Sized {
60    // ── Logarithms ─────────────────────────────────────────────
61
62    /// Natural log. See the log/exp implementation module for the
63    /// algorithm.
64    fn ln_strict(self) -> Self;
65    fn ln_strict_with(self, mode: RoundingMode) -> Self;
66    fn ln_approx(self, working_digits: u32) -> Self;
67    fn ln_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
68
69    /// Log to caller-chosen base.
70    fn log_strict(self, base: Self) -> Self;
71    fn log_strict_with(self, base: Self, mode: RoundingMode) -> Self;
72    fn log_approx(self, base: Self, working_digits: u32) -> Self;
73    fn log_approx_with(self, base: Self, working_digits: u32, mode: RoundingMode) -> Self;
74
75    /// Log base 2.
76    fn log2_strict(self) -> Self;
77    fn log2_strict_with(self, mode: RoundingMode) -> Self;
78    fn log2_approx(self, working_digits: u32) -> Self;
79    fn log2_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
80
81    /// Log base 10.
82    fn log10_strict(self) -> Self;
83    fn log10_strict_with(self, mode: RoundingMode) -> Self;
84    fn log10_approx(self, working_digits: u32) -> Self;
85    fn log10_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
86
87    // ── Exponentials ───────────────────────────────────────────
88
89    fn exp_strict(self) -> Self;
90    fn exp_strict_with(self, mode: RoundingMode) -> Self;
91    fn exp_approx(self, working_digits: u32) -> Self;
92    fn exp_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
93
94    fn exp2_strict(self) -> Self;
95    fn exp2_strict_with(self, mode: RoundingMode) -> Self;
96    fn exp2_approx(self, working_digits: u32) -> Self;
97    fn exp2_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
98
99    // ── Power ──────────────────────────────────────────────────
100
101    fn powf_strict(self, exp: Self) -> Self;
102    fn powf_strict_with(self, exp: Self, mode: RoundingMode) -> Self;
103    fn powf_approx(self, exp: Self, working_digits: u32) -> Self;
104    fn powf_approx_with(self, exp: Self, working_digits: u32, mode: RoundingMode) -> Self;
105
106    // ── Roots ──────────────────────────────────────────────────
107    //
108    // No `_approx` siblings — the exact-integer-root path has no
109    // guard-width parameter to expose.
110
111    fn sqrt_strict(self) -> Self;
112    fn sqrt_strict_with(self, mode: RoundingMode) -> Self;
113
114    fn cbrt_strict(self) -> Self;
115    fn cbrt_strict_with(self, mode: RoundingMode) -> Self;
116
117    fn hypot_strict(self, other: Self) -> Self;
118    fn hypot_strict_with(self, other: Self, mode: RoundingMode) -> Self;
119
120    // ── Trig (forward) ─────────────────────────────────────────
121
122    fn sin_strict(self) -> Self;
123    fn sin_strict_with(self, mode: RoundingMode) -> Self;
124    fn sin_approx(self, working_digits: u32) -> Self;
125    fn sin_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
126
127    fn cos_strict(self) -> Self;
128    fn cos_strict_with(self, mode: RoundingMode) -> Self;
129    fn cos_approx(self, working_digits: u32) -> Self;
130    fn cos_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
131
132    fn tan_strict(self) -> Self;
133    fn tan_strict_with(self, mode: RoundingMode) -> Self;
134    fn tan_approx(self, working_digits: u32) -> Self;
135    fn tan_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
136
137    // ── Trig (inverse) ─────────────────────────────────────────
138
139    fn atan_strict(self) -> Self;
140    fn atan_strict_with(self, mode: RoundingMode) -> Self;
141    fn atan_approx(self, working_digits: u32) -> Self;
142    fn atan_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
143
144    fn asin_strict(self) -> Self;
145    fn asin_strict_with(self, mode: RoundingMode) -> Self;
146    fn asin_approx(self, working_digits: u32) -> Self;
147    fn asin_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
148
149    fn acos_strict(self) -> Self;
150    fn acos_strict_with(self, mode: RoundingMode) -> Self;
151    fn acos_approx(self, working_digits: u32) -> Self;
152    fn acos_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
153
154    /// `atan2(self, other)` — matches the f64 convention where
155    /// `self` is `y` and `other` is `x`.
156    fn atan2_strict(self, other: Self) -> Self;
157    fn atan2_strict_with(self, other: Self, mode: RoundingMode) -> Self;
158    fn atan2_approx(self, other: Self, working_digits: u32) -> Self;
159    fn atan2_approx_with(self, other: Self, working_digits: u32, mode: RoundingMode) -> Self;
160
161    // ── Hyperbolic ─────────────────────────────────────────────
162
163    fn sinh_strict(self) -> Self;
164    fn sinh_strict_with(self, mode: RoundingMode) -> Self;
165    fn sinh_approx(self, working_digits: u32) -> Self;
166    fn sinh_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
167
168    fn cosh_strict(self) -> Self;
169    fn cosh_strict_with(self, mode: RoundingMode) -> Self;
170    fn cosh_approx(self, working_digits: u32) -> Self;
171    fn cosh_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
172
173    fn tanh_strict(self) -> Self;
174    fn tanh_strict_with(self, mode: RoundingMode) -> Self;
175    fn tanh_approx(self, working_digits: u32) -> Self;
176    fn tanh_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
177
178    fn asinh_strict(self) -> Self;
179    fn asinh_strict_with(self, mode: RoundingMode) -> Self;
180    fn asinh_approx(self, working_digits: u32) -> Self;
181    fn asinh_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
182
183    fn acosh_strict(self) -> Self;
184    fn acosh_strict_with(self, mode: RoundingMode) -> Self;
185    fn acosh_approx(self, working_digits: u32) -> Self;
186    fn acosh_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
187
188    fn atanh_strict(self) -> Self;
189    fn atanh_strict_with(self, mode: RoundingMode) -> Self;
190    fn atanh_approx(self, working_digits: u32) -> Self;
191    fn atanh_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
192
193    // ── Angle conversion ───────────────────────────────────────
194
195    fn to_degrees_strict(self) -> Self;
196    fn to_degrees_strict_with(self, mode: RoundingMode) -> Self;
197    fn to_degrees_approx(self, working_digits: u32) -> Self;
198    fn to_degrees_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
199
200    fn to_radians_strict(self) -> Self;
201    fn to_radians_strict_with(self, mode: RoundingMode) -> Self;
202    fn to_radians_approx(self, working_digits: u32) -> Self;
203    fn to_radians_approx_with(self, working_digits: u32, mode: RoundingMode) -> Self;
204}