coord/
lib.rs

1//! `coord` is a simple, ergonomic vector mathematics crate for Rust designed for use in game development, physics engines and other programs that deal with general-purpose multi-variable mathematics
2//!
3//! # Features
4//!
5//! - Basic vector operations
6//! - Basic primitive operations
7//! - Basic mathematic operations upon vectors
8//! - Macros that make manipulating vectors simpler
9//! - Vector serialization
10//! - Hash support
11//!
12//! # Coming Soon
13//!
14//! - Bitwise vector operations
15//! - More mathematic functions
16//! - Conversion between primitive vectors of different types
17//!
18//! # Examples
19//!
20//! ```
21//! #[macro_use]
22//! extern crate coord;
23//! use coord::prelude::*;
24//!
25//! fn main() {
26//! 	// Coord supports 4 multi-variable vector types: Vec1, Vec2, Vec3 and Vec4
27//! 	let mut v = vec3!(1.0, 2.5, 3.0);
28//!
29//! 	// Coord supports common mathematical operations for both primitive and vector types
30//!     // The macros support multiple methods of construction including arrays and tuples
31//! 	v += vec3![1.0; 3] * 5.0;
32//! 	let _ = v * vec3!([10.0, 10.0, 10.0]);
33//!
34//! 	// Coord implements many common mathematic functions
35//! 	let _ = v.length();
36//! 	let _ = v.norm();
37//!
38//! 	// Coord supports debug and display printing of vectors
39//! 	println!("Debug => {:?}", v);
40//! 	println!("Display => {:?}", v);
41//!
42//! 	// Coord allows arbitrary vector component types
43//! 	let _ = vec2!(true, false); // Create a boolean vector
44//! }
45//! ```
46
47#![no_std]
48#![feature(alloc)]
49
50#![feature(euclidean_division)]
51
52extern crate num;
53#[cfg(feature = "serialize")]
54#[macro_use]
55extern crate serde_derive;
56#[cfg(feature = "serialize")]
57extern crate serde;
58
59pub mod vec1;
60pub mod vec2;
61pub mod vec3;
62pub mod vec4;
63pub mod math;
64#[macro_use]
65pub mod macros;
66
67use math::{VecNum, VecInt, VecUnsigned, VecSigned, VecFloat};
68
69#[cfg(feature = "serialize")]
70use serde::{Serialize, Deserialize};
71
72/// A trait implemented by all types that can exist within a vector
73pub trait VecItem: Copy + Clone + Default + PartialEq {}
74
75/// A trait implemented by all vector types
76pub trait Vector {
77    type Item: VecItem;
78}
79
80impl VecItem for bool {}
81
82impl VecItem for u8 {}
83impl VecItem for u16 {}
84impl VecItem for u32 {}
85impl VecItem for u64 {}
86impl VecItem for u128 {}
87
88impl VecItem for i8 {}
89impl VecItem for i16 {}
90impl VecItem for i32 {}
91impl VecItem for i64 {}
92impl VecItem for i128 {}
93
94impl VecItem for f32 {}
95impl VecItem for f64 {}
96
97#[cfg(not(feature = "large_defaults"))]
98pub mod defaults {
99    //! This module contains several type definitions that make working with `coord` simpler and faster
100    //!
101    //! *The default size for numerical types is 32 bits. To change this to 64 bits, enable the `large_defaults` feature*
102
103    use super::*;
104
105    /// A 1-dimensional boolean vector type
106    pub type Vec1b = vec1::Vec1<bool>;
107    /// A 2-dimensional boolean vector type
108    pub type Vec2b = vec2::Vec2<bool>;
109    /// A 3-dimensional boolean vector type
110    pub type Vec3b = vec3::Vec3<bool>;
111    /// A 4-dimensional boolean vector type
112    pub type Vec4b = vec4::Vec4<bool>;
113
114    /// A 1-dimensional unsigned integer vector type
115    pub type Vec1u = vec1::Vec1<u32>;
116    /// A 2-dimensional unsigned integer vector type
117    pub type Vec2u = vec2::Vec2<u32>;
118    /// A 3-dimensional unsigned integer vector type
119    pub type Vec3u = vec3::Vec3<u32>;
120    /// A 4-dimensional unsigned integer vector type
121    pub type Vec4u = vec4::Vec4<u32>;
122
123    /// A 1-dimensional signed integer vector type
124    pub type Vec1i = vec1::Vec1<i32>;
125    /// A 2-dimensional signed integer vector type
126    pub type Vec2i = vec2::Vec2<i32>;
127    /// A 3-dimensional signed integer vector type
128    pub type Vec3i = vec3::Vec3<i32>;
129    /// A 4-dimensional signed integer vector type
130    pub type Vec4i = vec4::Vec4<i32>;
131
132    /// A 1-dimensional floating point vector type
133    pub type Vec1f = vec1::Vec1<f32>;
134    /// A 2-dimensional floating point vector type
135    pub type Vec2f = vec2::Vec2<f32>;
136    /// A 3-dimensional floating point vector type
137    pub type Vec3f = vec3::Vec3<f32>;
138    /// A 4-dimensional floating point vector type
139    pub type Vec4f = vec4::Vec4<f32>;
140}
141
142#[cfg(feature = "large_defaults")]
143pub mod defaults {
144    //! This module contains several type definitions that make working with `coord` simpler and faster
145    //!
146    //! *The default size for numerical types is 64 bits. To change this to 32 bits, disable the `large_defaults` feature*
147
148    use super::*;
149
150    /// A 1-dimensional boolean vector type
151    pub type Vec1b = vec1::Vec1<bool>;
152    /// A 2-dimensional boolean vector type
153    pub type Vec2b = vec2::Vec2<bool>;
154    /// A 3-dimensional boolean vector type
155    pub type Vec3b = vec3::Vec3<bool>;
156    /// A 4-dimensional boolean vector type
157    pub type Vec4b = vec4::Vec4<bool>;
158
159    /// A 1-dimensional unsigned integer vector type
160    pub type Vec1u = vec1::Vec1<u64>;
161    /// A 2-dimensional unsigned integer vector type
162    pub type Vec2u = vec2::Vec2<u64>;
163    /// A 3-dimensional unsigned integer vector type
164    pub type Vec3u = vec3::Vec3<u64>;
165    /// A 4-dimensional unsigned integer vector type
166    pub type Vec4u = vec4::Vec4<u64>;
167
168    /// A 1-dimensional signed integer vector type
169    pub type Vec1i = vec1::Vec1<i64>;
170    /// A 2-dimensional signed integer vector type
171    pub type Vec2i = vec2::Vec2<i64>;
172    /// A 3-dimensional signed integer vector type
173    pub type Vec3i = vec3::Vec3<i64>;
174    /// A 4-dimensional signed integer vector type
175    pub type Vec4i = vec4::Vec4<i64>;
176
177    /// A 1-dimensional floating point vector type
178    pub type Vec1f = vec1::Vec1<f64>;
179    /// A 2-dimensional floating point vector type
180    pub type Vec2f = vec2::Vec2<f64>;
181    /// A 3-dimensional floating point vector type
182    pub type Vec3f = vec3::Vec3<f64>;
183    /// A 4-dimensional floating point vector type
184    pub type Vec4f = vec4::Vec4<f64>;
185}
186
187pub mod prelude {
188    //! This module contains a variety of commonly used types and functions.
189    //!
190    //! # Examples
191    //!
192    //! ```
193    //! #[macro_use] extern crate coord;
194    //! use coord::prelude::*;
195    //! ```
196
197    pub use super::math;
198
199    pub use super::Vector;
200
201    pub use super::vec1::Vec1;
202    pub use super::vec2::Vec2;
203    pub use super::vec3::Vec3;
204    pub use super::vec4::Vec4;
205
206    pub use math::VecNum;
207    pub use math::VecDot;
208    pub use math::VecInt;
209    pub use math::VecUnsigned;
210    pub use math::VecSigned;
211    pub use math::VecFloat;
212
213    pub use super::defaults::*;
214}
215
216#[cfg(test)]
217mod tests {
218    use super::prelude::*;
219
220    #[test]
221    fn basic_construction() {
222        let _ = Vec1::new(1u32);
223        let _ = Vec2::new(1u32, 2u32);
224        let _ = Vec3::new(1u32, 2u32, 3u32);
225        let _ = Vec4::new(1u32, 2u32, 3u32, 4u32);
226
227        let _ = Vec2::from((1u32, 2u32));
228        let _ = Vec3::from((1u32, 2u32, 3u32));
229        let _ = Vec4::from((1u32, 2u32, 3u32, 4u32));
230    }
231
232    #[test]
233    fn basic_operations() {
234        let _ = Vec1u::new(0)          + Vec1u::new(3);
235        let _ = Vec2u::new(0, 1)       + Vec2u::new(3, 2);
236        let _ = Vec3u::new(0, 1, 2)    + Vec3u::new(3, 2, 1);
237        let _ = Vec4u::new(0, 1, 2, 3) + Vec4u::new(3, 2, 1, 0);
238
239        let _ = Vec1u::new(3)          - Vec1u::new(3);
240        let _ = Vec2u::new(3, 2)       - Vec2u::new(3, 2);
241        let _ = Vec3u::new(3, 2, 1)    - Vec3u::new(3, 2, 1);
242        let _ = Vec4u::new(3, 2, 1, 0) - Vec4u::new(3, 2, 1, 0);
243
244        let _ = Vec1u::new(1)          * Vec1u::new(4);
245        let _ = Vec2u::new(1, 2)       * Vec2u::new(4, 3);
246        let _ = Vec3u::new(1, 2, 3)    * Vec3u::new(4, 3, 2);
247        let _ = Vec4u::new(1, 2, 3, 4) * Vec4u::new(4, 3, 2, 1);
248
249        let _ = Vec1u::new(4)          / Vec1u::new(5);
250        let _ = Vec2u::new(4, 3)       / Vec2u::new(5, 4);
251        let _ = Vec3u::new(4, 3, 2)    / Vec3u::new(5, 4, 3);
252        let _ = Vec4u::new(4, 3, 2, 1) / Vec4u::new(5, 4, 3, 2);
253    }
254
255    #[test]
256    fn primitive_operations() {
257        let _ = Vec1u::new(0)          + 1;
258        let _ = Vec2u::new(0, 1)       + 2;
259        let _ = Vec3u::new(0, 1, 2)    + 3;
260        let _ = Vec4u::new(0, 1, 2, 3) + 4;
261
262        let _ = Vec1u::new(6)          - 1;
263        let _ = Vec2u::new(6, 7)       - 2;
264        let _ = Vec3u::new(6, 7, 8)    - 3;
265        let _ = Vec4u::new(6, 7, 8, 9) - 4;
266
267        let _ = Vec1u::new(0)          * 1;
268        let _ = Vec2u::new(0, 1)       * 2;
269        let _ = Vec3u::new(0, 1, 2)    * 3;
270        let _ = Vec4u::new(0, 1, 2, 3) * 4;
271
272        let _ = Vec1u::new(0)          / 1;
273        let _ = Vec2u::new(0, 1)       / 2;
274        let _ = Vec3u::new(0, 1, 2)    / 3;
275        let _ = Vec4u::new(0, 1, 2, 3) / 4;
276    }
277
278    #[test]
279    fn basic_assignment() {
280        let mut v1 = Vec1u::new(0);
281        let mut v2 = Vec2u::new(0, 1);
282        let mut v3 = Vec3u::new(0, 1, 2);
283        let mut v4 = Vec4u::new(0, 1, 2, 3);
284
285        v1 += Vec1u::new(0);
286        v1 -= Vec1u::new(0);
287        v1 *= Vec1u::new(1);
288        v1 /= Vec1u::new(1);
289
290        v2 += Vec2u::new(0, 1);
291        v2 -= Vec2u::new(0, 1);
292        v2 *= Vec2u::new(1, 2);
293        v2 /= Vec2u::new(1, 2);
294
295        v3 += Vec3u::new(0, 1, 2);
296        v3 -= Vec3u::new(0, 1, 2);
297        v3 *= Vec3u::new(1, 2, 3);
298        v3 /= Vec3u::new(1, 2, 3);
299
300        v4 += Vec4u::new(0, 1, 2, 3);
301        v4 -= Vec4u::new(0, 1, 2, 3);
302        v4 *= Vec4u::new(1, 2, 3, 4);
303        v4 /= Vec4u::new(1, 2, 3, 4);
304    }
305
306    #[test]
307    fn primitive_assignment() {
308        let mut v1 = Vec1u::new(0);
309        let mut v2 = Vec2u::new(0, 1);
310        let mut v3 = Vec3u::new(0, 1, 2);
311        let mut v4 = Vec4u::new(0, 1, 2, 3);
312
313        v1 += 0;
314        v1 -= 0;
315        v1 *= 1;
316        v1 /= 1;
317
318        v2 += 0;
319        v2 -= 0;
320        v2 *= 1;
321        v2 /= 1;
322
323        v3 += 0;
324        v3 -= 0;
325        v3 *= 1;
326        v3 /= 1;
327
328        v4 += 0;
329        v4 -= 0;
330        v4 *= 1;
331        v4 /= 1;
332    }
333
334    fn pass_vec1u(_: Vec1u) {}
335    fn pass_vec2u(_: Vec2u) {}
336    fn pass_vec3u(_: Vec3u) {}
337    fn pass_vec4u(_: Vec4u) {}
338
339    #[test]
340    fn pass_to_func() {
341        pass_vec1u(vec1!(1));
342        pass_vec2u(vec2!(1, 2));
343        pass_vec3u(vec3!(1, 2, 3));
344        pass_vec4u(vec4!(1, 2, 3, 4));
345    }
346
347    #[test]
348    fn dot_product_vec2i(){
349        let zero = vec2!(0, 0);
350        let one = vec2!(1, 1);
351        let right = vec2!(1, 0);
352        let left = vec2!(-1, 0);
353        let up = vec2!(0, 1);
354
355        assert_eq!(zero.dot(zero), 0);
356        assert_eq!(one.dot(one), 2);
357        assert_eq!(right.dot(up), 0);
358        assert_eq!(right.dot(right), 1);
359        assert_eq!(right.dot(left), -1);
360    }
361
362    #[test]
363    fn dot_product_vec3f(){
364        let zero = vec3!(0.0, 0.0, 0.0);
365        let one = vec3!(1.0, 1.0, 1.0);
366        let right = vec3!(1.0, 0.0, 0.0);
367        let left = vec3!(-1.0, 0.0, 0.0);
368        let up = vec3!(0.0, 1.0, 0.0);
369
370        /// floating point equality
371        fn f_eq(a: f64, b: f64) -> bool {
372            (b - a).abs() < 0.01
373        }
374
375        assert!(f_eq(zero.dot(zero), 0.0));
376        assert!(f_eq(one.dot(one), 3.0));
377        assert!(f_eq(right.dot(up), 0.0));
378        assert!(f_eq(right.dot(right), 1.0));
379        assert!(f_eq(right.dot(left), -1.0));
380    }
381
382    fn length_of<V: VecFloat>(vec: V) -> V::Item where V::Item: math::Float {
383        vec.length()
384    }
385
386    #[test]
387    fn pass_generic() {
388        let v3 = vec3!(1.5, 2.0, 6.5);
389        let _ = v3.length();
390        let _ = length_of(v3);
391    }
392
393    #[test]
394    fn macros() {
395        let _v1_0 = vec1!(7);
396        let _v1_1 = vec1!([7]);
397        let _v1_2 = vec1![7; 1];
398
399        let _v2_0 = vec2!(7, 5);
400        let _v2_1 = vec2!([7, 5]);
401        let _v2_2 = vec2![7; 2];
402
403        let _v3_0 = vec3!(7, 5, 3);
404        let _v3_1 = vec3!([7, 5, 3]);
405        let _v3_2 = vec3![7; 3];
406
407        let _v4_0 = vec4!(7, 5, 3 ,1);
408        let _v4_1 = vec4!([7, 5, 3, 1]);
409        let _v4_2 = vec4![7; 4];
410    }
411
412    #[cfg(feature = "serialize")]
413    #[test]
414    fn serialize() {
415        // Nothing yet
416    }
417
418    #[cfg(feature = "serialize")]
419    #[test]
420    fn deserialize() {
421        // Nothing yet
422    }
423}