glm/
traits.rs

1//
2// GLSL Mathematics for Rust.
3//
4// Copyright (c) 2015 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 basenum::{ BaseNum, BaseInt, BaseFloat, SignedNum, ApproxEq };
25use std::ops::{ Add, Mul, Sub, Div, Rem, Not, BitAnd, BitOr, BitXor, Shl, Shr };
26use rand::Rand;
27use num::{ Float, One, Zero };
28
29// TODO: use associated types to reduce redundant type parameters.
30
31/// Generic numeric type.
32pub trait GenNum<E: BaseNum>
33: Copy
34+ Sized
35+ Clone
36+ One
37+ Zero
38+ Div<Self, Output = Self>
39+ Rem<Self, Output = Self>
40+ Add<E, Output = Self>
41+ Mul<E, Output = Self>
42+ Rand
43{
44    /// Constructs from a scalar number.
45    fn from_s(x: E) -> Self;
46
47    fn map<F>(self, f: F) -> Self where F: Fn(E) -> E;
48
49    fn zip<F>(self, y: Self, f: F) -> Self where F: Fn(E, E) -> E;
50
51    fn split<F>(self, f: F) -> (Self, Self) where F: Fn(E) -> (E, E);
52
53    fn map2<F>(self, y: Self, f: F) -> (Self, Self) where F: Fn(E, E) -> (E, E);
54}
55
56macro_rules! impl_GenNum_for_scalar(
57    ($t: ty) => {
58        impl GenNum<$t> for $t {
59            #[inline(always)]
60            fn from_s(x: $t) -> Self {
61                x
62            }
63            #[inline(always)]
64            fn map<F: Fn($t) -> $t>(self, f: F) -> $t {
65                f(self)
66            }
67            #[inline(always)]
68            fn zip<F: Fn($t, $t) -> $t>(self, y: $t, f: F) -> $t {
69                f(self, y)
70            }
71            #[inline(always)]
72            fn split<F: Fn($t) -> ($t, $t)>(self, f: F) -> ($t, $t) {
73                f(self)
74            }
75            #[inline(always)]
76            fn map2<F: Fn($t, $t) -> ($t, $t)>(self, y: $t, f: F) -> ($t, $t) {
77                f(self, y)
78            }
79        }
80    }
81);
82
83/// Generic interger type.
84pub trait GenInt<I: BaseInt>
85: GenNum<I>
86+ Eq
87+ Not<Output = Self>
88+ BitAnd<Output = Self>
89+ BitOr<Output = Self>
90+ BitXor<Output = Self>
91+ Shl<usize, Output = Self>
92+ Shr<usize, Output = Self>
93{}
94
95/// Generic signed integer type.
96///
97/// # Note
98///
99/// Only 32-bit integer is used in GLSL.
100pub trait GenIType: GenInt<i32> + SignedNum + Sub<i32, Output = Self> {}
101
102impl_GenNum_for_scalar! { i32 }
103impl GenInt<i32> for i32 {}
104impl GenIType for i32 {}
105
106/// Generic unsigned integer type.
107///
108/// # Note
109///
110/// Only 32-bit unsigned integer is used in GLSL.
111pub trait GenUType: GenInt<u32> {}
112
113impl_GenNum_for_scalar! { u32 }
114impl GenInt<u32> for u32 {}
115impl GenUType for u32 {}
116
117/// Generic float number type.
118pub trait GenFloat<F: BaseFloat>
119: GenNum<F>
120+ ApproxEq<BaseType = F>
121+ SignedNum
122+ Sub<F, Output = Self>
123{
124    /// Computes and returns `a * b + c`.
125    fn fma(&self, b: &Self, c: &Self) -> Self;
126}
127
128pub trait GenType: GenFloat<f32> {}
129pub trait GenDType: GenFloat<f64> {}
130
131macro_rules! impl_GenFloat_for_scalar(
132    ($t: ty, $gt: ty) => {
133        impl_GenNum_for_scalar! { $t }
134        impl GenFloat<$t> for $t {
135            fn fma(&self, b: &$t, c: &$t) -> $t {
136                Float::mul_add(*self, *b, *c)
137            }
138        }
139        impl $gt for $t {}
140    }
141);
142
143impl_GenFloat_for_scalar! { f32, GenType }
144impl_GenFloat_for_scalar! { f64, GenDType }
145
146/// Generic boolean type.
147pub trait GenBType: Eq {}
148
149impl GenBType for bool {}