1use 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}