1- //! Implementations of advanced math functions
1+ //! Advanced mathematical functions
22
3- // TODO: implement the math functions as associated methods, and add them to FBig through a trait
4- // REF: https://pkg.go.dev/github.com/ericlagergren/decimal
3+ use crate :: {
4+ error:: { panic_infinite, panic_nan, panic_overflow, panic_underflow} ,
5+ fbig:: FBig ,
6+ repr:: { Context , Repr , Word } ,
7+ round:: { Round , Rounded } ,
8+ } ;
59
6- enum FpResult {
7- Normal ( Repr ) ,
10+ pub mod consts;
11+ pub mod trig;
12+
13+ /// The result of an advanced mathematical operation.
14+ ///
15+ /// This enum is used to handle non-finite results (NaN, Infinite) and
16+ /// boundary conditions (Overflow, Underflow) without panicking,
17+ /// as the core [`FBig`] type only represents finite numbers.
18+ ///
19+ /// Finite results are wrapped in a [Rounded] to preserve rounding information.
20+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
21+ pub enum FpResult < const B : Word > {
22+ Normal ( Rounded < Repr < B > > ) ,
823 Overflow ,
924 Underflow ,
1025 NaN ,
11-
1226 /// An exact infinite result is obtained from finite inputs, such as
13- /// divide by zero, logarithm on zero.
27+ /// divide by zero or logarithm of zero.
1428 Infinite ,
1529}
1630
17- impl Context {
18- fn sin ( & self , repr : Repr ) -> FpResult {
19- todo ! ( )
31+ impl < const B : Word > FpResult < B > {
32+ /// Convert the result into an [`FBig`] with the given context.
33+ ///
34+ /// # Panics
35+ /// Panics if the result is not `Normal`.
36+ #[ inline]
37+ #[ must_use]
38+ pub fn value < R : Round > ( self , context : & Context < R > ) -> FBig < R , B > {
39+ match self {
40+ Self :: Normal ( rounded) => FBig :: new ( rounded. value ( ) , * context) ,
41+ Self :: NaN => panic_nan ( ) ,
42+ Self :: Infinite => panic_infinite ( ) ,
43+ Self :: Overflow => panic_overflow ( ) ,
44+ Self :: Underflow => panic_underflow ( ) ,
45+ }
46+ }
47+
48+ /// Convert the result into an optional [`FBig`] with the given context.
49+ /// Returns `None` if the result is not `Normal`.
50+ #[ inline]
51+ #[ must_use]
52+ pub fn ok < R : Round > ( self , context : & Context < R > ) -> Option < Rounded < FBig < R , B > > > {
53+ match self {
54+ Self :: Normal ( rounded) => Some ( rounded. map ( |repr| FBig :: new ( repr, * context) ) ) ,
55+ _ => None ,
56+ }
57+ }
58+
59+ /// Returns `true` if the result is `NaN`.
60+ #[ inline]
61+ #[ must_use]
62+ pub const fn is_nan ( & self ) -> bool {
63+ matches ! ( self , Self :: NaN )
64+ }
65+
66+ /// Returns `true` if the result is `Infinite`.
67+ #[ inline]
68+ #[ must_use]
69+ pub const fn is_infinite ( & self ) -> bool {
70+ matches ! ( self , Self :: Infinite )
71+ }
72+
73+ /// Returns `true` if the result is a normal finite value.
74+ #[ inline]
75+ #[ must_use]
76+ pub const fn is_normal ( & self ) -> bool {
77+ matches ! ( self , Self :: Normal ( _) )
78+ }
79+
80+ /// Returns `true` if the result is a finite value (Normal, Overflow, or Underflow).
81+ #[ inline]
82+ #[ must_use]
83+ pub const fn is_finite ( & self ) -> bool {
84+ matches ! ( self , Self :: Normal ( _) | Self :: Overflow | Self :: Underflow )
2085 }
2186}
2287
23- trait ContextOps {
24- fn context ( & self ) -> & Context ;
25- fn repr ( & self ) -> & Repr ;
88+ /// Operations that can be performed on floating point numbers via their context.
89+ pub trait ContextOps < R : Round , const B : Word > {
90+ fn context ( & self ) -> & Context < R > ;
91+ fn repr ( & self ) -> & Repr < B > ;
2692
93+ /// Calculate the sine of the number.
2794 #[ inline]
28- fn sin ( & self ) -> FpResult {
95+ fn sin ( & self ) -> FpResult < B > {
2996 self . context ( ) . sin ( self . repr ( ) )
3097 }
31- }
98+
99+ /// Calculate the cosine of the number.
100+ #[ inline]
101+ fn cos ( & self ) -> FpResult < B > {
102+ self . context ( ) . cos ( self . repr ( ) )
103+ }
104+
105+ /// Calculate both the sine and cosine of the number.
106+ #[ inline]
107+ fn sin_cos ( & self ) -> ( FpResult < B > , FpResult < B > ) {
108+ self . context ( ) . sin_cos ( self . repr ( ) )
109+ }
110+
111+ /// Calculate the tangent of the number.
112+ #[ inline]
113+ fn tan ( & self ) -> FpResult < B > {
114+ self . context ( ) . tan ( self . repr ( ) )
115+ }
116+
117+ /// Calculate the arcsine of the number.
118+ #[ inline]
119+ fn asin ( & self ) -> FpResult < B > {
120+ self . context ( ) . asin ( self . repr ( ) )
121+ }
122+
123+ /// Calculate the arccosine of the number.
124+ #[ inline]
125+ fn acos ( & self ) -> FpResult < B > {
126+ self . context ( ) . acos ( self . repr ( ) )
127+ }
128+
129+ /// Calculate the arctangent of the number.
130+ #[ inline]
131+ fn atan ( & self ) -> FpResult < B > {
132+ self . context ( ) . atan ( self . repr ( ) )
133+ }
134+
135+ /// Calculate the 2-argument arctangent of the number (`y`) and `x`.
136+ #[ inline]
137+ fn atan2 ( & self , x : & Repr < B > ) -> FpResult < B > {
138+ self . context ( ) . atan2 ( self . repr ( ) , x)
139+ }
140+ }
141+
142+ impl < R : Round , const B : Word > ContextOps < R , B > for FBig < R , B > {
143+ #[ inline]
144+ fn context ( & self ) -> & Context < R > {
145+ & self . context
146+ }
147+ #[ inline]
148+ fn repr ( & self ) -> & Repr < B > {
149+ & self . repr
150+ }
151+ }
0 commit comments