├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── lib.rs ├── macros.rs ├── math.rs ├── vec1.rs ├── vec2.rs ├── vec3.rs └── vec4.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - nightly 4 | script: 5 | - cargo test -v 6 | - cargo test -v --all-features 7 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "coord" 3 | version = "0.11.1" 4 | authors = ["Joshua Barretto "] 5 | description = "A simple, ergonomic vector mathematics crate" 6 | license = "MIT" 7 | readme = "README.md" 8 | maintenance = { status = "experimental" } 9 | homepage = "https://github.com/zesterer/coord-rs" 10 | repository = "https://github.com/zesterer/coord-rs" 11 | keywords = ["simple", "vector", "mathematics", "no_std"] 12 | 13 | [dependencies] 14 | num = "0.1" 15 | 16 | serde = { version = "1.0", optional = true } 17 | serde_derive = { version = "1.0", optional = true } 18 | 19 | [features] 20 | large_defaults = [] 21 | serialize = ["serde", "serde_derive"] 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2018 Joshua Barretto 3 | 4 | Permission is hereby granted, free of charge, to any 5 | person obtaining a copy of this software and associated 6 | documentation files (the "Software"), to deal in the 7 | Software without restriction, including without 8 | limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software 11 | is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice 15 | shall be included in all copies or substantial portions 16 | of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 19 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 20 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 21 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 22 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 25 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | DEALINGS IN THE SOFTWARE. 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `coord` is deprecated. I recommend using [`vek`](https://github.com/yoanlcq/vek), a project with near-identical aims instead. 2 | 3 | # Coord Coord 4 | 5 | [![Build Status][ci-badge]][ci] [![Crates.io][cr-badge]][cr] ![Downloads][dl-badge] [![Docs][doc-badge]][doc] 6 | 7 | [ci-badge]: https://travis-ci.org/zesterer/coord-rs.svg?branch=master 8 | [ci]: https://travis-ci.org/zesterer/coord-rs 9 | [cr-badge]: https://img.shields.io/crates/v/coord.svg 10 | [cr]: https://crates.io/crates/coord 11 | [dl-badge]: https://img.shields.io/crates/d/coord.svg 12 | [doc-badge]: https://docs.rs/coord/badge.svg 13 | [doc]: https://docs.rs/coord 14 | 15 | ## Description 16 | 17 | 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. 18 | 19 | **Coord is now `no_std` compatible!** 20 | 21 | ## Example 22 | 23 | ```rust 24 | #[macro_use] 25 | extern crate coord; 26 | use coord::prelude::*; 27 | 28 | fn main() { 29 | // Coord supports 4 multi-variable vector types: Vec1, Vec2, Vec3 and Vec4 30 | let mut v = vec3!(1.0, 2.5, 3.0); 31 | 32 | // Coord supports common mathematical operations for both primitive and vector types 33 | v += vec3![1.0; 3] * 5.0; 34 | let _ = v * vec3!([10.0, 10.0, 10.0]); 35 | 36 | // Coord implements many common mathematic functions 37 | let _ = v.length(); 38 | let _ = v.norm(); 39 | 40 | // Coord supports debug and display printing of vectors 41 | println!("Debug => {:?}", v); 42 | println!("Display => {}", v); 43 | 44 | // Coord allows arbitrary vector component types 45 | let _ = vec2!(true, false); // Create a boolean vector 46 | } 47 | ``` 48 | 49 | **For more examples, visit [https://docs.rs/coord](https://docs.rs/coord)** 50 | 51 | ## Features 52 | 53 | - [x] Generic `Vec1`, `Vec2`, `Vec3` and `Vec4` types 54 | - [x] Utility macros to make vector manipulation simpler 55 | - [x] `VecXu`, `VecXi` and `VecXf` default type definitions 56 | - [x] Basic mathematic operations (`Add`, `Sub`, `Mul`, `Div`) 57 | - [x] Mathematic functions (i.e: `.length()`, `.norm()`, etc.) 58 | - [x] Serialization support with the `serialize` feature 59 | - [x] 64 bit default type support with the `large_defaults` feature 60 | - [x] Hash support 61 | - [x] `.map()` method performing arbitrary element-wise vector transformation 62 | - [x] `.convert_to()` method allowing element-wise vector conversion 63 | - [x] `.div_floor()` method allowing floor-like vector division 64 | 65 | ## Coming Soon 66 | 67 | - [ ] Bitwise operations 68 | - [ ] More mathematic functions 69 | - [ ] Modulo operator for integer vector types 70 | 71 | ## Using Coord 72 | 73 | To use Coord in your Rust project, add the following line beneath the `[dependencies]` section in your `Cargo.toml` file. 74 | 75 | ``` 76 | coord = "0.11.0" 77 | ``` 78 | 79 | If you want to enable serialization or 64-bit defaults, you should specify the dependency like the following line instead. 80 | 81 | ``` 82 | [dependencies.coord] 83 | version = "0.7.0" 84 | features = ["serialize", "large_defaults"] 85 | ``` 86 | 87 | ## FAQ 88 | 89 | ### Why does Coord exist? 90 | 91 | Coord came about as a result of a general dissatisfaction with existing vector mathematics libraries during development of the [Veloren Project](https://github.com/veloren/game). Existing solutions were either too complicated, awkward to use, or required too many dependencies. 92 | 93 | ### Does Coord aim to eventually implement feature X? 94 | 95 | Coord does not aim to be a fully-blown N-dimensional mathematics library. It aims to implement a small yet elegant set of features that make it suitable for applications where simple multi-variable mathematics is required. 96 | 97 | If you think feature X falls within that scope, and is not yet on the project todo list, you can open an issue on GitHub and I'll consider implementing it. 98 | 99 | ### Why does Coord choose 32 bit values for its default types? 100 | 101 | Coord defines a set of 'default' types within the `defaults` module. They are included within the `prelude` module too. These default types, such as `Vec2f`, `Vec3u`, `Vec4b`, etc. exist to make writing code with Coord faster. It is still possible to program without them like `Vec2`, `Vec3`, `Vec4`, etc. Coord chooses 32-bit types by default because it is my belief that these are more useful when developing for games and physics engines, which require fast calculations. Additionally, 32 bit floating point types means that Coord is compatible with OpenGL. 102 | 103 | ### Why does Coord not have a general-purpose `vec!` macro? 104 | 105 | Such a macro would conflict with the `vec!` macro within Rust's standard library. 106 | 107 | ### Why does Coord not rely on the standard library? 108 | 109 | It doesn't need to. Why limit the use cases of the library by requiring `std`? 110 | 111 | ### Bug! Bug! I've found a bug! 112 | 113 | Open an issue on Github and I'll fix it as soon as possible. 114 | 115 | [You can open an issue here](https://github.com/zesterer/coord-rs/issues/new) 116 | 117 | ## License 118 | 119 | Coord is open source software, licensed under the MIT license (See 'LICENSE' or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT)) 120 | -------------------------------------------------------------------------------- /src/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 | 52 | extern crate num; 53 | #[cfg(feature = "serialize")] 54 | #[macro_use] 55 | extern crate serde_derive; 56 | #[cfg(feature = "serialize")] 57 | extern crate serde; 58 | 59 | pub mod vec1; 60 | pub mod vec2; 61 | pub mod vec3; 62 | pub mod vec4; 63 | pub mod math; 64 | #[macro_use] 65 | pub mod macros; 66 | 67 | use math::{VecNum, VecInt, VecUnsigned, VecSigned, VecFloat}; 68 | 69 | #[cfg(feature = "serialize")] 70 | use serde::{Serialize, Deserialize}; 71 | 72 | /// A trait implemented by all types that can exist within a vector 73 | pub trait VecItem: Copy + Clone + Default + PartialEq {} 74 | 75 | /// A trait implemented by all vector types 76 | pub trait Vector { 77 | type Item: VecItem; 78 | } 79 | 80 | impl VecItem for bool {} 81 | 82 | impl VecItem for u8 {} 83 | impl VecItem for u16 {} 84 | impl VecItem for u32 {} 85 | impl VecItem for u64 {} 86 | impl VecItem for u128 {} 87 | 88 | impl VecItem for i8 {} 89 | impl VecItem for i16 {} 90 | impl VecItem for i32 {} 91 | impl VecItem for i64 {} 92 | impl VecItem for i128 {} 93 | 94 | impl VecItem for f32 {} 95 | impl VecItem for f64 {} 96 | 97 | #[cfg(not(feature = "large_defaults"))] 98 | pub 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; 107 | /// A 2-dimensional boolean vector type 108 | pub type Vec2b = vec2::Vec2; 109 | /// A 3-dimensional boolean vector type 110 | pub type Vec3b = vec3::Vec3; 111 | /// A 4-dimensional boolean vector type 112 | pub type Vec4b = vec4::Vec4; 113 | 114 | /// A 1-dimensional unsigned integer vector type 115 | pub type Vec1u = vec1::Vec1; 116 | /// A 2-dimensional unsigned integer vector type 117 | pub type Vec2u = vec2::Vec2; 118 | /// A 3-dimensional unsigned integer vector type 119 | pub type Vec3u = vec3::Vec3; 120 | /// A 4-dimensional unsigned integer vector type 121 | pub type Vec4u = vec4::Vec4; 122 | 123 | /// A 1-dimensional signed integer vector type 124 | pub type Vec1i = vec1::Vec1; 125 | /// A 2-dimensional signed integer vector type 126 | pub type Vec2i = vec2::Vec2; 127 | /// A 3-dimensional signed integer vector type 128 | pub type Vec3i = vec3::Vec3; 129 | /// A 4-dimensional signed integer vector type 130 | pub type Vec4i = vec4::Vec4; 131 | 132 | /// A 1-dimensional floating point vector type 133 | pub type Vec1f = vec1::Vec1; 134 | /// A 2-dimensional floating point vector type 135 | pub type Vec2f = vec2::Vec2; 136 | /// A 3-dimensional floating point vector type 137 | pub type Vec3f = vec3::Vec3; 138 | /// A 4-dimensional floating point vector type 139 | pub type Vec4f = vec4::Vec4; 140 | } 141 | 142 | #[cfg(feature = "large_defaults")] 143 | pub 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; 152 | /// A 2-dimensional boolean vector type 153 | pub type Vec2b = vec2::Vec2; 154 | /// A 3-dimensional boolean vector type 155 | pub type Vec3b = vec3::Vec3; 156 | /// A 4-dimensional boolean vector type 157 | pub type Vec4b = vec4::Vec4; 158 | 159 | /// A 1-dimensional unsigned integer vector type 160 | pub type Vec1u = vec1::Vec1; 161 | /// A 2-dimensional unsigned integer vector type 162 | pub type Vec2u = vec2::Vec2; 163 | /// A 3-dimensional unsigned integer vector type 164 | pub type Vec3u = vec3::Vec3; 165 | /// A 4-dimensional unsigned integer vector type 166 | pub type Vec4u = vec4::Vec4; 167 | 168 | /// A 1-dimensional signed integer vector type 169 | pub type Vec1i = vec1::Vec1; 170 | /// A 2-dimensional signed integer vector type 171 | pub type Vec2i = vec2::Vec2; 172 | /// A 3-dimensional signed integer vector type 173 | pub type Vec3i = vec3::Vec3; 174 | /// A 4-dimensional signed integer vector type 175 | pub type Vec4i = vec4::Vec4; 176 | 177 | /// A 1-dimensional floating point vector type 178 | pub type Vec1f = vec1::Vec1; 179 | /// A 2-dimensional floating point vector type 180 | pub type Vec2f = vec2::Vec2; 181 | /// A 3-dimensional floating point vector type 182 | pub type Vec3f = vec3::Vec3; 183 | /// A 4-dimensional floating point vector type 184 | pub type Vec4f = vec4::Vec4; 185 | } 186 | 187 | pub 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)] 217 | mod 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(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 | } 424 | -------------------------------------------------------------------------------- /src/macros.rs: -------------------------------------------------------------------------------- 1 | //! Macro definitions 2 | 3 | /// Neatly construct a `Vec1` from arbitrary components 4 | /// 5 | /// # Examples 6 | /// 7 | /// ``` 8 | /// #[macro_use] extern crate coord; 9 | /// use coord::prelude::*; 10 | /// 11 | /// let my_vec = vec1!(7); // Standard instantiation 12 | /// let my_vec = vec1!((12)); // Tuple instantiation 13 | /// let my_vec = vec1!([3.2]); // Array slice instantiation 14 | /// let my_vec = vec1!([true; 1]); // Array copy instantiation 15 | /// ``` 16 | #[macro_export] 17 | #[allow(unused_macros)] 18 | macro_rules! vec1 { 19 | ($arr:expr) => ( 20 | Vec1::from($arr) 21 | ); 22 | 23 | [$arr:expr; 1] => ( 24 | Vec1::from([$arr; 1]) 25 | ); 26 | 27 | ($x:expr) => ( 28 | Vec1::new($x) 29 | ); 30 | } 31 | 32 | /// Neatly construct a `Vec2` from arbitrary components 33 | /// 34 | /// # Examples 35 | /// 36 | /// ``` 37 | /// #[macro_use] extern crate coord; 38 | /// use coord::prelude::*; 39 | /// 40 | /// let my_vec = vec2!(7, 9); // Standard instantiation 41 | /// let my_vec = vec2!((12, -4)); // Tuple instantiation 42 | /// let my_vec = vec2!([3.2, 8.9]); // Array slice instantiation 43 | /// let my_vec = vec2!([true; 2]); // Array copy instantiation 44 | /// ``` 45 | #[macro_export] 46 | #[allow(unused_macros)] 47 | macro_rules! vec2 { 48 | ($arr:expr) => ( 49 | Vec2::from($arr) 50 | ); 51 | 52 | [$arr:expr; 2] => ( 53 | Vec2::from([$arr; 2]) 54 | ); 55 | 56 | ($x:expr, $y:expr) => ( 57 | Vec2::new($x, $y) 58 | ); 59 | } 60 | 61 | /// Neatly construct a `Vec3` from arbitrary components 62 | /// 63 | /// # Examples 64 | /// 65 | /// ``` 66 | /// #[macro_use] extern crate coord; 67 | /// use coord::prelude::*; 68 | /// 69 | /// let my_vec = vec3!(7, 9, 2); // Standard instantiation 70 | /// let my_vec = vec3!((12, -4, 0)); // Tuple instantiation 71 | /// let my_vec = vec3!([3.2, 8.9, 7.3]); // Array slice instantiation 72 | /// let my_vec = vec3!([true; 3]); // Array copy instantiation 73 | /// ``` 74 | #[macro_export] 75 | #[allow(unused_macros)] 76 | macro_rules! vec3 { 77 | ($arr:expr) => ( 78 | Vec3::from($arr) 79 | ); 80 | 81 | [$arr:expr; 3] => ( 82 | Vec3::from([$arr; 3]) 83 | ); 84 | 85 | ($x:expr, $y:expr, $z:expr) => ( 86 | Vec3::new($x, $y, $z) 87 | ); 88 | } 89 | 90 | /// Neatly construct a `Vec4` from arbitrary components 91 | /// 92 | /// # Examples 93 | /// 94 | /// ``` 95 | /// #[macro_use] extern crate coord; 96 | /// use coord::prelude::*; 97 | /// 98 | /// let my_vec = vec4!(7, 9, 2, -5); // Standard instantiation 99 | /// let my_vec = vec4!((12, -4, 0, 9)); // Tuple instantiation 100 | /// let my_vec = vec4!([3.2, 8.9, 7.3, -2.0]); // Array slice instantiation 101 | /// let my_vec = vec4!([true; 4]); // Array copy instantiation 102 | /// ``` 103 | #[macro_export] 104 | #[allow(unused_macros)] 105 | macro_rules! vec4 { 106 | ($arr:expr) => ( 107 | Vec4::from($arr) 108 | ); 109 | 110 | [$arr:expr; 4] => ( 111 | Vec4::from([$arr; 4]) 112 | ); 113 | 114 | ($x:expr, $y:expr, $z:expr, $w:expr) => ( 115 | Vec4::new($x, $y, $z, $w) 116 | ); 117 | } 118 | -------------------------------------------------------------------------------- /src/math.rs: -------------------------------------------------------------------------------- 1 | //! Mathematic functions and traits 2 | 3 | pub use num::{Num, Integer, Unsigned, Signed, Float}; 4 | use super::{Vector, VecItem}; 5 | 6 | /// A trait for vectors containing numerical types 7 | pub trait VecNum: Vector where Self::Item: VecItem + Num { 8 | /// Calculates the sum of all components of the vector 9 | fn sum(&self) -> Self::Item; 10 | 11 | /// Calculates the product of all components of the vector 12 | fn product(&self) -> Self::Item; 13 | 14 | } 15 | 16 | 17 | 18 | /// Trait for vectors that support a dot-product 19 | pub trait VecDot: Vector where Self::Item: VecItem + Num { 20 | /// calculates the dot product of the two vectors 21 | fn dot(&self, other: Self) -> Self::Item; 22 | } 23 | 24 | /// Default implement the dot product for all numeric vectors 25 | impl VecDot for V where V: Sized + Copy + VecNum + ::core::ops::Mul, V::Item: VecItem + Num { 26 | fn dot(&self, other: Self) -> Self::Item { 27 | (*self * other).sum() 28 | } 29 | } 30 | 31 | 32 | 33 | /// A trait for vectors containing integer types 34 | pub trait VecInt: Vector where Self::Item: VecItem + Integer { 35 | /// Performs a Eucledian division (i.e: rounds towards negative infinity) operation upon the vector 36 | fn div_euc(&self, other: Self) -> Self; 37 | } 38 | 39 | /// A trait for vectors containing unsigned numerical types 40 | pub trait VecUnsigned: Vector where Self::Item: VecItem + Unsigned {} 41 | 42 | /// A trait for vectors containing signed numerical types 43 | pub trait VecSigned: Vector where Self::Item: VecItem + Signed { 44 | /// Calculates the snake length (also known as 'manhattan distance') of the vector 45 | /// 46 | /// *For unsigned vectors, this is identical to the `.sum()` of the vector* 47 | fn snake_length(&self) -> Self::Item; 48 | } 49 | 50 | /// A trait for vectors containing floating point numerical types 51 | pub trait VecFloat: Vector where Self::Item: VecItem + Float { 52 | /// Calculates the magnitude of the vector 53 | fn length(&self) -> Self::Item; 54 | /// Calculates the normalized form of the vector *(i.e: a vector with identical direction but a magnitude of 1)* 55 | fn norm(&self) -> Self; 56 | 57 | /// Rounds each element of the vector down to the nearest whole number 58 | fn floor(&self) -> Self; 59 | 60 | /// Rounds each element of the vector up to the nearest whole number 61 | fn ceil(&self) -> Self; 62 | 63 | /// Rounds each element of the vector to the nearest whole number 64 | fn round(&self) -> Self; 65 | } 66 | -------------------------------------------------------------------------------- /src/vec1.rs: -------------------------------------------------------------------------------- 1 | //! Functionality pertaining to `Vec1` 2 | 3 | use core::ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; 4 | use core::fmt; 5 | 6 | #[allow(unused_imports)] 7 | use num::{Num, Integer, Unsigned, Signed, Float}; 8 | 9 | #[allow(unused_imports)] 10 | use super::{Vector, VecItem, VecNum, VecInt, VecUnsigned, VecSigned, VecFloat}; 11 | 12 | #[cfg(feature = "serialize")] 13 | #[derive(Copy, Clone, Default, Hash, Eq, PartialEq, Serialize, Deserialize)] 14 | pub struct Vec1 { 15 | pub x: T, 16 | } 17 | 18 | #[cfg(not(feature = "serialize"))] 19 | #[derive(Copy, Clone, Default, Hash, Eq, PartialEq)] 20 | pub struct Vec1 { 21 | pub x: T, 22 | } 23 | 24 | impl Vec1 { 25 | /// Creates a new Vec1 from a single component 26 | pub fn new(x: T) -> Self { Self { x, ..Default::default() } } 27 | 28 | /// Returns the elements of the vector as an array 29 | pub fn elements(&self) -> [T; 1] { [self.x] } 30 | 31 | /// Apply an operation to all elements of this vector, returning the result 32 | pub fn map U>(&self, f: F) -> Vec1 { 33 | Vec1 { 34 | x: f(self.x), 35 | } 36 | } 37 | 38 | pub fn convert_to>(&self) -> Vec1 { 39 | Vec1 { 40 | x: U::from(self.x), 41 | } 42 | } 43 | } 44 | 45 | impl Vector for Vec1 { 46 | type Item = T; 47 | } 48 | 49 | // Debug and Display traits 50 | 51 | impl fmt::Debug for Vec1 { 52 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 53 | write!(f, "(x: {:?})", self.x) 54 | } 55 | } 56 | 57 | impl fmt::Display for Vec1 { 58 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 59 | write!(f, "({})", self.x) 60 | } 61 | } 62 | 63 | // From traits 64 | 65 | impl From for Vec1 { 66 | fn from(item: T) -> Self { Self { x: item, ..Default::default() } } 67 | } 68 | 69 | impl From<[T; 1]> for Vec1 { 70 | fn from(arr: [T; 1]) -> Self { Self { x: arr[0], ..Default::default() } } 71 | } 72 | 73 | // Op traits 74 | 75 | impl Add for Vec1 where T: VecItem + Add, T::Output: VecItem + Add { 76 | type Output = Vec1; 77 | fn add(self, other: Self) -> Vec1 { 78 | Vec1 { 79 | x: self.x + other.x, 80 | ..Default::default() 81 | } 82 | } 83 | } 84 | 85 | impl Sub for Vec1 where T: VecItem + Sub, T::Output: VecItem + Sub { 86 | type Output = Vec1; 87 | fn sub(self, other: Self) -> Vec1 { 88 | Vec1 { 89 | x: self.x - other.x, 90 | ..Default::default() 91 | } 92 | } 93 | } 94 | 95 | impl Mul for Vec1 where T: VecItem + Mul, T::Output: VecItem + Mul { 96 | type Output = Vec1; 97 | fn mul(self, other: Self) -> Vec1 { 98 | Vec1 { 99 | x: self.x * other.x, 100 | ..Default::default() 101 | } 102 | } 103 | } 104 | 105 | impl Div for Vec1 where T: VecItem + Div, T::Output: VecItem + Div { 106 | type Output = Vec1; 107 | fn div(self, other: Self) -> Vec1 { 108 | Vec1 { 109 | x: self.x / other.x, 110 | ..Default::default() 111 | } 112 | } 113 | } 114 | 115 | // Op primitive traits 116 | 117 | impl Add for Vec1 where T: VecItem + Add, T::Output: VecItem + Add { 118 | type Output = Vec1; 119 | fn add(self, other: T) -> Vec1 { 120 | Vec1 { 121 | x: self.x + other, 122 | ..Default::default() 123 | } 124 | } 125 | } 126 | 127 | impl Sub for Vec1 where T: VecItem + Sub, T::Output: VecItem + Sub { 128 | type Output = Vec1; 129 | fn sub(self, other: T) -> Vec1 { 130 | Vec1 { 131 | x: self.x - other, 132 | ..Default::default() 133 | } 134 | } 135 | } 136 | 137 | impl Mul for Vec1 where T: VecItem + Mul, T::Output: VecItem + Mul { 138 | type Output = Vec1; 139 | fn mul(self, other: T) -> Vec1 { 140 | Vec1 { 141 | x: self.x * other, 142 | ..Default::default() 143 | } 144 | } 145 | } 146 | 147 | impl Div for Vec1 where T: VecItem + Div, T::Output: VecItem + Div { 148 | type Output = Vec1; 149 | fn div(self, other: T) -> Vec1 { 150 | Vec1 { 151 | x: self.x / other, 152 | ..Default::default() 153 | } 154 | } 155 | } 156 | 157 | // Assign operators 158 | 159 | impl AddAssign for Vec1 where T: VecItem + Add { 160 | fn add_assign(&mut self, other: Self) { 161 | *self = Vec1 { 162 | x: self.x + other.x, 163 | ..Default::default() 164 | } 165 | } 166 | } 167 | 168 | impl SubAssign for Vec1 where T: VecItem + Sub { 169 | fn sub_assign(&mut self, other: Self) { 170 | *self = Vec1 { 171 | x: self.x - other.x, 172 | ..Default::default() 173 | } 174 | } 175 | } 176 | 177 | impl MulAssign for Vec1 where T: VecItem + Mul { 178 | fn mul_assign(&mut self, other: Self) { 179 | *self = Vec1 { 180 | x: self.x * other.x, 181 | ..Default::default() 182 | } 183 | } 184 | } 185 | 186 | impl DivAssign for Vec1 where T: VecItem + Div { 187 | fn div_assign(&mut self, other: Self) { 188 | *self = Vec1 { 189 | x: self.x / other.x, 190 | ..Default::default() 191 | } 192 | } 193 | } 194 | 195 | // Assign primitive operators 196 | 197 | impl AddAssign for Vec1 where T: VecItem + Add { 198 | fn add_assign(&mut self, other: T) { 199 | *self = Vec1 { 200 | x: self.x + other, 201 | ..Default::default() 202 | } 203 | } 204 | } 205 | 206 | impl SubAssign for Vec1 where T: VecItem + Sub { 207 | fn sub_assign(&mut self, other: T) { 208 | *self = Vec1 { 209 | x: self.x - other, 210 | ..Default::default() 211 | } 212 | } 213 | } 214 | 215 | impl MulAssign for Vec1 where T: VecItem + Mul { 216 | fn mul_assign(&mut self, other: T) { 217 | *self = Vec1 { 218 | x: self.x * other, 219 | ..Default::default() 220 | } 221 | } 222 | } 223 | 224 | impl DivAssign for Vec1 where T: VecItem + Div { 225 | fn div_assign(&mut self, other: T) { 226 | *self = Vec1 { 227 | x: self.x / other, 228 | ..Default::default() 229 | } 230 | } 231 | } 232 | 233 | // VecNum traits 234 | 235 | impl VecNum for Vec1 where T: VecItem + Num { 236 | fn sum(&self) -> Self::Item { 237 | self.x 238 | } 239 | 240 | fn product(&self) -> Self::Item { 241 | self.x 242 | } 243 | } 244 | 245 | // VecInt traits 246 | 247 | impl VecInt for Vec1 where T: VecItem + Integer { 248 | fn div_euc(&self, other: Self) -> Self { 249 | Self { 250 | x: self.x.div_floor(&other.x), 251 | } 252 | } 253 | } 254 | 255 | // VecSigned traits 256 | 257 | impl VecSigned for Vec1 where T: VecItem + Signed { 258 | fn snake_length(&self) -> Self::Item { 259 | self.x.abs() 260 | } 261 | } 262 | 263 | // VecFloat traits 264 | 265 | impl VecFloat for Vec1 where T: VecItem + Float { 266 | fn length(&self) -> Self::Item { 267 | self.x 268 | } 269 | 270 | fn norm(&self) -> Self { 271 | Vec1::new( 272 | self.x, 273 | ) 274 | } 275 | 276 | fn floor(&self) -> Self { 277 | self.map(|e| e.floor()) 278 | } 279 | 280 | fn ceil(&self) -> Self { 281 | self.map(|e| e.ceil()) 282 | } 283 | 284 | fn round(&self) -> Self { 285 | self.map(|e| e.round()) 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /src/vec2.rs: -------------------------------------------------------------------------------- 1 | //! Functionality pertaining to `Vec2` 2 | 3 | use core::ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; 4 | use core::fmt; 5 | 6 | #[allow(unused_imports)] 7 | use num::{Num, Integer, Unsigned, Signed, Float}; 8 | 9 | #[allow(unused_imports)] 10 | use super::{Vector, VecItem, VecNum, VecInt, VecUnsigned, VecSigned, VecFloat}; 11 | 12 | #[cfg(feature = "serialize")] 13 | #[derive(Copy, Clone, Default, Hash, Eq, PartialEq, Serialize, Deserialize)] 14 | pub struct Vec2 { 15 | pub x: T, 16 | pub y: T, 17 | } 18 | 19 | #[cfg(not(feature = "serialize"))] 20 | #[derive(Copy, Clone, Default, Hash, Eq, PartialEq)] 21 | pub struct Vec2 { 22 | pub x: T, 23 | pub y: T, 24 | } 25 | 26 | impl Vec2 { 27 | /// Creates a new Vec2 from multiple components 28 | pub fn new(x: T, y: T) -> Self { Self { x, y, ..Default::default() } } 29 | 30 | /// Returns the elements of the vector as an array 31 | pub fn elements(&self) -> [T; 2] { [self.x, self.y] } 32 | 33 | /// Apply an operation to all elements of this vector, returning the result 34 | pub fn map U>(&self, f: F) -> Vec2 { 35 | Vec2 { 36 | x: f(self.x), 37 | y: f(self.y), 38 | } 39 | } 40 | 41 | pub fn convert_to>(&self) -> Vec2 { 42 | Vec2 { 43 | x: U::from(self.x), 44 | y: U::from(self.y), 45 | } 46 | } 47 | } 48 | 49 | impl Vector for Vec2 { 50 | type Item = T; 51 | } 52 | 53 | // Debug and Display traits 54 | 55 | impl fmt::Debug for Vec2 { 56 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 57 | write!(f, "(x: {:?}, y: {:?})", self.x, self.y) 58 | } 59 | } 60 | 61 | impl fmt::Display for Vec2 { 62 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 63 | write!(f, "({}, {})", self.x, self.y) 64 | } 65 | } 66 | 67 | // From traits 68 | 69 | impl From<[T; 2]> for Vec2 { 70 | fn from(arr: [T; 2]) -> Self { Self { x: arr[0], y: arr[1], ..Default::default() } } 71 | } 72 | 73 | impl From<(T, T)> for Vec2 { 74 | fn from(tup: (T, T)) -> Self { Self { x: tup.0, y: tup.1, ..Default::default() } } 75 | } 76 | 77 | // Op traits 78 | 79 | impl Add for Vec2 where T: VecItem + Add, T::Output: VecItem + Add { 80 | type Output = Vec2; 81 | fn add(self, other: Self) -> Vec2 { 82 | Vec2 { 83 | x: self.x + other.x, 84 | y: self.y + other.y, 85 | ..Default::default() 86 | } 87 | } 88 | } 89 | 90 | impl Sub for Vec2 where T: VecItem + Sub, T::Output: VecItem + Sub { 91 | type Output = Vec2; 92 | fn sub(self, other: Self) -> Vec2 { 93 | Vec2 { 94 | x: self.x - other.x, 95 | y: self.y - other.y, 96 | ..Default::default() 97 | } 98 | } 99 | } 100 | 101 | impl Mul for Vec2 where T: VecItem + Mul, T::Output: VecItem + Mul { 102 | type Output = Vec2; 103 | fn mul(self, other: Self) -> Vec2 { 104 | Vec2 { 105 | x: self.x * other.x, 106 | y: self.y * other.y, 107 | ..Default::default() 108 | } 109 | } 110 | } 111 | 112 | impl Div for Vec2 where T: VecItem + Div, T::Output: VecItem + Div { 113 | type Output = Vec2; 114 | fn div(self, other: Self) -> Vec2 { 115 | Vec2 { 116 | x: self.x / other.x, 117 | y: self.y / other.y, 118 | ..Default::default() 119 | } 120 | } 121 | } 122 | 123 | // Op primitive traits 124 | 125 | impl Add for Vec2 where T: VecItem + Add, T::Output: VecItem + Add { 126 | type Output = Vec2; 127 | fn add(self, other: T) -> Vec2 { 128 | Vec2 { 129 | x: self.x + other, 130 | y: self.y + other, 131 | ..Default::default() 132 | } 133 | } 134 | } 135 | 136 | impl Sub for Vec2 where T: VecItem + Sub, T::Output: VecItem + Sub { 137 | type Output = Vec2; 138 | fn sub(self, other: T) -> Vec2 { 139 | Vec2 { 140 | x: self.x - other, 141 | y: self.y - other, 142 | ..Default::default() 143 | } 144 | } 145 | } 146 | 147 | impl Mul for Vec2 where T: VecItem + Mul, T::Output: VecItem + Mul { 148 | type Output = Vec2; 149 | fn mul(self, other: T) -> Vec2 { 150 | Vec2 { 151 | x: self.x * other, 152 | y: self.y * other, 153 | ..Default::default() 154 | } 155 | } 156 | } 157 | 158 | impl Div for Vec2 where T: VecItem + Div, T::Output: VecItem + Div { 159 | type Output = Vec2; 160 | fn div(self, other: T) -> Vec2 { 161 | Vec2 { 162 | x: self.x / other, 163 | y: self.y / other, 164 | ..Default::default() 165 | } 166 | } 167 | } 168 | 169 | // Assign operators 170 | 171 | impl AddAssign for Vec2 where T: VecItem + Add { 172 | fn add_assign(&mut self, other: Self) { 173 | *self = Vec2 { 174 | x: self.x + other.x, 175 | y: self.y + other.y, 176 | ..Default::default() 177 | } 178 | } 179 | } 180 | 181 | impl SubAssign for Vec2 where T: VecItem + Sub { 182 | fn sub_assign(&mut self, other: Self) { 183 | *self = Vec2 { 184 | x: self.x - other.x, 185 | y: self.y - other.y, 186 | ..Default::default() 187 | } 188 | } 189 | } 190 | 191 | impl MulAssign for Vec2 where T: VecItem + Mul { 192 | fn mul_assign(&mut self, other: Self) { 193 | *self = Vec2 { 194 | x: self.x * other.x, 195 | y: self.y * other.y, 196 | ..Default::default() 197 | } 198 | } 199 | } 200 | 201 | impl DivAssign for Vec2 where T: VecItem + Div { 202 | fn div_assign(&mut self, other: Self) { 203 | *self = Vec2 { 204 | x: self.x / other.x, 205 | y: self.y / other.y, 206 | ..Default::default() 207 | } 208 | } 209 | } 210 | 211 | // Assign primitive operators 212 | 213 | impl AddAssign for Vec2 where T: VecItem + Add { 214 | fn add_assign(&mut self, other: T) { 215 | *self = Vec2 { 216 | x: self.x + other, 217 | y: self.y + other, 218 | ..Default::default() 219 | } 220 | } 221 | } 222 | 223 | impl SubAssign for Vec2 where T: VecItem + Sub { 224 | fn sub_assign(&mut self, other: T) { 225 | *self = Vec2 { 226 | x: self.x - other, 227 | y: self.y - other, 228 | ..Default::default() 229 | } 230 | } 231 | } 232 | 233 | impl MulAssign for Vec2 where T: VecItem + Mul { 234 | fn mul_assign(&mut self, other: T) { 235 | *self = Vec2 { 236 | x: self.x * other, 237 | y: self.y * other, 238 | ..Default::default() 239 | } 240 | } 241 | } 242 | 243 | impl DivAssign for Vec2 where T: VecItem + Div { 244 | fn div_assign(&mut self, other: T) { 245 | *self = Vec2 { 246 | x: self.x / other, 247 | y: self.y / other, 248 | ..Default::default() 249 | } 250 | } 251 | } 252 | 253 | // VecNum traits 254 | 255 | impl VecNum for Vec2 where T: VecItem + Num { 256 | fn sum(&self) -> Self::Item { 257 | self.x + self.y 258 | } 259 | 260 | fn product(&self) -> Self::Item { 261 | self.x * self.y 262 | } 263 | } 264 | 265 | // VecInt traits 266 | 267 | impl VecInt for Vec2 where T: VecItem + Integer { 268 | fn div_euc(&self, other: Self) -> Self { 269 | Self { 270 | x: self.x.div_floor(&other.x), 271 | y: self.y.div_floor(&other.y), 272 | } 273 | } 274 | } 275 | 276 | // VecSigned traits 277 | 278 | impl VecSigned for Vec2 where T: VecItem + Signed { 279 | fn snake_length(&self) -> Self::Item { 280 | self.x.abs() + self.y.abs() 281 | } 282 | } 283 | 284 | // VecFloat traits 285 | 286 | impl VecFloat for Vec2 where T: VecItem + Float { 287 | fn length(&self) -> Self::Item { 288 | (self.x * self.x + self.y * self.y).sqrt() 289 | } 290 | 291 | fn norm(&self) -> Self { 292 | let len = self.length(); 293 | Vec2::new( 294 | self.x / len, 295 | self.y / len, 296 | ) 297 | } 298 | 299 | fn floor(&self) -> Self { 300 | self.map(|e| e.floor()) 301 | } 302 | 303 | fn ceil(&self) -> Self { 304 | self.map(|e| e.ceil()) 305 | } 306 | 307 | fn round(&self) -> Self { 308 | self.map(|e| e.round()) 309 | } 310 | } 311 | -------------------------------------------------------------------------------- /src/vec3.rs: -------------------------------------------------------------------------------- 1 | //! Functionality pertaining to `Vec3` 2 | 3 | use core::ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; 4 | use core::fmt; 5 | 6 | #[allow(unused_imports)] 7 | use num::{Num, Integer, Unsigned, Signed, Float}; 8 | 9 | #[allow(unused_imports)] 10 | use super::{Vector, VecItem, VecNum, VecInt, VecUnsigned, VecSigned, VecFloat}; 11 | 12 | #[cfg(feature = "serialize")] 13 | #[derive(Copy, Clone, Default, Hash, Eq, PartialEq, Serialize, Deserialize)] 14 | pub struct Vec3 { 15 | pub x: T, 16 | pub y: T, 17 | pub z: T, 18 | } 19 | 20 | #[cfg(not(feature = "serialize"))] 21 | #[derive(Copy, Clone, Default, Hash, Eq, PartialEq)] 22 | pub struct Vec3 { 23 | pub x: T, 24 | pub y: T, 25 | pub z: T, 26 | } 27 | 28 | impl Vec3 { 29 | /// Creates a new Vec3 from multiple components 30 | pub fn new(x: T, y: T, z: T) -> Self { Self { x, y, z, ..Default::default() } } 31 | 32 | /// Returns the elements of the vector as an array 33 | pub fn elements(&self) -> [T; 3] { [self.x, self.y, self.z] } 34 | 35 | /// Apply an operation to all elements of this vector, returning the result 36 | pub fn map U>(&self, f: F) -> Vec3 { 37 | Vec3 { 38 | x: f(self.x), 39 | y: f(self.y), 40 | z: f(self.z), 41 | } 42 | } 43 | 44 | pub fn convert_to>(&self) -> Vec3 { 45 | Vec3 { 46 | x: U::from(self.x), 47 | y: U::from(self.y), 48 | z: U::from(self.z), 49 | } 50 | } 51 | } 52 | 53 | impl Vector for Vec3 { 54 | type Item = T; 55 | } 56 | 57 | // Debug and Display traits 58 | 59 | impl fmt::Debug for Vec3 { 60 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 61 | write!(f, "(x: {:?}, y: {:?}, z: {:?})", self.x, self.y, self.z) 62 | } 63 | } 64 | 65 | impl fmt::Display for Vec3 { 66 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 67 | write!(f, "({}, {}, {})", self.x, self.y, self.z) 68 | } 69 | } 70 | 71 | // From traits 72 | 73 | impl From<[T; 3]> for Vec3 { 74 | fn from(arr: [T; 3]) -> Self { Self { x: arr[0], y: arr[1], z: arr[2], ..Default::default() } } 75 | } 76 | 77 | impl From<(T, T, T)> for Vec3 { 78 | fn from(tup: (T, T, T)) -> Self { Self { x: tup.0, y: tup.1, z: tup.2, ..Default::default() } } 79 | } 80 | 81 | // Op traits 82 | 83 | impl Add for Vec3 where T: VecItem + Add, T::Output: VecItem + Add { 84 | type Output = Vec3; 85 | fn add(self, other: Self) -> Vec3 { 86 | Vec3 { 87 | x: self.x + other.x, 88 | y: self.y + other.y, 89 | z: self.z + other.z, 90 | ..Default::default() 91 | } 92 | } 93 | } 94 | 95 | impl Sub for Vec3 where T: VecItem + Sub, T::Output: VecItem + Sub { 96 | type Output = Vec3; 97 | fn sub(self, other: Self) -> Vec3 { 98 | Vec3 { 99 | x: self.x - other.x, 100 | y: self.y - other.y, 101 | z: self.z - other.z, 102 | ..Default::default() 103 | } 104 | } 105 | } 106 | 107 | impl Mul for Vec3 where T: VecItem + Mul, T::Output: VecItem + Mul { 108 | type Output = Vec3; 109 | fn mul(self, other: Self) -> Vec3 { 110 | Vec3 { 111 | x: self.x * other.x, 112 | y: self.y * other.y, 113 | z: self.z * other.z, 114 | ..Default::default() 115 | } 116 | } 117 | } 118 | 119 | impl Div for Vec3 where T: VecItem + Div, T::Output: VecItem + Div { 120 | type Output = Vec3; 121 | fn div(self, other: Self) -> Vec3 { 122 | Vec3 { 123 | x: self.x / other.x, 124 | y: self.y / other.y, 125 | z: self.z / other.z, 126 | ..Default::default() 127 | } 128 | } 129 | } 130 | 131 | // Op primitive traits 132 | 133 | impl Add for Vec3 where T: VecItem + Add, T::Output: VecItem + Add { 134 | type Output = Vec3; 135 | fn add(self, other: T) -> Vec3 { 136 | Vec3 { 137 | x: self.x + other, 138 | y: self.y + other, 139 | z: self.z + other, 140 | ..Default::default() 141 | } 142 | } 143 | } 144 | 145 | impl Sub for Vec3 where T: VecItem + Sub, T::Output: VecItem + Sub { 146 | type Output = Vec3; 147 | fn sub(self, other: T) -> Vec3 { 148 | Vec3 { 149 | x: self.x - other, 150 | y: self.y - other, 151 | z: self.z - other, 152 | ..Default::default() 153 | } 154 | } 155 | } 156 | 157 | impl Mul for Vec3 where T: VecItem + Mul, T::Output: VecItem + Mul { 158 | type Output = Vec3; 159 | fn mul(self, other: T) -> Vec3 { 160 | Vec3 { 161 | x: self.x * other, 162 | y: self.y * other, 163 | z: self.z * other, 164 | ..Default::default() 165 | } 166 | } 167 | } 168 | 169 | impl Div for Vec3 where T: VecItem + Div, T::Output: VecItem + Div { 170 | type Output = Vec3; 171 | fn div(self, other: T) -> Vec3 { 172 | Vec3 { 173 | x: self.x / other, 174 | y: self.y / other, 175 | z: self.z / other, 176 | ..Default::default() 177 | } 178 | } 179 | } 180 | 181 | // Assign operators 182 | 183 | impl AddAssign for Vec3 where T: VecItem + Add { 184 | fn add_assign(&mut self, other: Self) { 185 | *self = Vec3 { 186 | x: self.x + other.x, 187 | y: self.y + other.y, 188 | z: self.z + other.z, 189 | ..Default::default() 190 | } 191 | } 192 | } 193 | 194 | impl SubAssign for Vec3 where T: VecItem + Sub { 195 | fn sub_assign(&mut self, other: Self) { 196 | *self = Vec3 { 197 | x: self.x - other.x, 198 | y: self.y - other.y, 199 | z: self.z - other.z, 200 | ..Default::default() 201 | } 202 | } 203 | } 204 | 205 | impl MulAssign for Vec3 where T: VecItem + Mul { 206 | fn mul_assign(&mut self, other: Self) { 207 | *self = Vec3 { 208 | x: self.x * other.x, 209 | y: self.y * other.y, 210 | z: self.z * other.z, 211 | ..Default::default() 212 | } 213 | } 214 | } 215 | 216 | impl DivAssign for Vec3 where T: VecItem + Div { 217 | fn div_assign(&mut self, other: Self) { 218 | *self = Vec3 { 219 | x: self.x / other.x, 220 | y: self.y / other.y, 221 | z: self.z / other.z, 222 | ..Default::default() 223 | } 224 | } 225 | } 226 | 227 | // Assign primitive operators 228 | 229 | impl AddAssign for Vec3 where T: VecItem + Add { 230 | fn add_assign(&mut self, other: T) { 231 | *self = Vec3 { 232 | x: self.x + other, 233 | y: self.y + other, 234 | z: self.z + other, 235 | ..Default::default() 236 | } 237 | } 238 | } 239 | 240 | impl SubAssign for Vec3 where T: VecItem + Sub { 241 | fn sub_assign(&mut self, other: T) { 242 | *self = Vec3 { 243 | x: self.x - other, 244 | y: self.y - other, 245 | z: self.z - other, 246 | ..Default::default() 247 | } 248 | } 249 | } 250 | 251 | impl MulAssign for Vec3 where T: VecItem + Mul { 252 | fn mul_assign(&mut self, other: T) { 253 | *self = Vec3 { 254 | x: self.x * other, 255 | y: self.y * other, 256 | z: self.z * other, 257 | ..Default::default() 258 | } 259 | } 260 | } 261 | 262 | impl DivAssign for Vec3 where T: VecItem + Div { 263 | fn div_assign(&mut self, other: T) { 264 | *self = Vec3 { 265 | x: self.x / other, 266 | y: self.y / other, 267 | z: self.z / other, 268 | ..Default::default() 269 | } 270 | } 271 | } 272 | 273 | // VecNum traits 274 | 275 | impl VecNum for Vec3 where T: VecItem + Num { 276 | fn sum(&self) -> Self::Item { 277 | self.x + self.y + self.z 278 | } 279 | 280 | fn product(&self) -> Self::Item { 281 | self.x * self.y * self.z 282 | } 283 | } 284 | 285 | // VecInt traits 286 | 287 | impl VecInt for Vec3 where T: VecItem + Integer { 288 | fn div_euc(&self, other: Self) -> Self { 289 | Self { 290 | x: self.x.div_floor(&other.x), 291 | y: self.y.div_floor(&other.y), 292 | z: self.z.div_floor(&other.z), 293 | } 294 | } 295 | } 296 | 297 | // VecSigned traits 298 | 299 | impl VecSigned for Vec3 where T: VecItem + Signed { 300 | fn snake_length(&self) -> Self::Item { 301 | self.x.abs() + self.y.abs() + self.z.abs() 302 | } 303 | } 304 | 305 | // VecFloat traits 306 | 307 | impl VecFloat for Vec3 where T: VecItem + Float { 308 | fn length(&self) -> Self::Item { 309 | (self.x * self.x + self.y * self.y + self.z * self.z).sqrt() 310 | } 311 | 312 | fn norm(&self) -> Self { 313 | let len = self.length(); 314 | Vec3::new( 315 | self.x / len, 316 | self.y / len, 317 | self.z / len, 318 | ) 319 | } 320 | 321 | fn floor(&self) -> Self { 322 | self.map(|e| e.floor()) 323 | } 324 | 325 | fn ceil(&self) -> Self { 326 | self.map(|e| e.ceil()) 327 | } 328 | 329 | fn round(&self) -> Self { 330 | self.map(|e| e.round()) 331 | } 332 | } 333 | -------------------------------------------------------------------------------- /src/vec4.rs: -------------------------------------------------------------------------------- 1 | //! Functionality pertaining to `Vec4` 2 | 3 | use core::ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; 4 | use core::fmt; 5 | 6 | #[allow(unused_imports)] 7 | use num::{Num, Integer, Unsigned, Signed, Float}; 8 | 9 | #[allow(unused_imports)] 10 | use super::{Vector, VecItem, VecNum, VecInt, VecUnsigned, VecSigned, VecFloat}; 11 | 12 | #[cfg(feature = "serialize")] 13 | #[derive(Copy, Clone, Default, Hash, Eq, PartialEq, Serialize, Deserialize)] 14 | pub struct Vec4 { 15 | pub x: T, 16 | pub y: T, 17 | pub z: T, 18 | pub w: T, 19 | } 20 | 21 | #[cfg(not(feature = "serialize"))] 22 | #[derive(Copy, Clone, Default, Hash, Eq, PartialEq)] 23 | pub struct Vec4 { 24 | pub x: T, 25 | pub y: T, 26 | pub z: T, 27 | pub w: T, 28 | } 29 | 30 | impl Vec4 { 31 | /// Creates a new Vec3 from multiple components 32 | pub fn new(x: T, y: T, z: T, w: T) -> Self { Self { x, y, z, w, ..Default::default() } } 33 | 34 | /// Returns the elements of the vector as an array 35 | pub fn elements(&self) -> [T; 4] { [self.x, self.y, self.z, self.w] } 36 | 37 | /// Apply an operation to all elements of this vector, returning the result 38 | pub fn map U>(&self, f: F) -> Vec4 { 39 | Vec4 { 40 | x: f(self.x), 41 | y: f(self.y), 42 | z: f(self.z), 43 | w: f(self.w), 44 | } 45 | } 46 | 47 | pub fn convert_to>(&self) -> Vec4 { 48 | Vec4 { 49 | x: U::from(self.x), 50 | y: U::from(self.y), 51 | z: U::from(self.z), 52 | w: U::from(self.w), 53 | } 54 | } 55 | } 56 | 57 | impl Vector for Vec4 { 58 | type Item = T; 59 | } 60 | 61 | // Debug and Display traits 62 | 63 | impl fmt::Debug for Vec4 { 64 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 65 | write!(f, "(x: {:?}, y: {:?}, z: {:?}, w: {:?})", self.x, self.y, self.z, self.w) 66 | } 67 | } 68 | 69 | impl fmt::Display for Vec4 { 70 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 71 | write!(f, "({}, {}, {}, {})", self.x, self.y, self.z, self.w) 72 | } 73 | } 74 | 75 | // From traits 76 | 77 | impl From<[T; 4]> for Vec4 { 78 | fn from(arr: [T; 4]) -> Self { Self { x: arr[0], y: arr[1], z: arr[2], w: arr[3], ..Default::default() } } 79 | } 80 | 81 | impl From<(T, T, T, T)> for Vec4 { 82 | fn from(tup: (T, T, T, T)) -> Self { Self { x: tup.0, y: tup.1, z: tup.2, w: tup.3, ..Default::default() } } 83 | } 84 | 85 | // Op traits 86 | 87 | impl Add for Vec4 where T: VecItem + Add, T::Output: VecItem + Add { 88 | type Output = Vec4; 89 | fn add(self, other: Self) -> Vec4 { 90 | Vec4 { 91 | x: self.x + other.x, 92 | y: self.y + other.y, 93 | z: self.z + other.z, 94 | w: self.w + other.w, 95 | ..Default::default() 96 | } 97 | } 98 | } 99 | 100 | impl Sub for Vec4 where T: VecItem + Sub, T::Output: VecItem + Sub { 101 | type Output = Vec4; 102 | fn sub(self, other: Self) -> Vec4 { 103 | Vec4 { 104 | x: self.x - other.x, 105 | y: self.y - other.y, 106 | z: self.z - other.z, 107 | w: self.w - other.w, 108 | ..Default::default() 109 | } 110 | } 111 | } 112 | 113 | impl Mul for Vec4 where T: VecItem + Mul, T::Output: VecItem + Mul { 114 | type Output = Vec4; 115 | fn mul(self, other: Self) -> Vec4 { 116 | Vec4 { 117 | x: self.x * other.x, 118 | y: self.y * other.y, 119 | z: self.z * other.z, 120 | w: self.w * other.w, 121 | ..Default::default() 122 | } 123 | } 124 | } 125 | 126 | impl Div for Vec4 where T: VecItem + Div, T::Output: VecItem + Div { 127 | type Output = Vec4; 128 | fn div(self, other: Self) -> Vec4 { 129 | Vec4 { 130 | x: self.x / other.x, 131 | y: self.y / other.y, 132 | z: self.z / other.z, 133 | w: self.w / other.w, 134 | ..Default::default() 135 | } 136 | } 137 | } 138 | 139 | // Op primitive traits 140 | 141 | impl Add for Vec4 where T: VecItem + Add, T::Output: VecItem + Add { 142 | type Output = Vec4; 143 | fn add(self, other: T) -> Vec4 { 144 | Vec4 { 145 | x: self.x + other, 146 | y: self.y + other, 147 | z: self.z + other, 148 | w: self.w + other, 149 | ..Default::default() 150 | } 151 | } 152 | } 153 | 154 | impl Sub for Vec4 where T: VecItem + Sub, T::Output: VecItem + Sub { 155 | type Output = Vec4; 156 | fn sub(self, other: T) -> Vec4 { 157 | Vec4 { 158 | x: self.x - other, 159 | y: self.y - other, 160 | z: self.z - other, 161 | w: self.w - other, 162 | ..Default::default() 163 | } 164 | } 165 | } 166 | 167 | impl Mul for Vec4 where T: VecItem + Mul, T::Output: VecItem + Mul { 168 | type Output = Vec4; 169 | fn mul(self, other: T) -> Vec4 { 170 | Vec4 { 171 | x: self.x * other, 172 | y: self.y * other, 173 | z: self.z * other, 174 | w: self.w * other, 175 | ..Default::default() 176 | } 177 | } 178 | } 179 | 180 | impl Div for Vec4 where T: VecItem + Div, T::Output: VecItem + Div { 181 | type Output = Vec4; 182 | fn div(self, other: T) -> Vec4 { 183 | Vec4 { 184 | x: self.x / other, 185 | y: self.y / other, 186 | z: self.z / other, 187 | w: self.w / other, 188 | ..Default::default() 189 | } 190 | } 191 | } 192 | 193 | // Assign operators 194 | 195 | impl AddAssign for Vec4 where T: VecItem + Add { 196 | fn add_assign(&mut self, other: Self) { 197 | *self = Vec4 { 198 | x: self.x + other.x, 199 | y: self.y + other.y, 200 | z: self.z + other.z, 201 | w: self.w + other.w, 202 | ..Default::default() 203 | } 204 | } 205 | } 206 | 207 | impl SubAssign for Vec4 where T: VecItem + Sub { 208 | fn sub_assign(&mut self, other: Self) { 209 | *self = Vec4 { 210 | x: self.x - other.x, 211 | y: self.y - other.y, 212 | z: self.z - other.z, 213 | w: self.w - other.w, 214 | ..Default::default() 215 | } 216 | } 217 | } 218 | 219 | impl MulAssign for Vec4 where T: VecItem + Mul { 220 | fn mul_assign(&mut self, other: Self) { 221 | *self = Vec4 { 222 | x: self.x * other.x, 223 | y: self.y * other.y, 224 | z: self.z * other.z, 225 | w: self.w * other.w, 226 | ..Default::default() 227 | } 228 | } 229 | } 230 | 231 | impl DivAssign for Vec4 where T: VecItem + Div { 232 | fn div_assign(&mut self, other: Self) { 233 | *self = Vec4 { 234 | x: self.x / other.x, 235 | y: self.y / other.y, 236 | z: self.z / other.z, 237 | w: self.w / other.w, 238 | ..Default::default() 239 | } 240 | } 241 | } 242 | 243 | // Assign primitive operators 244 | 245 | impl AddAssign for Vec4 where T: VecItem + Add { 246 | fn add_assign(&mut self, other: T) { 247 | *self = Vec4 { 248 | x: self.x + other, 249 | y: self.y + other, 250 | z: self.z + other, 251 | w: self.w + other, 252 | ..Default::default() 253 | } 254 | } 255 | } 256 | 257 | impl SubAssign for Vec4 where T: VecItem + Sub { 258 | fn sub_assign(&mut self, other: T) { 259 | *self = Vec4 { 260 | x: self.x - other, 261 | y: self.y - other, 262 | z: self.z - other, 263 | w: self.w - other, 264 | ..Default::default() 265 | } 266 | } 267 | } 268 | 269 | impl MulAssign for Vec4 where T: VecItem + Mul { 270 | fn mul_assign(&mut self, other: T) { 271 | *self = Vec4 { 272 | x: self.x * other, 273 | y: self.y * other, 274 | z: self.z * other, 275 | w: self.w * other, 276 | ..Default::default() 277 | } 278 | } 279 | } 280 | 281 | impl DivAssign for Vec4 where T: VecItem + Div { 282 | fn div_assign(&mut self, other: T) { 283 | *self = Vec4 { 284 | x: self.x / other, 285 | y: self.y / other, 286 | z: self.z / other, 287 | w: self.w / other, 288 | ..Default::default() 289 | } 290 | } 291 | } 292 | 293 | // VecNum traits 294 | 295 | impl VecNum for Vec4 where T: VecItem + Num { 296 | fn sum(&self) -> Self::Item { 297 | self.x + self.y + self.z + self.w 298 | } 299 | 300 | fn product(&self) -> Self::Item { 301 | self.x * self.y * self.z * self.w 302 | } 303 | } 304 | 305 | // VecInt traits 306 | 307 | impl VecInt for Vec4 where T: VecItem + Integer { 308 | fn div_euc(&self, other: Self) -> Self { 309 | Self { 310 | x: self.x.div_floor(&other.x), 311 | y: self.y.div_floor(&other.y), 312 | z: self.z.div_floor(&other.z), 313 | w: self.w.div_floor(&other.w), 314 | } 315 | } 316 | } 317 | 318 | // VecSigned traits 319 | 320 | impl VecSigned for Vec4 where T: VecItem + Signed { 321 | fn snake_length(&self) -> Self::Item { 322 | self.x.abs() + self.y.abs() + self.z.abs() + self.w.abs() 323 | } 324 | } 325 | 326 | // VecFloat traits 327 | 328 | impl VecFloat for Vec4 where T: VecItem + Float { 329 | fn length(&self) -> Self::Item { 330 | (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt() 331 | } 332 | 333 | fn norm(&self) -> Self { 334 | let len = self.length(); 335 | Vec4::new( 336 | self.x / len, 337 | self.y / len, 338 | self.z / len, 339 | self.w / len, 340 | ) 341 | } 342 | 343 | fn floor(&self) -> Self { 344 | self.map(|e| e.floor()) 345 | } 346 | 347 | fn ceil(&self) -> Self { 348 | self.map(|e| e.ceil()) 349 | } 350 | 351 | fn round(&self) -> Self { 352 | self.map(|e| e.round()) 353 | } 354 | } 355 | --------------------------------------------------------------------------------