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/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 bc83066..eb5ab79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,12 +2,12 @@ //! License: Proprietary //! //! -#![feature(zero_one)] -#![feature(float_from_str_radix)] #![feature(float_extras)] #![feature(associated_consts)] +mod zero; +mod one; mod bounded; mod number; mod whole; @@ -21,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 eb8684e..999dc94 100644 --- a/src/number.rs +++ b/src/number.rs @@ -1,10 +1,13 @@ use std::cmp::PartialEq; +use std::fmt::{Debug, Display}; use std::mem::size_of; -use std::num::{Zero, One}; use std::ops::{Add, Sub, Mul, Div, Rem}; use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; +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 @@ -13,10 +16,11 @@ pub trait Number : Zero + One + Add + Sub + Mul + Div + Rem + AddAssign + SubAssign + MulAssign + DivAssign + RemAssign + PartialEq + - Copy + Clone + Copy + Clone + Debug + Display { type StrRadixError; + /// Create a number from a given string and base radix. /// ///``` @@ -751,6 +755,7 @@ macro_rules! int_number_trait_impl { type StrRadixError = ::std::num::ParseIntError; + fn from_str_radix(src: &str, radix: u32) -> Result { @@ -764,16 +769,23 @@ 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; + 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) } } )*) @@ -783,7 +795,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 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..8dc3036 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -3,11 +3,13 @@ //! //! [1]: https://en.wikipedia.org/wiki/Quaternion //! [2]: https://en.wikipedia.org/wiki/Dual_quaternion -use std::num::{Zero, One}; +use std::fmt::{Error, Formatter, Debug, Display}; 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 @@ -274,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 47d68a2..c2dd0e4 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -1,20 +1,24 @@ //! 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::fmt::{Error, Formatter, Debug, Display}; use std::ops::{Add, Sub, Mul, Div, Rem, Neg}; use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; -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 /// 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. @@ -48,6 +52,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. /// @@ -554,7 +564,7 @@ macro_rules! binary_operator_assign_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 @@ -601,6 +611,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; @@ -669,6 +684,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 { @@ -720,9 +792,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 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);