rs_math3d/
scalar.rs

1//! Scalar trait definitions for generic numeric operations.
2//!
3//! This module defines traits that extend `num-traits` for use in
4//! mathematical operations throughout the library. It provides a
5//! unified interface for both integer and floating-point types.
6//!
7//! The module leverages the `num-traits` crate for basic numeric
8//! operations while adding specialized methods needed for 3D math.
9
10// Copyright 2020-Present (c) Raja Lehtihet & Wael El Oraiby
11//
12// Redistribution and use in source and binary forms, with or without
13// modification, are permitted provided that the following conditions are met:
14//
15// 1. Redistributions of source code must retain the above copyright notice,
16// this list of conditions and the following disclaimer.
17//
18// 2. Redistributions in binary form must reproduce the above copyright notice,
19// this list of conditions and the following disclaimer in the documentation
20// and/or other materials provided with the distribution.
21//
22// 3. Neither the name of the copyright holder nor the names of its contributors
23// may be used to endorse or promote products derived from this software without
24// specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
30// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36// POSSIBILITY OF SUCH DAMAGE.
37
38use num_traits::{Num, NumAssignOps};
39use core::cmp::PartialOrd;
40use core::ops::Neg;
41
42// Re-export for convenience
43pub use num_traits::{Zero, One};
44
45/// Core scalar trait for numeric types used in the library.
46///
47/// This trait extends `num-traits` types with additional methods
48/// commonly needed in 3D mathematics. It is implemented for
49/// `i32`, `i64`, `f32`, and `f64`.
50///
51/// # Required Methods
52///
53/// Types implementing this trait must provide:
54/// - Basic arithmetic operations (via `Num` and `NumAssignOps`)
55/// - Comparison operations (via `PartialOrd`)
56/// - Additional constants and utility methods
57pub trait Scalar:
58    Num
59    + NumAssignOps
60    + Neg<Output = Self>
61    + PartialOrd
62    + Clone
63    + Copy
64    + Sized
65{
66    // Additional methods not provided by num-traits
67    fn two() -> Self;
68    fn half() -> Self;
69    fn quarter() -> Self;
70    fn l8192() -> Self;
71    fn epsilon() -> Self;
72    fn min(l: Self, r: Self) -> Self;
73    fn max(l: Self, r: Self) -> Self;
74    fn squared(self) -> Self {
75        self * self
76    }
77    fn tabs(self) -> Self;
78}
79
80/// Trait for floating-point scalars with transcendental functions.
81///
82/// Extends the base `Scalar` trait with operations specific to
83/// floating-point numbers, including trigonometric functions and
84/// square root.
85///
86/// # Implementation Note
87///
88/// These functions link to external C math libraries (libm on Unix,
89/// MSVCRT on Windows) since they're not available in no_std Rust.
90pub trait FloatScalar: Scalar {
91    fn infinity() -> Self;
92    fn tsqrt(self) -> Self;
93    fn tsin(self) -> Self;
94    fn tcos(self) -> Self;
95    fn ttan(self) -> Self;
96    fn tacos(self) -> Self;
97}
98
99// Implementation for i32
100impl Scalar for i32 {
101    fn two() -> Self { 2 }
102    fn half() -> Self { 0 }  // Integer division
103    fn quarter() -> Self { 0 }  // Integer division
104    fn l8192() -> Self { 8192 }
105    fn epsilon() -> Self { 0 }
106    fn min(l: Self, r: Self) -> Self {
107        if l < r { l } else { r }
108    }
109    fn max(l: Self, r: Self) -> Self {
110        if l > r { l } else { r }
111    }
112    fn tabs(self) -> Self {
113        self.abs()
114    }
115}
116
117// Implementation for i64
118impl Scalar for i64 {
119    fn two() -> Self { 2 }
120    fn half() -> Self { 0 }  // Integer division
121    fn quarter() -> Self { 0 }  // Integer division
122    fn l8192() -> Self { 8192 }
123    fn epsilon() -> Self { 0 }
124    fn min(l: Self, r: Self) -> Self {
125        if l < r { l } else { r }
126    }
127    fn max(l: Self, r: Self) -> Self {
128        if l > r { l } else { r }
129    }
130    fn tabs(self) -> Self {
131        self.abs()
132    }
133}
134
135// Implementation for f32
136impl Scalar for f32 {
137    fn two() -> Self { 2.0 }
138    fn half() -> Self { 0.5 }
139    fn quarter() -> Self { 0.25 }
140    fn l8192() -> Self { 8192.0 }
141    fn epsilon() -> Self { 
142        1.0 / (1024.0 * 1024.0)
143    }
144    fn min(l: Self, r: Self) -> Self {
145        if l < r { l } else { r }
146    }
147    fn max(l: Self, r: Self) -> Self {
148        if l > r { l } else { r }
149    }
150    fn tabs(self) -> Self {
151        self.abs()
152    }
153}
154
155// Implementation for f64
156impl Scalar for f64 {
157    fn two() -> Self { 2.0 }
158    fn half() -> Self { 0.5 }
159    fn quarter() -> Self { 0.25 }
160    fn l8192() -> Self { 8192.0 }
161    fn epsilon() -> Self {
162        1.0 / (1024.0 * 1024.0 * 1024.0 * 1024.0)
163    }
164    fn min(l: Self, r: Self) -> Self {
165        if l < r { l } else { r }
166    }
167    fn max(l: Self, r: Self) -> Self {
168        if l > r { l } else { r }
169    }
170    fn tabs(self) -> Self {
171        self.abs()
172    }
173}
174
175// FloatScalar implementation for f32
176// Note: Without std or libm, we need to provide our own implementations
177// or link to external math libraries
178impl FloatScalar for f32 {
179    fn infinity() -> Self {
180        core::f32::INFINITY
181    }
182    fn tsqrt(self) -> Self {
183        // Use external C math function
184        extern "C" {
185            fn sqrtf(x: f32) -> f32;
186        }
187        unsafe { sqrtf(self) }
188    }
189    fn tsin(self) -> Self {
190        extern "C" {
191            fn sinf(x: f32) -> f32;
192        }
193        unsafe { sinf(self) }
194    }
195    fn tcos(self) -> Self {
196        extern "C" {
197            fn cosf(x: f32) -> f32;
198        }
199        unsafe { cosf(self) }
200    }
201    fn ttan(self) -> Self {
202        extern "C" {
203            fn tanf(x: f32) -> f32;
204        }
205        unsafe { tanf(self) }
206    }
207    fn tacos(self) -> Self {
208        extern "C" {
209            fn acosf(x: f32) -> f32;
210        }
211        unsafe { acosf(self) }
212    }
213}
214
215// FloatScalar implementation for f64
216// Note: Without std or libm, we need to provide our own implementations
217// or link to external math libraries
218impl FloatScalar for f64 {
219    fn infinity() -> Self {
220        core::f64::INFINITY
221    }
222    fn tsqrt(self) -> Self {
223        extern "C" {
224            fn sqrt(x: f64) -> f64;
225        }
226        unsafe { sqrt(self) }
227    }
228    fn tsin(self) -> Self {
229        extern "C" {
230            fn sin(x: f64) -> f64;
231        }
232        unsafe { sin(self) }
233    }
234    fn tcos(self) -> Self {
235        extern "C" {
236            fn cos(x: f64) -> f64;
237        }
238        unsafe { cos(self) }
239    }
240    fn ttan(self) -> Self {
241        extern "C" {
242            fn tan(x: f64) -> f64;
243        }
244        unsafe { tan(self) }
245    }
246    fn tacos(self) -> Self {
247        extern "C" {
248            fn acos(x: f64) -> f64;
249        }
250        unsafe { acos(self) }
251    }
252}
253
254#[cfg(test)]
255mod tests {
256    use super::*;
257    #[test]
258    pub fn test() {
259        let out = -1.0;
260        let f = out.tabs();
261        assert_eq!(f, 1.0);
262    }
263}