rs_math3d/
scalar.rs

1// Copyright 2020-Present (c) Raja Lehtihet & Wael El Oraiby
2//
3// Redistribution and use in source and binary forms, with or without
4// modification, are permitted provided that the following conditions are met:
5//
6// 1. Redistributions of source code must retain the above copyright notice,
7// this list of conditions and the following disclaimer.
8//
9// 2. Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12//
13// 3. Neither the name of the copyright holder nor the names of its contributors
14// may be used to endorse or promote products derived from this software without
15// specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27// POSSIBILITY OF SUCH DAMAGE.
28use core::cmp::PartialOrd;
29use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
30
31extern crate std;
32
33use std::{f32, f64};
34
35pub trait Scalar<Rhs = Self, Output = Self>:
36    Add<Rhs, Output = Output>
37    + Sub<Rhs, Output = Output>
38    + Mul<Rhs, Output = Output>
39    + Div<Rhs, Output = Output>
40    + Rem<Rhs, Output = Output>
41    + DivAssign<Rhs>
42    + MulAssign<Rhs>
43    + Neg<Output = Output>
44    + AddAssign<Rhs>
45    + SubAssign<Rhs>
46    + PartialOrd
47    + Clone
48    + Copy
49{
50    fn zero() -> Self;
51    fn epsilon() -> Self;
52    fn one() -> Self;
53    fn two() -> Self;
54    fn half() -> Self;
55    fn quarter() -> Self;
56    fn l8192() -> Self;
57    fn min(l: Self, r: Self) -> Self;
58    fn max(l: Self, r: Self) -> Self;
59    fn squared(l: Self) -> Self;
60    fn tabs(self) -> Self;
61}
62
63pub trait FloatScalar<Rhs = Self, Output = Self>: Scalar<Rhs, Output> {
64    fn infinity() -> Self;
65    fn tsin(self) -> Self;
66    fn tcos(self) -> Self;
67    fn ttan(self) -> Self;
68    fn tacos(self) -> Self;
69    fn tsqrt(self) -> Self;
70}
71
72trait Epsilon {
73    fn epsilon() -> Self;
74}
75
76impl Epsilon for i32 {
77    fn epsilon() -> Self {
78        0
79    }
80}
81
82impl Epsilon for i64 {
83    fn epsilon() -> Self {
84        0
85    }
86}
87
88impl Epsilon for f32 {
89    fn epsilon() -> Self {
90        1.0 / (1024.0 * 1024.0)
91    }
92}
93
94impl Epsilon for f64 {
95    fn epsilon() -> Self {
96        1.0 / (1024.0 * 1024.0 * 1024.0 * 1024.0)
97    }
98}
99
100macro_rules! impl_scalar {
101    ($scalar:ident, $float:ident) => {
102        impl Scalar for $scalar {
103            fn epsilon() -> $scalar {
104                <$scalar as Epsilon>::epsilon()
105            }
106            fn zero() -> $scalar {
107                0 as $scalar
108            }
109            fn one() -> $scalar {
110                1 as $scalar
111            }
112            fn two() -> $scalar {
113                2 as $scalar
114            }
115            fn half() -> $scalar {
116                0.5 as $scalar
117            }
118            fn quarter() -> $scalar {
119                0.25 as $scalar
120            }
121            fn l8192() -> $scalar {
122                8192 as $scalar
123            }
124            fn min(l: Self, r: Self) -> Self {
125                if l < r {
126                    l
127                } else {
128                    r
129                }
130            }
131            fn max(l: Self, r: Self) -> Self {
132                if l > r {
133                    l
134                } else {
135                    r
136                }
137            }
138            fn squared(l: Self) -> Self {
139                l * l
140            }
141            fn tabs(self) -> $scalar {
142                self.abs()
143            }
144        }
145    };
146}
147
148macro_rules! impl_float_scalar {
149    ($scalar:ident) => {
150        impl FloatScalar for $scalar {
151            fn infinity() -> $scalar {
152                core::$scalar::INFINITY
153            }
154            fn tsqrt(self) -> $scalar {
155                self.sqrt() as $scalar
156            }
157            fn tsin(self) -> $scalar {
158                self.sin() as $scalar
159            }
160            fn tcos(self) -> $scalar {
161                self.cos() as $scalar
162            }
163            fn ttan(self) -> $scalar {
164                self.tan() as $scalar
165            }
166            fn tacos(self) -> $scalar {
167                self.acos() as $scalar
168            }
169        }
170    };
171}
172
173impl_scalar!(i32, f32);
174impl_scalar!(i64, f64);
175impl_scalar!(f32, f32);
176impl_scalar!(f64, f64);
177
178impl_float_scalar!(f32);
179impl_float_scalar!(f64);
180
181
182#[cfg(test)]
183mod tests {
184    use super::*;
185    #[test]
186    pub fn test() {
187        let out = -1.0;
188        let f = out.tabs();
189        assert_eq!(f, 1.0);
190    }
191}