Finished the Vector definition.

This complete what is needed for the definition of Vector2, Vector3, and Vector4.

This required a trigonometry section, fleshing out the rest of the Number, ToNumber,
and FromNumber section, correctly defining all the available function for the Real
trait, and defining several constants.
This commit is contained in:
Jason Travis Smith 2015-10-09 13:02:54 -04:00
parent e410e69e2f
commit 7ae702fd5c
13 changed files with 3158 additions and 198 deletions

8
README.md Normal file
View File

@ -0,0 +1,8 @@
# Sigils #
A mathematics library.
The code in this library uses macros pretty heavily. As such,
please check the trait's documentation for a function since the
macro definition will not really be documented. This was not
done to make documentation difficult, but to make coding the
library easier and to make it easier to maintain.

61
src/bounded.rs Normal file
View File

@ -0,0 +1,61 @@
use std::{u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64};
/// Primitive types that have upper and lower bounds.
pub trait Bounded
{
// TODO: I would love for this to be associated consts, but
// they are not currently working inside macros.
// It causes rust's stack to explode.
// Check this on later versions of rustc.
//
// Last version checked: rustc v1.3.0
/// The minimum value for this type.
//const MIN: Self;
fn min_value() -> Self;
/// The maximum value for this type.
//const MAX: Self;
fn max_value() -> Self;
}
/// A macro for making implementation of
/// the Bounded trait easier.
macro_rules! bounded_trait_impl
{
($T: ty, $minVal: expr, $maxVal: expr) =>
{
impl Bounded for $T
{
//const MIN: $T = $minVal;
fn min_value() -> $T
{
$minVal
}
//const MAX: $T = $maxVal;
fn max_value() -> $T
{
$maxVal
}
}
}
}
// Implement the Bounded for all the primitive types.
bounded_trait_impl!(u8, u8::MIN, u8::MAX);
bounded_trait_impl!(u16, u16::MIN, u16::MAX);
bounded_trait_impl!(u32, u32::MIN, u32::MAX);
bounded_trait_impl!(u64, u64::MIN, u64::MAX);
bounded_trait_impl!(usize, usize::MIN, usize::MAX);
bounded_trait_impl!(i8, i8::MIN, i8::MAX);
bounded_trait_impl!(i16, i16::MIN, i16::MAX);
bounded_trait_impl!(i32, i32::MIN, i32::MAX);
bounded_trait_impl!(i64, i64::MIN, i64::MAX);
bounded_trait_impl!(isize, isize::MIN, isize::MAX);
bounded_trait_impl!(f32, f32::MIN, f32::MAX);
bounded_trait_impl!(f64, f64::MIN, f64::MAX);

289
src/constants.rs Normal file
View File

@ -0,0 +1,289 @@
use std::{f32, f64};
// Create the Constants trait so that we can use
// associated constants to define Mathematical constants for
// the f32 and f64 types.
/// Defines Mathematical constants.
pub trait Constants
{
/// The square root of 2.
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::SQRT_2;
/// let val64: f64 = Constants::SQRT_2;
/// # assert_eq!(val32, std::f32::consts::SQRT_2);
/// # assert_eq!(val64, std::f64::consts::SQRT_2);
///```
const SQRT_2: Self;
/// The square root of 3.
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::SQRT_3;
/// let val64: f64 = Constants::SQRT_3;
/// # assert_eq!(val32, 1.73205080756887729352f32);
/// # assert_eq!(val64, 1.73205080756887729352f64);
///```
const SQRT_3: Self;
/// The inverse of the square root of 2
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::INVERSE_SQRT_2;
/// let val64: f64 = Constants::INVERSE_SQRT_2;
/// # assert_eq!(val32, 1.0f32 / std::f32::consts::SQRT_2);
/// # assert_eq!(val64, 1.0f64 / std::f64::consts::SQRT_2);
///```
const INVERSE_SQRT_2: Self;
/// The inverse of the square root of 3.
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::INVERSE_SQRT_3;
/// let val64: f64 = Constants::INVERSE_SQRT_3;
/// # assert_eq!(val32, 1.0f32 / 1.73205080756887729352f32);
/// # assert_eq!(val64, 1.0f64 / 1.73205080756887729352f64);
///```
const INVERSE_SQRT_3: Self;
/// The mathematical constant [E][1]. Also known as [Euler's number][1].
/// [1]: https://en.wikipedia.org/wiki/E_(mathematical_constant)
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::E;
/// let val64: f64 = Constants::E;
/// # assert_eq!(val32, std::f32::consts::E);
/// # assert_eq!(val64, std::f64::consts::E);
///```
const E: Self;
/// The log base 2 of E.
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::LOG2_E;
/// let val64: f64 = Constants::LOG2_E;
/// # assert_eq!(val32, std::f32::consts::LOG2_E);
/// # assert_eq!(val64, std::f64::consts::LOG2_E);
///```
const LOG2_E: Self;
/// The log base 10 of E.
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::LOG10_E;
/// let val64: f64 = Constants::LOG10_E;
/// # assert_eq!(val32, std::f32::consts::LOG10_E);
/// # assert_eq!(val64, std::f64::consts::LOG10_E);
///```
const LOG10_E: Self;
/// The natural log(ln) of 2.
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::LOGE_2;
/// let val64: f64 = Constants::LOGE_2;
/// # assert_eq!(val32, 2.0f32.ln());
/// # assert_eq!(val64, 2.0f64.ln());
///```
const LOGE_2: Self;
/// The natural log(ln) of 10.
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::LOGE_10;
/// let val64: f64 = Constants::LOGE_10;
/// # assert_eq!(val32, 10.0f32.ln());
/// # assert_eq!(val64, 10.0f64.ln());
///```
const LOGE_10: Self;
/// Two times the value of PI.
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::TWO_PI;
/// let val64: f64 = Constants::TWO_PI;
/// # assert_eq!(val32, std::f32::consts::PI * 2.0f32);
/// # assert_eq!(val64, std::f64::consts::PI * 2.0f64);
///```
const TWO_PI: Self;
/// [PI][1]. The ratio of a circles circumference to its diameter.
/// [1]: https://en.wikipedia.org/wiki/Pi
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::PI;
/// let val64: f64 = Constants::PI;
/// # assert_eq!(val32, std::f32::consts::PI);
/// # assert_eq!(val64, std::f64::consts::PI);
///```
const PI: Self;
/// One half of PI. (PI/2)
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::HALF_PI;
/// let val64: f64 = Constants::HALF_PI;
/// # assert_eq!(val32, std::f32::consts::PI / 2.0f32);
/// # assert_eq!(val64, std::f64::consts::PI / 2.0f64);
///```
const HALF_PI: Self;
/// One third of PI. (PI/3)
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::THIRD_PI;
/// let val64: f64 = Constants::THIRD_PI;
/// # assert_eq!(val32, std::f32::consts::PI / 3.0f32);
/// # assert_eq!(val64, std::f64::consts::PI / 3.0f64);
///```
const THIRD_PI: Self;
/// One forth of PI. (PI/4)
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::QUARTER_PI;
/// let val64: f64 = Constants::QUARTER_PI;
/// # assert_eq!(val32, std::f32::consts::PI / 4.0f32);
/// # assert_eq!(val64, std::f64::consts::PI / 4.0f64);
///```
const QUARTER_PI: Self;
/// One sixth of PI. (PI/6)
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::SIXTH_PI;
/// let val64: f64 = Constants::SIXTH_PI;
/// # assert_eq!(val32, std::f32::consts::PI / 6.0f32);
/// # assert_eq!(val64, std::f64::consts::PI / 6.0f64);
///```
const SIXTH_PI: Self;
/// One eighth of PI. (PI/8)
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::EIGHTH_PI;
/// let val64: f64 = Constants::EIGHTH_PI;
/// # assert_eq!(val32, std::f32::consts::PI / 8.0f32);
/// # assert_eq!(val64, std::f64::consts::PI / 8.0f64);
///```
const EIGHTH_PI: Self;
/// The inverse of PI. (1/PI)
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::INVERSE_PI;
/// let val64: f64 = Constants::INVERSE_PI;
/// # assert_eq!(val32, 1.0f32 / std::f32::consts::PI);
/// # assert_eq!(val64, 1.0f64 / std::f64::consts::PI);
///```
const INVERSE_PI: Self;
/// Two times the inverse of PI. (2/PI)
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::TWO_INVERSE_PI;
/// let val64: f64 = Constants::TWO_INVERSE_PI;
/// # assert_eq!(val32, 2.0f32 / std::f32::consts::PI);
/// # assert_eq!(val64, 2.0f64 / std::f64::consts::PI);
///```
const TWO_INVERSE_PI: Self;
/// Two times the inverse of the square root of PI. (2/sqrt(PI))
///
///```
/// use sigils::Constants;
///
/// let val32: f32 = Constants::TWO_INVERSE_SQRT_PI;
/// let val64: f64 = Constants::TWO_INVERSE_SQRT_PI;
/// # assert_eq!(val32, 2.0f32 * (std::f32::consts::PI).sqrt().recip());
/// # assert_eq!(val64, 2.0f64 * (std::f64::consts::PI).sqrt().recip());
///```
const TWO_INVERSE_SQRT_PI: Self;
}
// Implement a macro to simplify defining these constants
// for the two different types, f32 and f64.
macro_rules! constants_trait_impl
{
($T: ty, $sqrt2: expr, $sqrt3: expr, $e: expr,
$log2e: expr, $log10e: expr, $loge2: expr, $loge10: expr,
$pi: expr, $sqrtPI: expr) =>
{
impl Constants for $T
{
const SQRT_2: $T = $sqrt2;
const SQRT_3: $T = $sqrt3;
const INVERSE_SQRT_2: $T = 1.0 / $sqrt2;
const INVERSE_SQRT_3: $T = 1.0 / $sqrt3;
const E: $T = $e;
const LOG2_E: $T = $log2e;
const LOG10_E: $T = $log10e;
const LOGE_2: $T = $loge2;
const LOGE_10: $T = $loge10;
const TWO_PI: $T = 2.0 * $pi;
const PI: $T = $pi;
const HALF_PI: $T = $pi / 2.0;
const THIRD_PI: $T = $pi / 3.0;
const QUARTER_PI: $T = $pi / 4.0;
const SIXTH_PI: $T = $pi / 6.0;
const EIGHTH_PI: $T = $pi / 8.0;
const INVERSE_PI: $T = 1.0 / $pi;
const TWO_INVERSE_PI: $T = 2.0 / $pi;
const TWO_INVERSE_SQRT_PI: $T = 2.0 / $sqrtPI;
}
}
}
// Implement the math Constants.
constants_trait_impl!(f32, f32::consts::SQRT_2, 1.73205080756887729352f32,
f32::consts::E, f32::consts::LOG2_E,
f32::consts::LOG10_E, f32::consts::LN_2,
f32::consts::LN_10, f32::consts::PI,
1.7724538509055159f32);
constants_trait_impl!(f64, f64::consts::SQRT_2, 1.73205080756887729352f64,
f64::consts::E, f64::consts::LOG2_E,
f64::consts::LOG10_E, f64::consts::LN_2,
f64::consts::LN_10, f64::consts::PI,
1.7724538509055159f64);

View File

@ -1,16 +1,28 @@
//! A mathematical library.
//! License: Proprietary
//!
//!
#![feature(zero_one)] #![feature(zero_one)]
#![feature(float_from_str_radix)] #![feature(float_from_str_radix)]
#![feature(float_extras)]
#![feature(associated_consts)]
mod bounded;
mod number; mod number;
mod whole; mod whole;
mod integer; mod integer;
mod real; mod real;
mod constants;
pub mod trig;
pub mod vector; pub mod vector;
pub mod matrix;
pub mod quaternion;
pub use self::vector::Vector; pub use self::number::Number;
pub use self::vector::Vector2; pub use self::whole::Whole;
pub use self::vector::Vector3; pub use self::integer::Integer;
pub use self::vector::Vector4; pub use self::real::Real;
pub use self::constants::Constants;

1
src/matrix.rs Normal file
View File

@ -0,0 +1 @@
//! This module defines the 2x2, 3x3, and 4x4 Matrix structures.

View File

@ -1,7 +1,10 @@
use std::cmp::PartialEq; use std::cmp::PartialEq;
use std::mem::size_of;
use std::num::{Zero, One}; use std::num::{Zero, One};
use std::ops::{Add, Sub, Mul, Div, Rem}; use std::ops::{Add, Sub, Mul, Div, Rem};
use super::bounded::Bounded;
/// A trait that defines what is required to be considered /// A trait that defines what is required to be considered
/// a number. /// a number.
@ -12,34 +15,751 @@ pub trait Number : Zero + One + Add<Output=Self> + Sub<Output=Self> +
type StrRadixError; type StrRadixError;
/// Create a number from a given string and base radix. /// Create a number from a given string and base radix.
///
///```
/// // Parse the hex value "FF" into an i32.
/// // Hex values have a radix (base) of 16.
/// use sigils::Number;
///
/// let x: i32 = Number::from_str_radix("FF", 16u32).unwrap();
/// # assert_eq!(x, 255i32);
///```
fn from_str_radix(src: &str, radix: u32) -> fn from_str_radix(src: &str, radix: u32) ->
Result<Self, Self::StrRadixError>; Result<Self, Self::StrRadixError>;
} }
/// A trait that defines converting something to a Number.
// Create some macros to ease typing and reading. pub trait ToNumber
/// A macro to make implementing the trait easier for all the
/// base integer types in rust.
macro_rules! int_trait_impl
{ {
($traitName: ident for $($varType: ty)*) => /// Convert this to an u8.
($( /// None is returned if the conversion is not possible.
impl Number for $varType fn to_u8(&self) -> Option<u8>
{ {
type StrRadixError = ::std::num::ParseIntError; let option: Option<u64>;
fn from_str_radix(src: &str, radix: u32) -> option = self.to_u64();
Result<Self, ::std::num::ParseIntError> match option
{ {
<$varType>::from_str_radix(src, radix) Some(val) =>
} {
val.to_u8()
} }
)*)
None =>
{
None
}
}
}
/// Convert this to an u16.
/// None is returned if the conversion is not possible.
fn to_u16(&self) -> Option<u16>
{
let option: Option<u64>;
option = self.to_u64();
match option
{
Some(val) =>
{
val.to_u16()
}
None =>
{
None
}
}
}
/// Convert this to an u32.
/// None is returned if the conversion is not possible.
fn to_u32(&self) -> Option<u32>
{
let option: Option<u64>;
option = self.to_u64();
match option
{
Some(val) =>
{
val.to_u32()
}
None =>
{
None
}
}
}
/// Convert this to an u64.
/// None is returned if the conversion is not possible.
fn to_u64(&self) -> Option<u64>;
/// Convert this to an usize.
/// None is returned if the conversion is not possible.
fn to_usize(&self) -> Option<usize>
{
let option: Option<u64>;
option = self.to_u64();
match option
{
Some(val) =>
{
val.to_usize()
}
None =>
{
None
}
}
}
/// Convert this to an i8.
/// None is returned if the conversion is not possible.
fn to_i8(&self) -> Option<i8>
{
let option: Option<i64>;
option = self.to_i64();
match option
{
Some(val) =>
{
val.to_i8()
}
None =>
{
None
}
}
}
/// Convert this to an i16.
/// None is returned if the conversion is not possible.
fn to_i16(&self) -> Option<i16>
{
let option: Option<i64>;
option = self.to_i64();
match option
{
Some(val) =>
{
val.to_i16()
}
None =>
{
None
}
}
}
/// Convert this to an i32.
/// None is returned if the conversion is not possible.
fn to_i32(&self) -> Option<i32>
{
let option: Option<i64>;
option = self.to_i64();
match option
{
Some(val) =>
{
val.to_i32()
}
None =>
{
None
}
}
}
/// Convert this to an i64.
/// None is returned if the conversion is not possible.
fn to_i64(&self) -> Option<i64>;
/// Convert this to an isize.
/// None is returned if the conversion is not possible.
fn to_isize(&self) -> Option<isize>
{
let option: Option<i64>;
option = self.to_i64();
match option
{
Some(val) =>
{
val.to_isize()
}
None =>
{
None
}
}
}
/// Convert this to an f32.
/// None is returned if the conversion is not possible.
fn to_f32(&self) -> Option<f32>
{
let option: Option<f64>;
option = self.to_f64();
match option
{
Some(val) =>
{
val.to_f32()
}
None =>
{
None
}
}
}
/// Convert this to an f64.
/// None is returned if the conversion is not possible.
fn to_f64(&self) -> Option<f64>
{
let option: Option<i64>;
option = self.to_i64();
match option
{
Some(val) =>
{
val.to_f64()
}
None =>
{
None
}
}
}
} }
/// A macro to make implementing the trait easier for all the /// A trait that defines convertung a Number to something else.
pub trait FromNumber : Sized
{
/// Convert an i8 to an optional value of this type.
/// None is returned if the conversion is not possible.
fn from_i8(number: i8) -> Option<Self>
{
FromNumber::from_i64(number as i64)
}
/// Convert an i16 to an optional value of this type.
/// None is returned if the conversion is not possible.
fn from_i16(number: i16) -> Option<Self>
{
FromNumber::from_i64(number as i64)
}
/// Convert an i32 to an optional value of this type.
/// None is returned if the conversion is not possible.
fn from_i32(number: i32) -> Option<Self>
{
FromNumber::from_i64(number as i64)
}
/// Convert an i64 to an optional value of this type.
/// None is returned if the conversion is not possible.
fn from_i64(number: i64) -> Option<Self>;
/// Convert an isize to an optional value of this type.
/// None is returned if the conversion is not possible.
fn from_isize(number: isize) -> Option<Self>
{
FromNumber::from_i64(number as i64)
}
/// Convert an u8 to an optional value of this type.
/// None is returned if the conversion is not possible.
fn from_u8(number: u8) -> Option<Self>
{
FromNumber::from_u64(number as u64)
}
/// Convert an u16 to an optional value of this type.
/// None is returned if the conversion is not possible.
fn from_u16(number: u16) -> Option<Self>
{
FromNumber::from_u64(number as u64)
}
/// Convert an u32 to an optional value of this type.
/// None is returned if the conversion is not possible.
fn from_u32(number: u32) -> Option<Self>
{
FromNumber::from_u64(number as u64)
}
/// Convert an u64 to an optional value of this type.
/// None is returned if the conversion is not possible.
fn from_u64(number: u64) -> Option<Self>;
/// Convert an usize to an optional value of this type.
/// None is returned if the conversion is not possible.
fn from_usize(number: usize) -> Option<Self>
{
FromNumber::from_u64(number as u64)
}
/// Convert an f32 to an optional value of this type.
/// None is returned if the conversion is not possible.
fn from_f32(number: f32) -> Option<Self>
{
FromNumber::from_f64(number as f64)
}
/// Convert an f64 to an optional value of this type.
/// None is returned if the conversion is not possible.
fn from_f64(number: f64) -> Option<Self>
{
FromNumber::from_i64(number as i64)
}
}
// Create some macros to ease typing and reading.
macro_rules! convert_int_to_int
{
($srcType: ty, $dstType: ty, $val: expr) =>
{
{
let num: i64;
let min_value: $dstType;
let max_value: $dstType;
num = $val as i64;
min_value = Bounded::min_value();
max_value = Bounded::max_value();
if (min_value as i64) <= num && num <= (max_value as i64)
{
Some($val as $dstType)
}
else
{
None
}
}
}
}
macro_rules! convert_int_to_uint
{
($srcType: ty, $dstType: ty, $val: expr) =>
{
{
let zero: $srcType;
let max_value: $dstType;
zero = Zero::zero();
max_value = Bounded::max_value();
if zero <= $val && ($val as u64) <= (max_value as u64)
{
Some($val as $dstType)
}
else
{
None
}
}
}
}
macro_rules! convert_uint_to_int
{
($dstType: ty, $val: expr) =>
{
{
let max_value: $dstType;
max_value = Bounded::max_value();
if ($val as u64) <= (max_value as u64)
{
Some($val as $dstType)
}
else
{
None
}
}
}
}
macro_rules! convert_uint_to_uint
{
($srcType: ty, $dstType: ty, $val: expr) =>
{
if size_of::<$srcType>() <= size_of::<$dstType>()
{
Some($val as $dstType)
}
else
{
let zero: $srcType;
let max_value: $dstType;
zero = Zero::zero();
max_value = Bounded::max_value();
if zero <= $val && ($val as u64) <= (max_value as u64)
{
Some($val as $dstType)
}
else
{
None
}
}
}
}
macro_rules! convert_float_to_float
{
($srcType: ty, $dstType: ty, $val: expr) =>
{
if size_of::<$srcType>() <= size_of::<$dstType>()
{
Some($val as $dstType)
}
else
{
let num: f64;
let min_value: $srcType;
let max_value: $srcType;
num = $val as f64;
min_value = Bounded::min_value();
max_value = Bounded::max_value();
if (min_value as f64) <= num && num <= (max_value as f64)
{
Some($val as $dstType)
}
else
{
None
}
}
}
}
macro_rules! int_to_number_impl
{
($traitName: ident for $($varType: ty)*) =>
($(
impl $traitName for $varType
{
fn to_u8(&self) -> Option<u8>
{
convert_int_to_uint!($varType, u8, *self)
}
fn to_u16(&self) -> Option<u16>
{
convert_int_to_uint!($varType, u16, *self)
}
fn to_u32(&self) -> Option<u32>
{
convert_int_to_uint!($varType, u32, *self)
}
fn to_u64(&self) -> Option<u64>
{
convert_int_to_uint!($varType, u64, *self)
}
fn to_usize(&self) -> Option<usize>
{
convert_int_to_uint!($varType, usize, *self)
}
fn to_i8(&self) -> Option<i8>
{
convert_int_to_int!($varType, i8, *self)
}
fn to_i16(&self) -> Option<i16>
{
convert_int_to_int!($varType, i16, *self)
}
fn to_i32(&self) -> Option<i32>
{
convert_int_to_int!($varType, i32, *self)
}
fn to_i64(&self) -> Option<i64>
{
convert_int_to_int!($varType, i64, *self)
}
fn to_isize(&self) -> Option<isize>
{
convert_int_to_int!($varType, isize, *self)
}
fn to_f32(&self) -> Option<f32>
{
Some(*self as f32)
}
fn to_f64(&self) -> Option<f64>
{
Some(*self as f64)
}
}
)*)
}
macro_rules! uint_to_number_impl
{
($traitName: ident for $($varType: ty)*) =>
($(
impl $traitName for $varType
{
fn to_u8(&self) -> Option<u8>
{
convert_uint_to_uint!($varType, u8, *self)
}
fn to_u16(&self) -> Option<u16>
{
convert_uint_to_uint!($varType, u16, *self)
}
fn to_u32(&self) -> Option<u32>
{
convert_uint_to_uint!($varType, u32, *self)
}
fn to_u64(&self) -> Option<u64>
{
convert_uint_to_uint!($varType, u64, *self)
}
fn to_usize(&self) -> Option<usize>
{
convert_uint_to_uint!($varType, usize, *self)
}
fn to_i8(&self) -> Option<i8>
{
convert_uint_to_int!(i8, *self)
}
fn to_i16(&self) -> Option<i16>
{
convert_uint_to_int!(i16, *self)
}
fn to_i32(&self) -> Option<i32>
{
convert_uint_to_int!(i32, *self)
}
fn to_i64(&self) -> Option<i64>
{
convert_uint_to_int!(i64, *self)
}
fn to_isize(&self) -> Option<isize>
{
convert_uint_to_int!(isize, *self)
}
fn to_f32(&self) -> Option<f32>
{
Some(*self as f32)
}
fn to_f64(&self) -> Option<f64>
{
Some(*self as f64)
}
}
)*)
}
macro_rules! float_to_number_impl
{
($traitName: ident for $($varType: ty)*) =>
($(
impl $traitName for $varType
{
fn to_u8(&self) -> Option<u8>
{
Some(*self as u8)
}
fn to_u16(&self) -> Option<u16>
{
Some(*self as u16)
}
fn to_u32(&self) -> Option<u32>
{
Some(*self as u32)
}
fn to_u64(&self) -> Option<u64>
{
Some(*self as u64)
}
fn to_usize(&self) -> Option<usize>
{
Some(*self as usize)
}
fn to_i8(&self) -> Option<i8>
{
Some(*self as i8)
}
fn to_i16(&self) -> Option<i16>
{
Some(*self as i16)
}
fn to_i32(&self) -> Option<i32>
{
Some(*self as i32)
}
fn to_i64(&self) -> Option<i64>
{
Some(*self as i64)
}
fn to_isize(&self) -> Option<isize>
{
Some(*self as isize)
}
fn to_f32(&self) -> Option<f32>
{
convert_float_to_float!($varType, f32, *self)
}
fn to_f64(&self) -> Option<f64>
{
convert_float_to_float!($varType, f64, *self)
}
}
)*)
}
macro_rules! from_number_impl
{
($varType: ty, $toTypeFunc: ident) =>
{
impl FromNumber for $varType
{
fn from_u8(number: u8) -> Option<$varType>
{
number.$toTypeFunc()
}
fn from_u16(number: u16) -> Option<$varType>
{
number.$toTypeFunc()
}
fn from_u32(number: u32) -> Option<$varType>
{
number.$toTypeFunc()
}
fn from_u64(number: u64) -> Option<$varType>
{
number.$toTypeFunc()
}
fn from_i8(number: i8) -> Option<$varType>
{
number.$toTypeFunc()
}
fn from_i16(number: i16) -> Option<$varType>
{
number.$toTypeFunc()
}
fn from_i32(number: i32) -> Option<$varType>
{
number.$toTypeFunc()
}
fn from_i64(number: i64) -> Option<$varType>
{
number.$toTypeFunc()
}
fn from_f32(number: f32) -> Option<$varType>
{
number.$toTypeFunc()
}
fn from_f64(number: f64) -> Option<$varType>
{
number.$toTypeFunc()
}
}
}
}
/// A macro to make implementing the Number trait easier for all the
/// base integer types in rust.
macro_rules! int_number_trait_impl
{
($traitName: ident for $($varType: ty)*) =>
($(
impl $traitName for $varType
{
type StrRadixError = ::std::num::ParseIntError;
fn from_str_radix(src: &str, radix: u32) ->
Result<Self, ::std::num::ParseIntError>
{
<$varType>::from_str_radix(src, radix)
}
}
)*)
}
/// A macro to make implementing the Number trait easier for all the
/// base float types in rust. /// base float types in rust.
macro_rules! float_trait_impl macro_rules! float_number_trait_impl
{ {
($traitName: ident for $($varType: ty)*) => ($traitName: ident for $($varType: ty)*) =>
($( ($(
@ -57,7 +777,30 @@ macro_rules! float_trait_impl
} }
// Implement the trait for the types that are Numbers. // Implement the Number trait for the types that are Numbers.
int_trait_impl!(Number for u8 u16 u32 u64 usize); int_number_trait_impl!(Number for u8 u16 u32 u64 usize);
int_trait_impl!(Number for i8 i16 i32 i64 isize); int_number_trait_impl!(Number for i8 i16 i32 i64 isize);
float_trait_impl!(Number for f32 f64); float_number_trait_impl!(Number for f32 f64);
// Implement the ToNumber and FromNumber traits for
// the types that are Numbers. The FromNumber trait needs
// to be defined after ToNumber since FromNumber uses
// ToNumber definitions.
uint_to_number_impl!(ToNumber for u8 u16 u32 u64 usize);
int_to_number_impl!(ToNumber for i8 i16 i32 i64 isize);
float_to_number_impl!(ToNumber for f32 f64);
from_number_impl!(u8, to_u8);
from_number_impl!(u16, to_u16);
from_number_impl!(u32, to_u32);
from_number_impl!(u64, to_u64);
from_number_impl!(usize, to_usize);
from_number_impl!(i8, to_i8);
from_number_impl!(i16, to_i16);
from_number_impl!(i32, to_i32);
from_number_impl!(i64, to_i64);
from_number_impl!(isize, to_isize);
from_number_impl!(f32, to_f32);
from_number_impl!(f64, to_f64);

5
src/quaternion.rs Normal file
View File

@ -0,0 +1,5 @@
//! This module defines the [Quaternion][1] and
//! [DualQuaternion][2] structures.
//!
//! [1]: https://en.wikipedia.org/wiki/Quaternion
//! [2]: https://en.wikipedia.org/wiki/Dual_quaternion

File diff suppressed because it is too large Load Diff

26
src/trig.rs Normal file
View File

@ -0,0 +1,26 @@
//use super::constants::Constants;
use super::real::Real;
/*
pub struct Radians<T> where T: Real
{
pub value: T
}
pub struct Degrees<T> where T: Real
{
pub value: T
}
*/
pub fn acos<T>(x: T) -> T where T: Real
{
x.acos()
}
pub fn atan2<T>(x: T, y: T) -> T where T: Real
{
x.atan2(y)
}

View File

@ -1,11 +1,18 @@
//! 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::num::{Zero, One};
use std::ops::{Add, Sub, Mul, Div, Rem}; use std::ops::{Add, Sub, Mul, Div, Rem, Neg};
use super::number::Number; use super::number::Number;
use super::real::Real;
use super::trig::{acos, atan2};
/// A trait that defines the minimum set of /// A trait that defines the minimum set of
/// functions a Vector must implement. /// functions a [Vector][1] must implement.
///
/// [1]: https://en.wikipedia.org/wiki/Vector_(mathematics_and_physics)
pub trait Vector<T> : Clone where T: Number pub trait Vector<T> : Clone where T: Number
{ {
// Creation functions. // Creation functions.
@ -23,26 +30,6 @@ pub trait Vector<T> : Clone where T: Number
///``` ///```
fn from_value(val: T) -> Self; fn from_value(val: T) -> Self;
/// Create a zero Vector. All components will be set to zero.
///
/// ```
/// // Create a new Vector4<u8> where all
/// // the components are 0.
/// use sigils::vector::*;
///
/// let vector = Vector4::<u8>::zero();
/// # assert_eq!(vector.x, 0u8);
/// # assert_eq!(vector.y, 0u8);
/// # assert_eq!(vector.z, 0u8);
/// # assert_eq!(vector.w, 0u8);
/// ```
// TODO: Should Vectors implement the Zero trait
// instead of defining a function for it?
fn zero() -> Self
{
Self::from_value(T::zero())
}
/// Create an identity Vector. All components will be set to one. /// Create an identity Vector. All components will be set to one.
/// ///
/// ``` /// ```
@ -54,78 +41,75 @@ pub trait Vector<T> : Clone where T: Number
/// # assert_eq!(vector.x, 1i32); /// # assert_eq!(vector.x, 1i32);
/// # assert_eq!(vector.y, 1i32); /// # assert_eq!(vector.y, 1i32);
/// ``` /// ```
// TODO: Should Vectors implement the One trait
// instead of defining an identity function?
fn identity() -> Self fn identity() -> Self
{ {
Self::from_value(T::one()) Self::from_value(T::one())
} }
// Scalar operations that result in a new Vector. // Scalar operations that change this Vector.
/// Add a scalar value to this Vector and return a new Vector. /// Add a scalar value to this Vector.
/// ///
/// ``` /// ```
/// // Create a new Vector2<i32> where all /// // Create a new Vector2<i32> where all
/// // the components are 1. Then add 1 to it. /// // the components are 1. Then add 1 to it.
/// use sigils::vector::*; /// use sigils::vector::*;
/// ///
/// let vector = Vector2::<i32>::identity(); /// let mut vector = Vector2::<i32>::identity();
/// let vector_two = vector.add_scalar(1i32); /// vector.add_scalar(1i32);
/// # assert_eq!(vector_two.x, 2i32); /// # assert_eq!(vector.x, 2i32);
/// # assert_eq!(vector_two.y, 2i32); /// # assert_eq!(vector.y, 2i32);
/// ``` /// ```
fn add_scalar(&self, scalar: T) -> Self; fn add_scalar(&mut self, scalar: T);
/// Subtract a scalar value from this Vector and return a new Vector. /// Subtract a scalar value from this Vector.
/// ///
/// ``` /// ```
/// // Create a new Vector4<f64> where all /// // Create a new Vector4<f64> where all
/// // the components are 1. Then subtract 1 from it. /// // the components are 1. Then subtract 1 from it.
/// use sigils::vector::*; /// use sigils::vector::*;
/// ///
/// let vector = Vector4::<f64>::identity(); /// let mut vector = Vector4::<f64>::identity();
/// let vector_two = vector.sub_scalar(1.0f64); /// vector.sub_scalar(1.0f64);
/// # assert_eq!(vector_two.x, 0f64); /// # assert_eq!(vector.x, 0f64);
/// # assert_eq!(vector_two.y, 0f64); /// # assert_eq!(vector.y, 0f64);
/// # assert_eq!(vector_two.z, 0f64); /// # assert_eq!(vector.z, 0f64);
/// # assert_eq!(vector_two.w, 0f64); /// # assert_eq!(vector.w, 0f64);
/// ``` /// ```
fn sub_scalar(&self, scalar: T) -> Self; fn sub_scalar(&mut self, scalar: T);
/// Multiply this Vector by a scalar value and return a new Vector. /// Multiply this Vector by a scalar value.
/// ///
/// ``` /// ```
/// // Create a new Vector4<f64> where all /// // Create a new Vector4<f64> where all
/// // the components are 5. Then multiply it by 5. /// // the components are 5. Then multiply it by 5.
/// use sigils::vector::*; /// use sigils::vector::*;
/// ///
/// let vector = Vector4::<f32>::from_value(5f32); /// let mut vector = Vector4::<f32>::from_value(5f32);
/// let vector_two = vector.mul_scalar(5f32); /// vector.mul_scalar(5f32);
/// # assert_eq!(vector_two.x, 25f32); /// # assert_eq!(vector.x, 25f32);
/// # assert_eq!(vector_two.y, 25f32); /// # assert_eq!(vector.y, 25f32);
/// # assert_eq!(vector_two.z, 25f32); /// # assert_eq!(vector.z, 25f32);
/// # assert_eq!(vector_two.w, 25f32); /// # assert_eq!(vector.w, 25f32);
/// ``` /// ```
fn mul_scalar(&self, scalar: T) -> Self; fn mul_scalar(&mut self, scalar: T);
/// Divide this Vector by a scalar value and return a new Vector. /// Divide this Vector by a scalar value.
/// ///
/// ``` /// ```
/// // Create a new Vector3<u8> where all /// // Create a new Vector3<u8> where all
/// // the components are 25. Then divide it by 5. /// // the components are 25. Then divide it by 5.
/// use sigils::vector::*; /// use sigils::vector::*;
/// ///
/// let vector = Vector3::<u8>::from_value(25u8); /// let mut vector = Vector3::<u8>::from_value(25u8);
/// let vector_two = vector.div_scalar(5u8); /// vector.div_scalar(5u8);
/// # assert_eq!(vector_two.x, 5u8); /// # assert_eq!(vector.x, 5u8);
/// # assert_eq!(vector_two.y, 5u8); /// # assert_eq!(vector.y, 5u8);
/// # assert_eq!(vector_two.z, 5u8); /// # assert_eq!(vector.z, 5u8);
/// ``` /// ```
fn div_scalar(&self, scalar: T) -> Self; fn div_scalar(&mut self, scalar: T);
/// Divide this Vector by a scalar value, take the remainder, /// Divide this Vector by a scalar value and store the remainder.
/// and return a new Vector.
/// ///
/// ``` /// ```
/// // Create a new Vector3<isize> where all /// // Create a new Vector3<isize> where all
@ -133,79 +117,226 @@ pub trait Vector<T> : Clone where T: Number
/// // and take the remainder. /// // and take the remainder.
/// use sigils::vector::*; /// use sigils::vector::*;
/// ///
/// let vector = Vector3::<isize>::from_value(25isize); /// let mut vector = Vector3::<isize>::from_value(25isize);
/// let vector_two = vector.rem_scalar(7isize); /// vector.rem_scalar(7isize);
/// # assert_eq!(vector_two.x, 4isize); /// # assert_eq!(vector.x, 4isize);
/// # assert_eq!(vector_two.y, 4isize); /// # assert_eq!(vector.y, 4isize);
/// # assert_eq!(vector_two.z, 4isize); /// # assert_eq!(vector.z, 4isize);
/// ``` /// ```
fn rem_scalar(&self, scalar: T) -> Self; fn rem_scalar(&mut self, scalar: T);
// Vector operations that result in a new Vector.
/// Add a Vector to this Vector and return a new Vector.
fn add_vector(&self, vector: &Self) -> Self;
/// Subtract a Vector from this Vector and return a new Vector.
fn sub_vector(&self, vector: &Self) -> Self;
/// Multiply this Vector by a Vector and return a new Vector.
fn mul_vector(&self, vector: &Self) -> Self;
/// Divide this Vector by a Vector and return a new Vector.
fn div_vector(&self, vector: &Self) -> Self;
/// Divide this Vector by a Vector, take the remainder,
/// and return a new Vector.
fn rem_vector(&self, vector: &Self) -> Self;
// Scalar operations that change this Vector.
/// Add a scalar value to this Vector.
fn add_scalar_self(&mut self, scalar: T);
/// Subtract a scalar value from this Vector.
fn sub_scalar_self(&mut self, scalar: T);
/// Multiply this Vector by a scalar value.
fn mul_scalar_self(&mut self, scalar: T);
/// Divide this Vector by a scalar value.
fn div_scalar_self(&mut self, scalar: T);
/// Divide this Vector by a scalar value and take the remainder.
fn rem_scalar_self(&mut self, scalar: T);
// Vector operations that change this Vector. // Vector operations that change this Vector.
/// Add a Vector to this Vector. /// Add a Vector to this Vector.
fn add_vector_self(&mut self, vector: &Self); ///
/// ```
/// // Create a new Vector2<i32> where all
/// // the components are 1. Then add
/// // another Vector2<i32>, where all the
/// // components are 1, to it.
/// use sigils::vector::*;
///
/// let mut vector = Vector2::<i32>::identity();
/// let vector_two = Vector2::<i32>::identity();
/// vector.add_vector(&vector_two);
/// # assert_eq!(vector.x, 2i32);
/// # assert_eq!(vector.y, 2i32);
/// ```
fn add_vector(&mut self, vector: &Self);
/// Subtract a Vector from this Vector. /// Subtract a Vector from this Vector.
fn sub_vector_self(&mut self, vector: &Self); ///
/// ```
/// // Create a new Vector3<i64> where all
/// // the components are 5. Then subtract
/// // a Vector3<i64>, where all the
/// // components are 2, from it.
/// use sigils::vector::*;
///
/// let mut vector = Vector3::<i64>::from_value(5i64);
/// let vector_two = Vector3::<i64>::from_value(2i64);
/// vector.sub_vector(&vector_two);
/// # assert_eq!(vector.x, 3i64);
/// # assert_eq!(vector.y, 3i64);
/// # assert_eq!(vector.z, 3i64);
/// ```
fn sub_vector(&mut self, vector: &Self);
/// Multiply this Vector by a Vector. /// Multiply this Vector by a Vector.
fn mul_vector_self(&mut self, vector: &Self); ///
/// ```
/// // Create a new Vector4<f32> where all
/// // the components are 6.5. Then multiply
/// // it by another Vector4<f32>, where all the
/// // components are 4.0.
/// use sigils::vector::*;
///
/// let mut vector = Vector4::<f32>::from_value(6.5f32);
/// let vector_two = Vector4::<f32>::from_value(4.0f32);
/// vector.mul_vector(&vector_two);
/// # assert_eq!(vector.x, 26.0f32);
/// # assert_eq!(vector.y, 26.0f32);
/// # assert_eq!(vector.z, 26.0f32);
/// # assert_eq!(vector.w, 26.0f32);
/// ```
fn mul_vector(&mut self, vector: &Self);
/// Divide this Vector by a Vector. /// Divide this Vector by a Vector.
fn div_vector_self(&mut self, vector: &Self); ///
/// ```
/// // Create a new Vector2<f64> where all
/// // the components are 19. Then
/// // divide it by another Vector2<f64>,
/// // where all the components are 2.0.
/// use sigils::vector::*;
///
/// let mut vector = Vector2::<f64>::from_value(19.0f64);
/// let vector_two = Vector2::<f64>::from_value(2.0f64);
/// vector.div_vector(&vector_two);
/// # assert_eq!(vector.x, 9.5f64);
/// # assert_eq!(vector.y, 9.5f64);
/// ```
fn div_vector(&mut self, vector: &Self);
/// Divide this Vector by a Vector and take the remainder. /// Divide this Vector by a Vector and store the remainder.
fn rem_vector_self(&mut self, vector: &Self); ///
/// ```
/// // Create a new Vector3<usize> where all
/// // the components are 22. Then
/// // divide it by another Vector3<usize>,
/// // where all the components are 6.
/// use sigils::vector::*;
///
/// let mut vector = Vector3::<usize>::from_value(22usize);
/// let vector_two = Vector3::<usize>::from_value(6usize);
/// vector.rem_vector(&vector_two);
/// # assert_eq!(vector.x, 4usize);
/// # assert_eq!(vector.y, 4usize);
/// # assert_eq!(vector.z, 4usize);
/// ```
fn rem_vector(&mut self, vector: &Self);
// TODO: Look at defining negation
// Basic Vector functions. // Basic Vector functions.
/// Get the sum of all the components of the Vector. /// Get the sum of all the components of the Vector.
///
///```
/// // Create a new Vector4<f32> where all
/// // the components are 5.125. Then get
/// // the sum of the Vector's components.
/// use sigils::vector::*;
///
/// let vector: Vector4<f32> = Vector4::<f32>::from_value(5.125f32);
/// let sum: f32 = vector.get_sum();
/// # assert_eq!(sum, 20.5f32);
///```
fn get_sum(&self) -> T; fn get_sum(&self) -> T;
/// Get the product of all the components of the Vector. /// Get the product of all the components of the Vector.
///
///```
/// // Create a new Vector3<isize> where all
/// // the components are 3. Then get
/// // the product of the Vector's components.
/// use sigils::vector::*;
///
/// let vector: Vector3<isize> = Vector3::<isize>::from_value(3isize);
/// let sum: isize = vector.get_product();
/// # assert_eq!(sum, 27isize);
///```
fn get_product(&self) -> T; fn get_product(&self) -> T;
/// Get the dot product between this and another Vector. /// Get the dot product between this and another Vector.
fn dot(&self, vector: &Self) -> T ///
///```
/// // Create a two new Vector3<i64> where all
/// // the components are 3. Then get the
/// // dot product of the two Vectors.
/// use sigils::vector::*;
///
/// let vector: Vector3<i64> = Vector3::<i64>::from_value(3i64);
/// let vector_two: Vector3<i64> = Vector3::<i64>::from_value(3i64);
/// let dotProduct: i64 = vector.dot(&vector_two);
/// # assert_eq!(dotProduct, 27i64);
///```
fn dot(&self, vector: &Self) -> T;
}
/// Defines the [EuclideanVector][1] trait.
///
/// [1]: https://en.wikipedia.org/wiki/Euclidean_vector
pub trait EuclideanVector<T> : Vector<T> where T: Real
{
/// Get the length of the Vector.
fn get_length(&self) -> T
{ {
self.mul_vector(vector).get_sum() self.dot(self).sqrt()
}
/// Get the squared length of the Vector.
fn get_length_squared(&self) -> T
{
self.dot(self)
}
/// Normalizes the Vector by multplying all the
/// components by 1/|V|.
fn normalize(&self) -> Self
{
let mut new_vector: Self;
new_vector = self.clone();
new_vector.mul_scalar(self.get_length().recip());
new_vector
}
/// Normalizes the Vector by multplying all the
/// components by 1/|V|.
fn normalize_self(&mut self)
{
let length: T;
length = self.get_length().recip();
self.mul_scalar(length)
}
/// Determines if this Vector is perpendicular to another Vector.
fn is_perpendicular_to(&self, vector: &Self) -> bool
{
// TODO: Make this work with a fudge factor since floats
// are tricky.
self.dot(vector) == T::zero()
}
/// Calculates the angle between this vector and
/// another Vector, in radians.
fn angle(&self, vector: &Self) -> T;
/// Linearly interpolate the length of this Vector
/// towards the length of another Vector by a given amount.
fn lerp(&self, vector: &Self, amount: T) -> Self
{
let mut temp: Self;
let mut new_vector: Self;
temp = vector.clone();
temp.sub_vector(&self);
temp.mul_scalar(amount);
new_vector = self.clone();
new_vector.add_vector(&temp);
new_vector
}
/// Linearly interpolate the length of this Vector
/// towards the length of another Vector by a given amount.
fn lerp_self(&mut self, vector: &Self, amount: T)
{
let mut temp: Self;
temp = vector.clone();
temp.mul_scalar(amount);
self.add_vector(&temp);
} }
} }
@ -239,6 +370,16 @@ macro_rules! binary_operator_impl
($traitName: ident :: $funcName: ident, ($traitName: ident :: $funcName: ident,
$structName: ident {$($field: ident),+}) => $structName: ident {$($field: ident),+}) =>
{ {
impl<T> $traitName<T> for $structName<T> where T: Number
{
type Output = $structName<T>;
fn $funcName(self, scalar: T) -> $structName<T>
{
$structName::new($(self.$field.$funcName(scalar)),+)
}
}
impl<'a, T> $traitName<T> for &'a $structName<T> where T: Number impl<'a, T> $traitName<T> for &'a $structName<T> where T: Number
{ {
type Output = $structName<T>; type Output = $structName<T>;
@ -249,6 +390,59 @@ macro_rules! binary_operator_impl
} }
} }
impl<'a, T> $traitName<&'a T> for $structName<T> where T: Number
{
type Output = $structName<T>;
fn $funcName(self, scalar: &'a T) -> $structName<T>
{
$structName::new($(self.$field.$funcName(*scalar)),+)
}
}
impl<'a, 'b, T> $traitName<&'b T> for &'a $structName<T> where T: Number
{
type Output = $structName<T>;
fn $funcName(self, scalar: &'b T) -> $structName<T>
{
$structName::new($(self.$field.$funcName(*scalar)),+)
}
}
impl<'a, T> $traitName<$structName<T>> for $structName<T>
where T: Number
{
type Output = $structName<T>;
fn $funcName(self, vector: $structName<T>) -> $structName<T>
{
$structName::new($(self.$field.$funcName(vector.$field)),+)
}
}
impl<'a, T> $traitName<$structName<T>> for &'a $structName<T>
where T: Number
{
type Output = $structName<T>;
fn $funcName(self, vector: $structName<T>) -> $structName<T>
{
$structName::new($(self.$field.$funcName(vector.$field)),+)
}
}
impl<'a, 'b, T> $traitName<&'a $structName<T>> for $structName<T>
where T: Number
{
type Output = $structName<T>;
fn $funcName(self, vector: &'a $structName<T>) -> $structName<T>
{
$structName::new($(self.$field.$funcName(vector.$field)),+)
}
}
impl<'a, 'b, T> $traitName<&'a $structName<T>> for &'b $structName<T> impl<'a, 'b, T> $traitName<&'a $structName<T>> for &'b $structName<T>
where T: Number where T: Number
{ {
@ -268,12 +462,17 @@ macro_rules! define_vector
{ {
($structName: ident <$T: ident> {$($field: ident),+}) => ($structName: ident <$T: ident> {$($field: ident),+}) =>
{ {
// Do not add a where clause here or implementing
// generic traits were the generic is different
// will not work properly.
/// This structure was defined with the macro /// This structure was defined with the macro
/// define_vector. /// define_vector.
/// ///
/// Please excuse the lack of comments. /// Please excuse the lack of comments and refer
/// to the trait definitions for comments about
/// the implementation.
#[derive(PartialEq, Eq, Copy, Clone, Hash)] #[derive(PartialEq, Eq, Copy, Clone, Hash)]
pub struct $structName<T> where T: Number pub struct $structName<T>
{ {
$(pub $field: T),+ $(pub $field: T),+
} }
@ -286,6 +485,21 @@ macro_rules! define_vector
} }
} }
// Give this vector a negation function when the
// type stored in it is negatable.
impl<$T> $structName<$T> where T: Copy + Neg<Output = $T>
{
/// Negate this vector in-place (multiply by -1).
///
///```
///
///```
pub fn negate(&mut self)
{
$(self.$field = -self.$field);+
}
}
impl<T> Vector<T> for $structName<T> where T: Number impl<T> Vector<T> for $structName<T> where T: Number
{ {
fn from_value(val: T) -> $structName<T> fn from_value(val: T) -> $structName<T>
@ -293,105 +507,53 @@ macro_rules! define_vector
$structName {$($field: val),+} $structName {$($field: val),+}
} }
fn add_scalar(&self, scalar: T) -> $structName<T> fn add_scalar(&mut self, scalar: T)
{
self + scalar
}
fn sub_scalar(&self, scalar: T) -> $structName<T>
{
self - scalar
}
fn mul_scalar(&self, scalar: T) -> $structName<T>
{
self * scalar
}
fn div_scalar(&self, scalar: T) -> $structName<T>
{
self / scalar
}
fn rem_scalar(&self, scalar: T) -> $structName<T>
{
self % scalar
}
fn add_vector(&self, vector: &$structName<T>) -> $structName<T>
{
self + vector
}
fn sub_vector(&self, vector: &$structName<T>) -> $structName<T>
{
self - vector
}
fn mul_vector(&self, vector: &$structName<T>) -> $structName<T>
{
self * vector
}
fn div_vector(&self, vector: &$structName<T>) -> $structName<T>
{
self / vector
}
fn rem_vector(&self, vector: &$structName<T>) -> $structName<T>
{
self % vector
}
fn add_scalar_self(&mut self, scalar: T)
{ {
*self = &*self + scalar; *self = &*self + scalar;
} }
fn sub_scalar_self(&mut self, scalar: T) fn sub_scalar(&mut self, scalar: T)
{ {
*self = &*self - scalar; *self = &*self - scalar;
} }
fn mul_scalar_self(&mut self, scalar: T) fn mul_scalar(&mut self, scalar: T)
{ {
*self = &*self * scalar; *self = &*self * scalar;
} }
fn div_scalar_self(&mut self, scalar: T) fn div_scalar(&mut self, scalar: T)
{ {
*self = &*self / scalar; *self = &*self / scalar;
} }
fn rem_scalar_self(&mut self, scalar: T) fn rem_scalar(&mut self, scalar: T)
{ {
*self = &*self % scalar; *self = &*self % scalar;
} }
fn add_vector_self(&mut self, vector: &$structName<T>) fn add_vector(&mut self, vector: &$structName<T>)
{ {
*self = &*self + vector; *self = &*self + vector;
} }
fn sub_vector_self(&mut self, vector: &$structName<T>) fn sub_vector(&mut self, vector: &$structName<T>)
{ {
*self = &*self - vector; *self = &*self - vector;
} }
fn mul_vector_self(&mut self, vector: &$structName<T>) fn mul_vector(&mut self, vector: &$structName<T>)
{ {
*self = &*self * vector; *self = &*self * vector;
} }
fn div_vector_self(&mut self, vector: &$structName<T>) fn div_vector(&mut self, vector: &$structName<T>)
{ {
*self = &*self / vector; *self = &*self / vector;
} }
fn rem_vector_self(&mut self, vector: &$structName<T>) fn rem_vector(&mut self, vector: &$structName<T>)
{ {
*self = &*self % vector; *self = &*self % vector;
} }
@ -406,8 +568,42 @@ macro_rules! define_vector
{ {
perform_method_on_components!(mul, {$(self.$field),+}) perform_method_on_components!(mul, {$(self.$field),+})
} }
fn dot(&self, vector: &$structName<T>) -> T
{
self.mul(vector).get_sum()
}
} }
// Implement the Zero and One traits for the Vector.
impl<T> Zero for $structName<T> where T: Number
{
fn zero() -> $structName<T>
{
$structName::from_value(T::zero())
}
}
impl<T> One for $structName<T> where T: Number
{
fn one() -> $structName<T>
{
$structName::identity()
}
}
// Implement the negation operator for the Vector structure.
impl<T> Neg for $structName<T> where T: Neg<Output = T>
{
type Output = $structName<T>;
fn neg(self) -> $structName<T>
{
$structName::<T> {$($field: -self.$field),+}
}
}
// Implement the binary operations for this Vector structure.
binary_operator_impl!(Add::add, $structName {$($field),+}); binary_operator_impl!(Add::add, $structName {$($field),+});
binary_operator_impl!(Sub::sub, $structName {$($field),+}); binary_operator_impl!(Sub::sub, $structName {$($field),+});
binary_operator_impl!(Mul::mul, $structName {$($field),+}); binary_operator_impl!(Mul::mul, $structName {$($field),+});
@ -439,10 +635,17 @@ impl<T> Vector2<T> where T: Number
Vector2::new(T::zero(), T::one()) Vector2::new(T::zero(), T::one())
} }
/// Calculate the perpendicular dot product.
pub fn perpendicular_dot(&self, vector: &Vector2<T>) -> T pub fn perpendicular_dot(&self, vector: &Vector2<T>) -> T
{ {
(self.x * vector.y) - (self.y * vector.x) (self.x * vector.y) - (self.y * vector.x)
} }
/// Adds a z component with the given value to the Vector.
pub fn extend(&self, val: T) -> Vector3<T>
{
Vector3::new(self.x, self.y, val)
}
} }
impl<T> Vector3<T> where T: Number impl<T> Vector3<T> where T: Number
@ -473,6 +676,39 @@ impl<T> Vector3<T> where T: Number
(self.z * vector.x) - (self.x * vector.z), (self.z * vector.x) - (self.x * vector.z),
(self.x * vector.y) - (self.y * vector.x)) (self.x * vector.y) - (self.y * vector.x))
} }
/// Calculate the cross product between this and another Vector
/// and store it in this Vector.
/// The final result will be a Vector perpendicular to both
/// of the input Vectors.
pub fn cross_self(&mut self, vector: &Vector3<T>)
{
*self = self.cross(&vector);
}
/// Adds a w component with the given value to the Vector.
pub fn extend(&self, val: T) -> Vector4<T>
{
Vector4::new(self.x, self.y, self.z, val)
}
/// Discards the z component of the Vector.
pub fn truncate(&self) -> Vector2<T>
{
self.truncate_component(2)
}
/// Discards the component at the given index from the Vector.
pub fn truncate_component(&self, index: isize) -> Vector2<T>
{
match index
{
0 => Vector2::new(self.y, self.z),
1 => Vector2::new(self.x, self.z),
2 => Vector2::new(self.x, self.y),
_ => panic!("Component index {:?} is out of range.", index)
}
}
} }
impl<T> Vector4<T> where T: Number impl<T> Vector4<T> where T: Number
@ -500,4 +736,51 @@ impl<T> Vector4<T> where T: Number
{ {
Vector4::new(T::zero(), T::zero(), T::zero(), T::one()) Vector4::new(T::zero(), T::zero(), T::zero(), T::one())
} }
/// Discards the w component of the Vector.
pub fn truncate(&self) -> Vector3<T>
{
self.truncate_component(3)
}
/// Discards the component at the given index from the Vector.
pub fn truncate_component(&self, index: isize) -> Vector3<T>
{
match index
{
0 => Vector3::new(self.y, self.z, self.w),
1 => Vector3::new(self.x, self.z, self.w),
2 => Vector3::new(self.x, self.y, self.w),
3 => Vector3::new(self.x, self.y, self.z),
_ => panic!("Component index {:?} is out of range.", index)
}
}
}
// Implement the angle specific portion of the EuclideanVector.
impl<T> EuclideanVector<T> for Vector2<T> where T: Real
{
fn angle(&self, vector: &Vector2<T>) -> T
{
//unimplemented!();
atan2(self.perpendicular_dot(vector), self.dot(vector))
}
}
impl<T> EuclideanVector<T> for Vector3<T> where T: Real
{
fn angle(&self, vector: &Vector3<T>) -> T
{
//unimplemented!();
atan2(self.cross(vector).get_length(), self.dot(vector))
}
}
impl<T> EuclideanVector<T> for Vector4<T> where T: Real
{
fn angle(&self, vector: &Vector4<T>) -> T
{
//unimplemented!();
acos(self.dot(vector) / (self.get_length() * vector.get_length()))
}
} }

97
tests/constants.rs Normal file
View File

@ -0,0 +1,97 @@
extern crate sigils;
use std::{f32, f64};
use sigils::Constants;
#[test]
fn constant_check_f32()
{
let val: f32 = Constants::SQRT_2;
assert_eq!(val, f32::consts::SQRT_2);
let val: f32 = Constants::SQRT_3;
assert_eq!(val, 1.73205080756887729352f32);
let val: f32 = Constants::INVERSE_SQRT_2;
assert_eq!(val, 1.0f32 / f32::consts::SQRT_2);
let val: f32 = Constants::INVERSE_SQRT_3;
assert_eq!(val, 1.0f32 / 1.73205080756887729352f32);
let val: f32 = Constants::E;
assert_eq!(val, f32::consts::E);
let val: f32 = Constants::LOG2_E;
assert_eq!(val, f32::consts::LOG2_E);
let val: f32 = Constants::LOG10_E;
assert_eq!(val, f32::consts::LOG10_E);
let val: f32 = Constants::LOGE_2;
assert_eq!(val, 2f32.ln());
let val: f32 = Constants::LOGE_10;
assert_eq!(val, 10f32.ln());
let val: f32 = Constants::TWO_PI;
assert_eq!(val, 2f32 * f32::consts::PI);
let val: f32 = Constants::PI;
assert_eq!(val, f32::consts::PI);
let val: f32 = Constants::HALF_PI;
assert_eq!(val, f32::consts::PI / 2f32);
let val: f32 = Constants::THIRD_PI;
assert_eq!(val, f32::consts::PI / 3f32);
let val: f32 = Constants::QUARTER_PI;
assert_eq!(val, f32::consts::PI / 4f32);
let val: f32 = Constants::SIXTH_PI;
assert_eq!(val, f32::consts::PI / 6f32);
let val: f32 = Constants::EIGHTH_PI;
assert_eq!(val, f32::consts::PI / 8f32);
let val: f32 = Constants::INVERSE_PI;
assert_eq!(val, 1.0f32 / f32::consts::PI);
let val: f32 = Constants::TWO_INVERSE_PI;
assert_eq!(val, 2.0f32 / f32::consts::PI);
let val: f32 = Constants::TWO_INVERSE_SQRT_PI;
assert_eq!(val, 2.0f32 / (f32::consts::PI).sqrt());
}
#[test]
fn constant_check_f64()
{
let val: f64 = Constants::SQRT_2;
assert_eq!(val, f64::consts::SQRT_2);
let val: f64 = Constants::SQRT_3;
assert_eq!(val, 1.73205080756887729352f64);
let val: f64 = Constants::INVERSE_SQRT_2;
assert_eq!(val, 1.0f64 / f64::consts::SQRT_2);
let val: f64 = Constants::INVERSE_SQRT_3;
assert_eq!(val, 1.0f64 / 1.73205080756887729352f64);
let val: f64 = Constants::E;
assert_eq!(val, f64::consts::E);
let val: f64 = Constants::LOG2_E;
assert_eq!(val, f64::consts::LOG2_E);
let val: f64 = Constants::LOG10_E;
assert_eq!(val, f64::consts::LOG10_E);
let val: f64 = Constants::LOGE_2;
assert_eq!(val, 2f64.ln());
let val: f64 = Constants::LOGE_10;
assert_eq!(val, 10f64.ln());
let val: f64 = Constants::TWO_PI;
assert_eq!(val, 2f64 * f64::consts::PI);
let val: f64 = Constants::PI;
assert_eq!(val, f64::consts::PI);
let val: f64 = Constants::HALF_PI;
assert_eq!(val, f64::consts::PI / 2f64);
let val: f64 = Constants::THIRD_PI;
assert_eq!(val, f64::consts::PI / 3f64);
let val: f64 = Constants::QUARTER_PI;
assert_eq!(val, f64::consts::PI / 4f64);
let val: f64 = Constants::SIXTH_PI;
assert_eq!(val, f64::consts::PI / 6f64);
let val: f64 = Constants::EIGHTH_PI;
assert_eq!(val, f64::consts::PI / 8f64);
let val: f64 = Constants::INVERSE_PI;
assert_eq!(val, 1.0f64 / f64::consts::PI);
let val: f64 = Constants::TWO_INVERSE_PI;
assert_eq!(val, 2.0f64 / f64::consts::PI);
let val: f64 = Constants::TWO_INVERSE_SQRT_PI;
assert_eq!(val, 2.0f64 / (f64::consts::PI).sqrt());
}

View File

@ -1,3 +1,5 @@
extern crate sigils; extern crate sigils;
mod constants;
mod vector; mod vector;

View File

@ -1,5 +1,6 @@
extern crate sigils; extern crate sigils;
use std::ops::{Add, Sub, Mul, Div, Rem};
use sigils::vector::*; use sigils::vector::*;
@ -10,3 +11,348 @@ fn vector_creation()
assert_eq!(v.x, 1.0f32); assert_eq!(v.x, 1.0f32);
} }
#[test]
fn vector_add()
{
let v: Vector3<f32> = Vector3::<f32>::from_value(1.0f32);
let v_two: Vector3<f32> = Vector3::<f32>::from_value(4.0f32);
let scalar: f32 = 4.0f32;
let v_three = v.add(&v_two);
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = v.add(v_two);
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = v + &v_two;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = v + v_two;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = &v + &v_two;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = &v + v_two;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = &v + 4.0f32;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = v + 4.0f32;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = &v + scalar;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = v + scalar;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = &v + &scalar;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = v + &scalar;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
}
#[test]
fn vector_sub()
{
let v: Vector3<f32> = Vector3::<f32>::from_value(9.0f32);
let v_two: Vector3<f32> = Vector3::<f32>::from_value(4.0f32);
let scalar: f32 = 4.0f32;
let v_three = v.sub(&v_two);
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = v.sub(v_two);
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = v - &v_two;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = v - v_two;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = &v - &v_two;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = &v - v_two;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = &v - 4.0f32;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = v - 4.0f32;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = &v - scalar;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = v - scalar;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = &v - &scalar;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
let v_three = v - &scalar;
assert_eq!(v_three.x, 5.0f32);
assert_eq!(v_three.y, 5.0f32);
assert_eq!(v_three.z, 5.0f32);
}
#[test]
fn vector_mul()
{
let v: Vector3<f32> = Vector3::<f32>::from_value(3.0f32);
let v_two: Vector3<f32> = Vector3::<f32>::from_value(5.0f32);
let scalar: f32 = 5.0f32;
let v_three = v.mul(&v_two);
assert_eq!(v_three.x, 15.0f32);
assert_eq!(v_three.y, 15.0f32);
assert_eq!(v_three.z, 15.0f32);
let v_three = v.mul(v_two);
assert_eq!(v_three.x, 15.0f32);
assert_eq!(v_three.y, 15.0f32);
assert_eq!(v_three.z, 15.0f32);
let v_three = v * &v_two;
assert_eq!(v_three.x, 15.0f32);
assert_eq!(v_three.y, 15.0f32);
assert_eq!(v_three.z, 15.0f32);
let v_three = v * v_two;
assert_eq!(v_three.x, 15.0f32);
assert_eq!(v_three.y, 15.0f32);
assert_eq!(v_three.z, 15.0f32);
let v_three = &v * &v_two;
assert_eq!(v_three.x, 15.0f32);
assert_eq!(v_three.y, 15.0f32);
assert_eq!(v_three.z, 15.0f32);
let v_three = &v * v_two;
assert_eq!(v_three.x, 15.0f32);
assert_eq!(v_three.y, 15.0f32);
assert_eq!(v_three.z, 15.0f32);
let v_three = &v * 5.0f32;
assert_eq!(v_three.x, 15.0f32);
assert_eq!(v_three.y, 15.0f32);
assert_eq!(v_three.z, 15.0f32);
let v_three = v * 5.0f32;
assert_eq!(v_three.x, 15.0f32);
assert_eq!(v_three.y, 15.0f32);
assert_eq!(v_three.z, 15.0f32);
let v_three = &v * scalar;
assert_eq!(v_three.x, 15.0f32);
assert_eq!(v_three.y, 15.0f32);
assert_eq!(v_three.z, 15.0f32);
let v_three = v * scalar;
assert_eq!(v_three.x, 15.0f32);
assert_eq!(v_three.y, 15.0f32);
assert_eq!(v_three.z, 15.0f32);
let v_three = &v * &scalar;
assert_eq!(v_three.x, 15.0f32);
assert_eq!(v_three.y, 15.0f32);
assert_eq!(v_three.z, 15.0f32);
let v_three = v * &scalar;
assert_eq!(v_three.x, 15.0f32);
assert_eq!(v_three.y, 15.0f32);
assert_eq!(v_three.z, 15.0f32);
}
#[test]
fn vector_div()
{
let v: Vector3<f32> = Vector3::<f32>::from_value(15.0f32);
let v_two: Vector3<f32> = Vector3::<f32>::from_value(5.0f32);
let scalar: f32 = 5.0f32;
let v_three = v.div(&v_two);
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = v.div(v_two);
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = v / &v_two;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = v / v_two;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = &v / &v_two;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = &v / v_two;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = &v / 5.0f32;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = v / 5.0f32;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = &v / scalar;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = v / scalar;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = &v / &scalar;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = v / &scalar;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
}
#[test]
fn vector_rem()
{
let v: Vector3<f32> = Vector3::<f32>::from_value(15.0f32);
let v_two: Vector3<f32> = Vector3::<f32>::from_value(6.0f32);
let scalar: f32 = 6.0f32;
let v_three = v.rem(&v_two);
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = v.rem(v_two);
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = v % &v_two;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = v % v_two;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = &v % &v_two;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = &v % v_two;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = &v % 6.0f32;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = v % 6.0f32;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = &v % scalar;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = v % scalar;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = &v % &scalar;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
let v_three = v % &scalar;
assert_eq!(v_three.x, 3.0f32);
assert_eq!(v_three.y, 3.0f32);
assert_eq!(v_three.z, 3.0f32);
}