From 902aeb5dbe4076c1c3deb94a5adbf77a91947b04 Mon Sep 17 00:00:00 2001 From: Jason Travis Smith Date: Thu, 31 Dec 2015 02:58:21 -0500 Subject: [PATCH 1/6] This adds get_size() to all vector implementations. get_size() was added so that vectors could all be converted to Vector4 when being turned into binary values. from_str_radix() for floating point numbers was deprecated from the standard library. Until there is time to write our own implementation of this floating point numbers will panic on non base 10 string conversion. Base 10 string conversion will use the from_str function. --- src/lib.rs | 1 - src/number.rs | 9 ++++++++- src/vector.rs | 19 +++++++++++++++---- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index bc83066..7af9538 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,6 @@ //! //! #![feature(zero_one)] -#![feature(float_from_str_radix)] #![feature(float_extras)] #![feature(associated_consts)] diff --git a/src/number.rs b/src/number.rs index ce5129f..6f13328 100644 --- a/src/number.rs +++ b/src/number.rs @@ -2,6 +2,7 @@ use std::cmp::PartialEq; use std::mem::size_of; use std::num::{Zero, One}; use std::ops::{Add, Sub, Mul, Div, Rem}; +use std::str::FromStr; use super::bounded::Bounded; @@ -770,7 +771,13 @@ macro_rules! float_number_trait_impl fn from_str_radix(src: &str, radix: u32) -> Result { - <$varType>::from_str_radix(src, radix) + // TODO: Currently this will panic on a non base 10 radix. + // This is because the std library deprecated the + // from_str_radix function. Until a function can be + // written this will use the from_str function and + // panic for non base 10 requests. + assert!(radix == 10); + <$varType>::from_str(src) } } )*) diff --git a/src/vector.rs b/src/vector.rs index 943c2f6..a47c322 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -47,6 +47,12 @@ pub trait Vector : Clone where T: Number } + // Property functions. + /// Returns the size, how many components the Vector + /// has, of this Vector. + fn get_size(&self) -> u8; + + // Scalar operations that change this Vector. /// Add a scalar value to this Vector. /// @@ -511,7 +517,7 @@ macro_rules! binary_operator_impl /// that implements the Vector trait. macro_rules! define_vector { - ($structName: ident <$T: ident> {$($field: ident),+}) => + ($structName: ident <$T: ident> {$($field: ident),+}, $field_count: expr) => { // Do not add a where clause here or implementing // generic traits were the generic is different @@ -558,6 +564,11 @@ macro_rules! define_vector $structName {$($field: val),+} } + fn get_size(&self) -> u8 + { + $field_count + } + fn add_scalar(&mut self, scalar: T) { *self = &*self + scalar; @@ -665,9 +676,9 @@ macro_rules! define_vector // Define the Vector2, Vector3, and Vector4 structures. -define_vector!(Vector2 {x, y}); -define_vector!(Vector3 {x, y, z}); -define_vector!(Vector4 {x, y, z, w}); +define_vector!(Vector2 {x, y}, 2u8); +define_vector!(Vector3 {x, y, z}, 3u8); +define_vector!(Vector4 {x, y, z, w}, 4u8); // Implements operations specific to the different From 946ad90fa033b01d5581d11c93f79d1de39e7921 Mon Sep 17 00:00:00 2001 From: Jason Travis Smith Date: Wed, 6 Jan 2016 00:54:44 -0500 Subject: [PATCH 2/6] Numbers now define how many bytes it takes to represent them. Numbers now have an associated constant value that defines how many bytes it takes to define them. --- src/number.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/number.rs b/src/number.rs index 6f13328..88a56e8 100644 --- a/src/number.rs +++ b/src/number.rs @@ -1,3 +1,5 @@ +use std::{u8, u16, u32, u64, usize}; +use std::{i8, i16, i32, i64, isize}; use std::cmp::PartialEq; use std::mem::size_of; use std::num::{Zero, One}; @@ -15,6 +17,11 @@ pub trait Number : Zero + One + Add + Sub + { type StrRadixError; + + /// The amount of Bytes required to represent this Number. + const BYTES: u8; + + /// Create a number from a given string and base radix. /// ///``` @@ -749,6 +756,10 @@ macro_rules! int_number_trait_impl { type StrRadixError = ::std::num::ParseIntError; + + const BYTES: u8 = <$varType>::BYTES; + + fn from_str_radix(src: &str, radix: u32) -> Result { @@ -762,12 +773,16 @@ macro_rules! int_number_trait_impl /// base float types in rust. macro_rules! float_number_trait_impl { - ($traitName: ident for $($varType: ty)*) => + ($traitName: ident for $($varType: ty, $numBytes: expr)*) => ($( impl $traitName for $varType { type StrRadixError = ::std::num::ParseFloatError; + + const BYTES: u8 = $numBytes; + + fn from_str_radix(src: &str, radix: u32) -> Result { @@ -787,7 +802,7 @@ macro_rules! float_number_trait_impl // Implement the Number trait for the types that are Numbers. int_number_trait_impl!(Number for u8 u16 u32 u64 usize); int_number_trait_impl!(Number for i8 i16 i32 i64 isize); -float_number_trait_impl!(Number for f32 f64); +float_number_trait_impl!(Number for f32, 4 f64, 8); // Implement the ToNumber and FromNumber traits for // the types that are Numbers. The FromNumber trait needs From 4aa410ad7e0f2909b4d070367fcf3b59140389c8 Mon Sep 17 00:00:00 2001 From: Jason Travis Smith Date: Wed, 6 Jan 2016 02:04:23 -0500 Subject: [PATCH 3/6] Making the associated constant Number::BYTES a usize. As much as I prefer to have tighter types for variables, this seems to make writing code easier and cleaner. --- src/number.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/number.rs b/src/number.rs index 88a56e8..776e432 100644 --- a/src/number.rs +++ b/src/number.rs @@ -19,7 +19,7 @@ pub trait Number : Zero + One + Add + Sub + /// The amount of Bytes required to represent this Number. - const BYTES: u8; + const BYTES: usize; /// Create a number from a given string and base radix. @@ -757,7 +757,7 @@ macro_rules! int_number_trait_impl type StrRadixError = ::std::num::ParseIntError; - const BYTES: u8 = <$varType>::BYTES; + const BYTES: usize = <$varType>::BYTES; fn from_str_radix(src: &str, radix: u32) -> @@ -780,7 +780,7 @@ macro_rules! float_number_trait_impl type StrRadixError = ::std::num::ParseFloatError; - const BYTES: u8 = $numBytes; + const BYTES: usize = $numBytes; fn from_str_radix(src: &str, radix: u32) -> From 04e744fb0f0df24fdaba4035b8ed0160d011f5c6 Mon Sep 17 00:00:00 2001 From: Jason Travis Smith Date: Wed, 6 Jan 2016 03:14:58 -0500 Subject: [PATCH 4/6] Removing the recent addition of Number::BYTES. This really does not have anything to do with a Number. This has to deal with the byte representation of certain types and as such it should really live in the Alchemy crate. --- src/number.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/number.rs b/src/number.rs index 776e432..5d1692a 100644 --- a/src/number.rs +++ b/src/number.rs @@ -1,5 +1,3 @@ -use std::{u8, u16, u32, u64, usize}; -use std::{i8, i16, i32, i64, isize}; use std::cmp::PartialEq; use std::mem::size_of; use std::num::{Zero, One}; @@ -18,10 +16,6 @@ pub trait Number : Zero + One + Add + Sub + type StrRadixError; - /// The amount of Bytes required to represent this Number. - const BYTES: usize; - - /// Create a number from a given string and base radix. /// ///``` @@ -757,9 +751,6 @@ macro_rules! int_number_trait_impl type StrRadixError = ::std::num::ParseIntError; - const BYTES: usize = <$varType>::BYTES; - - fn from_str_radix(src: &str, radix: u32) -> Result { @@ -780,9 +771,6 @@ macro_rules! float_number_trait_impl type StrRadixError = ::std::num::ParseFloatError; - const BYTES: usize = $numBytes; - - fn from_str_radix(src: &str, radix: u32) -> Result { From 9306a73f9a0d03a15f0f870fee18024880c7cf2a Mon Sep 17 00:00:00 2001 From: Jason Travis Smith Date: Wed, 6 Jan 2016 05:59:38 -0500 Subject: [PATCH 5/6] Added the Zero and One traits to sigils. It looks like these may be removed from the standard library soon. --- src/integer.rs | 2 +- src/lib.rs | 5 ++++- src/matrix.rs | 7 +++--- src/number.rs | 11 +++++----- src/one.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++++ src/quaternion.rs | 7 +++--- src/vector.rs | 9 ++++---- src/whole.rs | 2 +- src/zero.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 133 insertions(+), 18 deletions(-) create mode 100644 src/one.rs create mode 100644 src/zero.rs diff --git a/src/integer.rs b/src/integer.rs index 7a60d32..96384d4 100644 --- a/src/integer.rs +++ b/src/integer.rs @@ -22,7 +22,7 @@ use super::number::Number; /// [10]: https://doc.rust-lang.org/std/primitive.i64.html /// [11]: https://doc.rust-lang.org/std/primitive.isize.html /// [12]: https://doc.rust-lang.org/std/index.html -pub trait Integer : Number +pub trait Integer: Number { } diff --git a/src/lib.rs b/src/lib.rs index 7af9538..eb5ab79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,11 +2,12 @@ //! License: Proprietary //! //! -#![feature(zero_one)] #![feature(float_extras)] #![feature(associated_consts)] +mod zero; +mod one; mod bounded; mod number; mod whole; @@ -20,6 +21,8 @@ pub mod matrix; pub mod quaternion; +pub use self::zero::Zero; +pub use self::one::One; pub use self::number::Number; pub use self::whole::Whole; pub use self::integer::Integer; diff --git a/src/matrix.rs b/src/matrix.rs index fc9e016..c687dd0 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -1,9 +1,10 @@ //! This module defines the 2x2, 3x3, and 4x4 Matrix structures. -use std::num::{Zero, One}; use std::ops::{Add, Sub, Mul, Div, Rem, Neg}; -use super::number::Number; -use super::vector::{Vector, Vector2, Vector3, Vector4}; +use ::zero::Zero; +use ::one::One; +use ::number::Number; +use ::vector::{Vector, Vector2, Vector3, Vector4}; /// A trait that defines the minimum set of diff --git a/src/number.rs b/src/number.rs index 5d1692a..d977059 100644 --- a/src/number.rs +++ b/src/number.rs @@ -1,17 +1,18 @@ use std::cmp::PartialEq; use std::mem::size_of; -use std::num::{Zero, One}; use std::ops::{Add, Sub, Mul, Div, Rem}; use std::str::FromStr; -use super::bounded::Bounded; +use ::zero::Zero; +use ::one::One; +use ::bounded::Bounded; /// A trait that defines what is required to be considered /// a number. -pub trait Number : Zero + One + Add + Sub + - Mul + Div + Rem + - PartialEq + Copy + Clone +pub trait Number: Zero + One + Add + Sub + + Mul + Div + Rem + + PartialEq + Copy + Clone { type StrRadixError; diff --git a/src/one.rs b/src/one.rs new file mode 100644 index 0000000..7694e8e --- /dev/null +++ b/src/one.rs @@ -0,0 +1,54 @@ +use std::ops::Mul; + +/// Defines a multiplicative identity element for `Self`. +pub trait One: Sized + Mul +{ + /// Returns the multiplicative identity element of `Self`, `1`. + /// + /// # Laws + /// + /// ```{.text} + /// a * 1 = a ∀ a ∈ Self + /// 1 * a = a ∀ a ∈ Self + /// ``` + /// + /// # Purity + /// + /// This function should return the same result at all times regardless of + /// external mutable state, for example values stored in TLS or in + /// `static mut`s. + fn one() -> Self; +} + + + +macro_rules! one_impl +{ + ($varType: ty, $val: expr) => + { + impl One for $varType + { + fn one() -> $varType + { + $val + } + } + } +} + + + +one_impl!(u8, 1u8); +one_impl!(u16, 1u16); +one_impl!(u32, 1u32); +one_impl!(u64, 1u64); +one_impl!(usize, 1usize); + +one_impl!(i8, 1i8); +one_impl!(i16, 1i16); +one_impl!(i32, 1i32); +one_impl!(i64, 1i64); +one_impl!(isize, 1isize); + +one_impl!(f32, 1.0f32); +one_impl!(f64, 1.0f64); diff --git a/src/quaternion.rs b/src/quaternion.rs index 87d20ec..ddd71ac 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -3,11 +3,12 @@ //! //! [1]: https://en.wikipedia.org/wiki/Quaternion //! [2]: https://en.wikipedia.org/wiki/Dual_quaternion -use std::num::{Zero, One}; use std::ops::{Add, Sub, Mul, Div, Neg}; -use super::real::Real; -use super::vector::{Vector, EuclideanVector, Vector3}; +use ::zero::Zero; +use ::one::One; +use ::real::Real; +use ::vector::{Vector, EuclideanVector, Vector3}; /// A Quaternion is a combination of a scalar and a vector diff --git a/src/vector.rs b/src/vector.rs index a47c322..800483e 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -1,12 +1,13 @@ //! This module defines 2, 3, and 4 component [Vector][1] structures. //! //! [1]: https://en.wikipedia.org/wiki/Vector_(mathematics_and_physics) -use std::num::{Zero, One}; use std::ops::{Add, Sub, Mul, Div, Rem, Neg}; -use super::number::Number; -use super::real::Real; -use super::trig::{acos, atan2}; +use ::zero::Zero; +use ::one::One; +use ::number::Number; +use ::real::Real; +use ::trig::{acos, atan2}; /// A trait that defines the minimum set of diff --git a/src/whole.rs b/src/whole.rs index 2eadd7e..104a7b4 100644 --- a/src/whole.rs +++ b/src/whole.rs @@ -16,7 +16,7 @@ use super::number::Number; /// [5]: https://doc.rust-lang.org/std/primitive.u64.html /// [6]: https://doc.rust-lang.org/std/primitive.usize.html /// [7]: https://doc.rust-lang.org/std/index.html -pub trait Whole : Number +pub trait Whole: Number { } diff --git a/src/zero.rs b/src/zero.rs new file mode 100644 index 0000000..6ff510e --- /dev/null +++ b/src/zero.rs @@ -0,0 +1,54 @@ +use std::ops::Add; + +/// Defines an additive identity element for `Self`. +pub trait Zero: Sized + Add +{ + /// Returns the additive identity element of `Self`, `0`. + /// + /// # Laws + /// + /// ```{.text} + /// a + 0 = a ∀ a ∈ Self + /// 0 + a = a ∀ a ∈ Self + /// ``` + /// + /// # Purity + /// + /// This function should return the same result at all times regardless of + /// external mutable state, for example values stored in TLS or in + /// `static mut`s. + fn zero() -> Self; +} + + + +macro_rules! zero_impl +{ + ($varType: ty, $val: expr) => + { + impl Zero for $varType + { + fn zero() -> $varType + { + $val + } + } + } +} + + + +zero_impl!(u8, 0u8); +zero_impl!(u16, 0u16); +zero_impl!(u32, 0u32); +zero_impl!(u64, 0u64); +zero_impl!(usize, 0usize); + +zero_impl!(i8, 0i8); +zero_impl!(i16, 0i16); +zero_impl!(i32, 0i32); +zero_impl!(i64, 0i64); +zero_impl!(isize, 0isize); + +zero_impl!(f32, 0.0f32); +zero_impl!(f64, 0.0f64); From e64c3b0fbecca351e0a078fefc4273a0f0b8e6ad Mon Sep 17 00:00:00 2001 From: Jason Travis Smith Date: Thu, 7 Jan 2016 17:42:23 -0500 Subject: [PATCH 6/6] Added Debug, Display, and Default to Vectors and Quaternions. This also adds an example for Vectors and Quaternions. --- examples/quaternion.rs | 14 ++++++++++ examples/vector.rs | 22 +++++++++++++++ src/number.rs | 3 +- src/quaternion.rs | 29 ++++++++++++++++++++ src/vector.rs | 62 +++++++++++++++++++++++++++++++++++++++++- 5 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 examples/quaternion.rs create mode 100644 examples/vector.rs diff --git a/examples/quaternion.rs b/examples/quaternion.rs new file mode 100644 index 0000000..5d94d72 --- /dev/null +++ b/examples/quaternion.rs @@ -0,0 +1,14 @@ +extern crate sigils; + + + +use sigils::quaternion::{Quaternion}; + + +pub fn main() +{ + let quat: Quaternion; + + quat = Quaternion::::default(); + println!("Quaternion: {}", quat); +} diff --git a/examples/vector.rs b/examples/vector.rs new file mode 100644 index 0000000..3857d64 --- /dev/null +++ b/examples/vector.rs @@ -0,0 +1,22 @@ +extern crate sigils; + + + +use sigils::vector::{Vector2, Vector3, Vector4}; + + +pub fn main() +{ + let vec2: Vector2; + let vec3: Vector3; + let vec4: Vector4; + + vec2 = Vector2::::default(); + println!("Vector2: {}", vec2); + + vec3 = Vector3::::default(); + println!("Vector3: {}", vec3); + + vec4 = Vector4::::default(); + println!("Vector4: {}", vec4); +} diff --git a/src/number.rs b/src/number.rs index d977059..4dad830 100644 --- a/src/number.rs +++ b/src/number.rs @@ -1,4 +1,5 @@ use std::cmp::PartialEq; +use std::fmt::{Debug, Display}; use std::mem::size_of; use std::ops::{Add, Sub, Mul, Div, Rem}; use std::str::FromStr; @@ -12,7 +13,7 @@ use ::bounded::Bounded; /// a number. pub trait Number: Zero + One + Add + Sub + Mul + Div + Rem + - PartialEq + Copy + Clone + PartialEq + Copy + Clone + Debug + Display { type StrRadixError; diff --git a/src/quaternion.rs b/src/quaternion.rs index ddd71ac..8dc3036 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -3,6 +3,7 @@ //! //! [1]: https://en.wikipedia.org/wiki/Quaternion //! [2]: https://en.wikipedia.org/wiki/Dual_quaternion +use std::fmt::{Error, Formatter, Debug, Display}; use std::ops::{Add, Sub, Mul, Div, Neg}; use ::zero::Zero; @@ -275,6 +276,34 @@ impl Quaternion where T: Real // TODO: Add binary operations for editing self. } +// Implement the Debug trait for the Quaternion. +impl Debug for Quaternion where T: Real +{ + fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> + { + write!(formatter, "[{:?}, {:?}]", self.scalar, self.vector) + } +} + +// Implement the Display trait for the Quaternion. +impl Display for Quaternion where T: Real +{ + fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> + { + write!(formatter, "[{}, {}]", self.scalar, self.vector) + } +} + +// Implement a default value for Quaternions which +// returns the identity quaternion. +impl Default for Quaternion where T: Real +{ + fn default() -> Quaternion + { + Quaternion::identity() + } +} + // Implement the Zero and One traits for the Quaternion. impl Zero for Quaternion where T: Real { diff --git a/src/vector.rs b/src/vector.rs index 800483e..7624a54 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -1,6 +1,7 @@ //! This module defines 2, 3, and 4 component [Vector][1] structures. //! //! [1]: https://en.wikipedia.org/wiki/Vector_(mathematics_and_physics) +use std::fmt::{Error, Formatter, Debug, Display}; use std::ops::{Add, Sub, Mul, Div, Rem, Neg}; use ::zero::Zero; @@ -10,11 +11,13 @@ use ::real::Real; use ::trig::{acos, atan2}; + /// A trait that defines the minimum set of /// functions a [Vector][1] must implement. /// /// [1]: https://en.wikipedia.org/wiki/Vector_(mathematics_and_physics) -pub trait Vector : Clone where T: Number +pub trait Vector: Debug + Display + Clone + Default + Zero + One + where T: Number { // Creation functions. /// Create a Vector from a single value. @@ -638,6 +641,63 @@ macro_rules! define_vector } } + // Implement the Debug trait for the Vector. + impl Debug for $structName where T: Number + { + fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> + { + let mut count: u8; + + // Use the size of the Vector to + // pretty up the printing. + count = self.get_size(); + + write!(formatter, "<"); + $( + write!(formatter, "{:?}", self.$field); + if count > 0 + { + write!(formatter, ", "); + } + count -= 1; + )* + write!(formatter, ">") + } + } + + // Implement the Display trait for the Vector. + impl Display for $structName where T: Number + { + fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> + { + let mut count: u8; + + // Use the size of the Vector to + // pretty up the printing. + count = self.get_size(); + + write!(formatter, "<"); + $( + write!(formatter, "{}", self.$field); + if count > 1 + { + write!(formatter, ", "); + } + count -= 1; + )* + write!(formatter, ">") + } + } + + // Implement the Default trait for the Vector. + impl Default for $structName where T: Number + { + fn default() -> $structName + { + $structName::identity() + } + } + // Implement the Zero and One traits for the Vector. impl Zero for $structName where T: Number {