Skip to main content

rill_core/math/
num.rs

1use core::fmt;
2use core::ops::*;
3
4/// Базовый числовой трейт для любых скалярных типов.
5///
6/// Включает арифметику, min/max/clamp, abs.
7/// Реализован для f32, f64 и всех целых типов (i8/i16/i32/i64, u8/u16/u32/u64).
8pub trait Scalar:
9    Copy
10    + Clone
11    + Send
12    + Sync
13    + 'static
14    + Default
15    + PartialOrd
16    + Add<Output = Self>
17    + Sub<Output = Self>
18    + Mul<Output = Self>
19    + Div<Output = Self>
20    + Rem<Output = Self>
21    + Neg<Output = Self>
22    + AddAssign
23    + SubAssign
24    + MulAssign
25    + DivAssign
26    + fmt::Debug
27{
28    const ZERO: Self;
29    const ONE: Self;
30    const MIN: Self;
31    const MAX: Self;
32
33    fn abs(self) -> Self;
34    fn min(self, other: Self) -> Self;
35    fn max(self, other: Self) -> Self;
36    fn clamp(self, min: Self, max: Self) -> Self;
37}
38
39/// Трансцендентные операции (sin, cos, sqrt, exp, ln).
40///
41/// Расширяет `Scalar` функциями, доступными только для типов
42/// с плавающей точкой (f32, f64).
43pub trait Transcendental: Scalar {
44    const PI: Self;
45
46    fn to_f32(self) -> f32;
47    fn from_f32(value: f32) -> Self;
48
49    fn to_f64(self) -> f64 {
50        self.to_f32() as f64
51    }
52
53    fn from_f64(value: f64) -> Self {
54        Self::from_f32(value as f32)
55    }
56
57    fn sqrt(self) -> Self;
58    fn exp(self) -> Self;
59    fn ln(self) -> Self;
60    fn sin(self) -> Self;
61    fn cos(self) -> Self;
62    fn tan(self) -> Self;
63}
64
65// -----------------------------------------------------------------------------
66// Scalar — f32
67// -----------------------------------------------------------------------------
68
69impl Scalar for f32 {
70    const ZERO: f32 = 0.0;
71    const ONE: f32 = 1.0;
72    const MIN: f32 = -1.0;
73    const MAX: f32 = 1.0;
74
75    #[inline(always)]
76    fn abs(self) -> f32 { self.abs() }
77
78    #[inline(always)]
79    fn min(self, other: f32) -> f32 { self.min(other) }
80
81    #[inline(always)]
82    fn max(self, other: f32) -> f32 { self.max(other) }
83
84    #[inline(always)]
85    fn clamp(self, min: f32, max: f32) -> f32 { self.clamp(min, max) }
86}
87
88impl Transcendental for f32 {
89    const PI: f32 = std::f32::consts::PI;
90
91    #[inline(always)]
92    fn to_f32(self) -> f32 { self }
93
94    #[inline(always)]
95    fn from_f32(value: f32) -> f32 { value }
96
97    #[inline(always)]
98    fn from_f64(value: f64) -> f32 { value as f32 }
99
100    #[inline(always)]
101    fn sqrt(self) -> f32 { self.sqrt() }
102
103    #[inline(always)]
104    fn exp(self) -> f32 { self.exp() }
105
106    #[inline(always)]
107    fn ln(self) -> f32 { self.ln() }
108
109    #[inline(always)]
110    fn sin(self) -> f32 { self.sin() }
111
112    #[inline(always)]
113    fn cos(self) -> f32 { self.cos() }
114
115    #[inline(always)]
116    fn tan(self) -> f32 { self.tan() }
117}
118
119// -----------------------------------------------------------------------------
120// Scalar + Transcendental — f64
121// -----------------------------------------------------------------------------
122
123impl Scalar for f64 {
124    const ZERO: f64 = 0.0;
125    const ONE: f64 = 1.0;
126    const MIN: f64 = -1.0;
127    const MAX: f64 = 1.0;
128
129    #[inline(always)]
130    fn abs(self) -> f64 { self.abs() }
131
132    #[inline(always)]
133    fn min(self, other: f64) -> f64 { self.min(other) }
134
135    #[inline(always)]
136    fn max(self, other: f64) -> f64 { self.max(other) }
137
138    #[inline(always)]
139    fn clamp(self, min: f64, max: f64) -> f64 { self.clamp(min, max) }
140}
141
142impl Transcendental for f64 {
143    const PI: f64 = std::f64::consts::PI;
144
145    #[inline(always)]
146    fn to_f32(self) -> f32 { self as f32 }
147
148    #[inline(always)]
149    fn from_f32(value: f32) -> f64 { value as f64 }
150
151    #[inline(always)]
152    fn from_f64(value: f64) -> f64 { value }
153
154    #[inline(always)]
155    fn sqrt(self) -> f64 { self.sqrt() }
156
157    #[inline(always)]
158    fn exp(self) -> f64 { self.exp() }
159
160    #[inline(always)]
161    fn ln(self) -> f64 { self.ln() }
162
163    #[inline(always)]
164    fn sin(self) -> f64 { self.sin() }
165
166    #[inline(always)]
167    fn cos(self) -> f64 { self.cos() }
168
169    #[inline(always)]
170    fn tan(self) -> f64 { self.tan() }
171}
172
173// -----------------------------------------------------------------------------
174// Scalar — целые типы
175// -----------------------------------------------------------------------------
176
177macro_rules! impl_scalar_int {
178    ($ty:ty, $zero:expr, $one:expr, $min:expr, $max:expr) => {
179        impl Scalar for $ty {
180            const ZERO: $ty = $zero;
181            const ONE: $ty = $one;
182            const MIN: $ty = $min;
183            const MAX: $ty = $max;
184
185            #[inline(always)]
186            fn abs(self) -> $ty { if self >= 0 { self } else { -self } }
187
188            #[inline(always)]
189            fn min(self, other: $ty) -> $ty { core::cmp::Ord::min(self, other) }
190
191            #[inline(always)]
192            fn max(self, other: $ty) -> $ty { core::cmp::Ord::max(self, other) }
193
194            #[inline(always)]
195            fn clamp(self, lo: $ty, hi: $ty) -> $ty { core::cmp::Ord::clamp(self, lo, hi) }
196        }
197    };
198}
199
200impl_scalar_int!(i8, 0, 1, i8::MIN, i8::MAX);
201impl_scalar_int!(i16, 0, 1, i16::MIN, i16::MAX);
202impl_scalar_int!(i32, 0, 1, i32::MIN, i32::MAX);
203impl_scalar_int!(i64, 0, 1, i64::MIN, i64::MAX);