glm/
traits.rs

1//
2// GLSL Mathematics for Rust.
3//
4// Copyright (c) 2015, 2025 The glm-rs authors.
5//
6// Permission is hereby granted, free of charge, to any person obtaining a copy
7// of this software and associated documentation files (the "Software"), to deal
8// in the Software without restriction, including without limitation the rights
9// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10// copies of the Software, and to permit persons to whom the Software is
11// furnished to do so, subject to the following conditions:
12//
13// The above copyright notice and this permission notice shall be included in
14// all copies or substantial portions of the Software.
15//
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22// THE SOFTWARE.
23
24use core::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Rem, Shl, Shr, Sub};
25
26use num_traits::{Float, One, Zero};
27
28use crate::basenum::{ApproxEq, BaseFloat, BaseInt, BaseNum, SignedNum};
29
30// TODO: use associated types to reduce redundant type parameters.
31
32/// Generic numeric type.
33pub trait GenNum<E: BaseNum>:
34    Copy
35    + Sized
36    + Clone
37    + One
38    + Zero
39    + Div<Self, Output = Self>
40    + Rem<Self, Output = Self>
41    + Add<E, Output = Self>
42    + Mul<E, Output = Self>
43{
44    /// Constructs from a scalar number.
45    fn from_s(x: E) -> Self;
46
47    fn map<F>(self, f: F) -> Self
48    where
49        F: Fn(E) -> E;
50
51    fn zip<F>(self, y: Self, f: F) -> Self
52    where
53        F: Fn(E, E) -> E;
54
55    fn split<F>(self, f: F) -> (Self, Self)
56    where
57        F: Fn(E) -> (E, E);
58
59    fn map2<F>(self, y: Self, f: F) -> (Self, Self)
60    where
61        F: Fn(E, E) -> (E, E);
62}
63
64macro_rules! impl_GenNum_for_scalar(
65    ($t: ty) => {
66        impl GenNum<$t> for $t {
67            #[inline(always)]
68            fn from_s(x: $t) -> Self {
69                x
70            }
71            #[inline(always)]
72            fn map<F: Fn($t) -> $t>(self, f: F) -> $t {
73                f(self)
74            }
75            #[inline(always)]
76            fn zip<F: Fn($t, $t) -> $t>(self, y: $t, f: F) -> $t {
77                f(self, y)
78            }
79            #[inline(always)]
80            fn split<F: Fn($t) -> ($t, $t)>(self, f: F) -> ($t, $t) {
81                f(self)
82            }
83            #[inline(always)]
84            fn map2<F: Fn($t, $t) -> ($t, $t)>(self, y: $t, f: F) -> ($t, $t) {
85                f(self, y)
86            }
87        }
88    }
89);
90
91/// Generic interger type.
92pub trait GenInt<I: BaseInt>:
93    GenNum<I>
94    + Eq
95    + Not<Output = Self>
96    + BitAnd<Output = Self>
97    + BitOr<Output = Self>
98    + BitXor<Output = Self>
99    + Shl<usize, Output = Self>
100    + Shr<usize, Output = Self>
101{
102}
103
104/// Generic signed integer type.
105///
106/// # Note
107///
108/// Only 32-bit integer is used in GLSL.
109pub trait GenIType: GenInt<i32> + SignedNum + Sub<i32, Output = Self> {}
110
111impl_GenNum_for_scalar! { i32 }
112impl GenInt<i32> for i32 {}
113impl GenIType for i32 {}
114
115/// Generic unsigned integer type.
116///
117/// # Note
118///
119/// Only 32-bit unsigned integer is used in GLSL.
120pub trait GenUType: GenInt<u32> {}
121
122impl_GenNum_for_scalar! { u32 }
123impl GenInt<u32> for u32 {}
124impl GenUType for u32 {}
125
126/// Generic float number type.
127pub trait GenFloat<F: BaseFloat>:
128    GenNum<F> + ApproxEq<BaseType = F> + SignedNum + Sub<F, Output = Self>
129{
130    /// Computes and returns `a * b + c`.
131    fn fma(&self, b: &Self, c: &Self) -> Self;
132}
133
134pub trait GenType: GenFloat<f32> {}
135pub trait GenDType: GenFloat<f64> {}
136
137macro_rules! impl_GenFloat_for_scalar(
138    ($t: ty, $gt: path) => {
139        impl_GenNum_for_scalar! { $t }
140        impl GenFloat<$t> for $t {
141            fn fma(&self, b: &$t, c: &$t) -> $t {
142                Float::mul_add(*self, *b, *c)
143            }
144        }
145        impl $gt for $t {}
146    }
147);
148
149impl_GenFloat_for_scalar! { f32, GenType }
150impl_GenFloat_for_scalar! { f64, GenDType }
151
152/// Generic boolean type.
153pub trait GenBType: Eq {}
154
155impl GenBType for bool {}