Merge #495
495: Mat3 constructors enhancement r=kvark a=AndreaCatania The reason of this PR is because I need to transform thing in a 2d plane, and these functions are really handy. - Added to the Mat3 the possibility to be constructed from a translation vector, similarly to the Mat4. - Added unit tests. Co-authored-by: Andrea Catania <info@andreacatania.com>
This commit is contained in:
commit
50a345b7c4
25 changed files with 840 additions and 444 deletions
|
@ -28,9 +28,7 @@ macro_rules! bench_binop {
|
|||
bh.iter(|| {
|
||||
i = (i + 1) & (LEN - 1);
|
||||
|
||||
unsafe {
|
||||
test::black_box(elems1.get_unchecked(i).$binop(*elems2.get_unchecked(i)))
|
||||
}
|
||||
unsafe { test::black_box(elems1.get_unchecked(i).$binop(*elems2.get_unchecked(i))) }
|
||||
})
|
||||
}
|
||||
};
|
||||
|
@ -50,9 +48,7 @@ macro_rules! bench_unop {
|
|||
bh.iter(|| {
|
||||
i = (i + 1) & (LEN - 1);
|
||||
|
||||
unsafe {
|
||||
test::black_box(elems.get_unchecked_mut(i).$unop())
|
||||
}
|
||||
unsafe { test::black_box(elems.get_unchecked_mut(i).$unop()) }
|
||||
})
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,9 +20,9 @@ extern crate cgmath;
|
|||
extern crate rand;
|
||||
extern crate test;
|
||||
|
||||
use rand::{IsaacRng, Rng, FromEntropy};
|
||||
use test::Bencher;
|
||||
use cgmath::*;
|
||||
use rand::{FromEntropy, IsaacRng, Rng};
|
||||
use test::Bencher;
|
||||
|
||||
#[path = "common/macros.rs"]
|
||||
#[macro_use]
|
||||
|
|
|
@ -20,7 +20,7 @@ extern crate cgmath;
|
|||
extern crate rand;
|
||||
extern crate test;
|
||||
|
||||
use rand::{IsaacRng, Rng, FromEntropy};
|
||||
use rand::{FromEntropy, IsaacRng, Rng};
|
||||
use std::ops::*;
|
||||
use test::Bencher;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ extern crate cgmath;
|
|||
extern crate rand;
|
||||
extern crate test;
|
||||
|
||||
use rand::{IsaacRng, Rng, FromEntropy};
|
||||
use rand::{FromEntropy, IsaacRng, Rng};
|
||||
use std::ops::*;
|
||||
use test::Bencher;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ extern crate cgmath;
|
|||
extern crate rand;
|
||||
extern crate test;
|
||||
|
||||
use rand::{IsaacRng, Rng, FromEntropy};
|
||||
use rand::{FromEntropy, IsaacRng, Rng};
|
||||
use std::ops::*;
|
||||
use test::Bencher;
|
||||
|
||||
|
|
29
build.rs
29
build.rs
|
@ -1,7 +1,7 @@
|
|||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::env;
|
||||
use std::string::String;
|
||||
|
||||
/// Generate the name of the swizzle function and what it returns.
|
||||
|
@ -11,14 +11,18 @@ fn gen_swizzle_nth<'a>(variables: &'a str, mut i: usize, upto: usize) -> Option<
|
|||
debug_assert!(i > 0); // zeroth permutation is empty
|
||||
let mut swizzle_impl = String::new();
|
||||
let mut swizzle = String::new();
|
||||
let n = variables.len()+1;
|
||||
let n = variables.len() + 1;
|
||||
for _ in 0..upto {
|
||||
if i == 0 { break; }
|
||||
if i % n == 0 { return None; }
|
||||
let c = variables.as_bytes()[i%n - 1] as char;
|
||||
if i == 0 {
|
||||
break;
|
||||
}
|
||||
if i % n == 0 {
|
||||
return None;
|
||||
}
|
||||
let c = variables.as_bytes()[i % n - 1] as char;
|
||||
swizzle.push(c);
|
||||
swizzle_impl.push_str(&format!("self.{}, ", c));
|
||||
i = i/n;
|
||||
i = i / n;
|
||||
}
|
||||
Some((swizzle, swizzle_impl))
|
||||
}
|
||||
|
@ -31,15 +35,16 @@ fn gen_swizzle_nth<'a>(variables: &'a str, mut i: usize, upto: usize) -> Option<
|
|||
#[cfg(feature = "swizzle")]
|
||||
fn gen_swizzle_functions(variables: &'static str, upto: usize) -> String {
|
||||
let mut result = String::new();
|
||||
let nn = (variables.len()+1).pow(upto as u32);
|
||||
let nn = (variables.len() + 1).pow(upto as u32);
|
||||
for i in 1..nn {
|
||||
if let Some((swizzle_name, swizzle_impl)) = gen_swizzle_nth(variables, i, upto) {
|
||||
let dim = format!("{}", swizzle_name.len());
|
||||
result.push_str(
|
||||
&format!("
|
||||
result.push_str(&format!(
|
||||
"
|
||||
/// Swizzle operator that creates a new type with dimension {2} from variables `{0}`.
|
||||
#[inline] pub fn {0}(&self) -> $vector_type{2}<$S> {{ $vector_type{2}::new({1}) }}\n",
|
||||
swizzle_name, swizzle_impl, dim));
|
||||
swizzle_name, swizzle_impl, dim
|
||||
));
|
||||
}
|
||||
}
|
||||
result
|
||||
|
@ -50,7 +55,6 @@ fn gen_swizzle_functions(_: &'static str, _: usize) -> String {
|
|||
String::new()
|
||||
}
|
||||
|
||||
|
||||
/// This script generates the macro for building swizzle operators for multidimensional
|
||||
/// vectors and points. This macro is included in macros.rs
|
||||
fn main() {
|
||||
|
@ -92,5 +96,6 @@ macro_rules! impl_swizzle_functions {{
|
|||
xyzw4 = gen_swizzle_functions("xyzw", 4));
|
||||
let mut f = File::create(swizzle_file_path)
|
||||
.expect("Unable to create file that defines the swizzle operator macro.");
|
||||
f.write_all(data.as_bytes()).expect("Unable to write swizzle operator macro.");
|
||||
f.write_all(data.as_bytes())
|
||||
.expect("Unable to write swizzle operator macro.");
|
||||
}
|
||||
|
|
|
@ -15,17 +15,17 @@
|
|||
|
||||
//! Angle units for type-safe, self-documenting code.
|
||||
|
||||
use std::fmt;
|
||||
use std::f64;
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
use std::ops::*;
|
||||
|
||||
use num_traits::{cast, Bounded};
|
||||
#[cfg(feature = "rand")]
|
||||
use rand::{
|
||||
distributions::{uniform::SampleUniform, Distribution, Standard},
|
||||
Rng,
|
||||
distributions::{Distribution, Standard, uniform::SampleUniform},
|
||||
};
|
||||
use num_traits::{cast, Bounded};
|
||||
|
||||
use structure::*;
|
||||
|
||||
|
|
12
src/euler.rs
12
src/euler.rs
|
@ -13,21 +13,21 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use num_traits::cast;
|
||||
#[cfg(feature = "rand")]
|
||||
use rand::{
|
||||
Rng,
|
||||
distributions::{Distribution, Standard},
|
||||
Rng,
|
||||
};
|
||||
use num_traits::cast;
|
||||
|
||||
use structure::*;
|
||||
|
||||
use angle::Rad;
|
||||
use approx;
|
||||
use quaternion::Quaternion;
|
||||
#[cfg(feature = "mint")]
|
||||
use mint;
|
||||
use num::BaseFloat;
|
||||
use quaternion::Quaternion;
|
||||
|
||||
/// A set of [Euler angles] representing a rotation in three-dimensional space.
|
||||
///
|
||||
|
@ -191,8 +191,10 @@ impl<A: Angle> approx::UlpsEq for Euler<A> {
|
|||
|
||||
#[cfg(feature = "rand")]
|
||||
impl<A> Distribution<Euler<A>> for Standard
|
||||
where Standard: Distribution<A>,
|
||||
A: Angle {
|
||||
where
|
||||
Standard: Distribution<A>,
|
||||
A: Angle,
|
||||
{
|
||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Euler<A> {
|
||||
Euler {
|
||||
x: rng.gen(),
|
||||
|
|
|
@ -58,9 +58,9 @@ extern crate approx;
|
|||
#[cfg(feature = "mint")]
|
||||
pub extern crate mint;
|
||||
|
||||
pub extern crate num_traits;
|
||||
#[cfg(feature = "rand")]
|
||||
extern crate rand;
|
||||
pub extern crate num_traits;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[macro_use]
|
||||
|
@ -77,11 +77,11 @@ pub use structure::*;
|
|||
|
||||
pub use matrix::{Matrix2, Matrix3, Matrix4};
|
||||
pub use quaternion::Quaternion;
|
||||
pub use vector::{dot, Vector1, Vector2, Vector3, Vector4, vec1, vec2, vec3, vec4};
|
||||
pub use vector::{dot, vec1, vec2, vec3, vec4, Vector1, Vector2, Vector3, Vector4};
|
||||
|
||||
pub use angle::{Deg, Rad};
|
||||
pub use euler::Euler;
|
||||
pub use point::{Point1, Point2, Point3, point1, point2, point3};
|
||||
pub use point::{point1, point2, point3, Point1, Point2, Point3};
|
||||
pub use rotation::*;
|
||||
pub use transform::*;
|
||||
|
||||
|
|
|
@ -139,14 +139,30 @@ macro_rules! impl_assignment_operator {
|
|||
}
|
||||
|
||||
macro_rules! fold_array {
|
||||
(&$method:ident, { $x:expr }) => { *$x };
|
||||
(&$method:ident, { $x:expr, $y:expr }) => { $x.$method(&$y) };
|
||||
(&$method:ident, { $x:expr, $y:expr, $z:expr }) => { $x.$method(&$y).$method(&$z) };
|
||||
(&$method:ident, { $x:expr, $y:expr, $z:expr, $w:expr }) => { $x.$method(&$y).$method(&$z).$method(&$w) };
|
||||
($method:ident, { $x:expr }) => { $x };
|
||||
($method:ident, { $x:expr, $y:expr }) => { $x.$method($y) };
|
||||
($method:ident, { $x:expr, $y:expr, $z:expr }) => { $x.$method($y).$method($z) };
|
||||
($method:ident, { $x:expr, $y:expr, $z:expr, $w:expr }) => { $x.$method($y).$method($z).$method($w) };
|
||||
(&$method:ident, { $x:expr }) => {
|
||||
*$x
|
||||
};
|
||||
(&$method:ident, { $x:expr, $y:expr }) => {
|
||||
$x.$method(&$y)
|
||||
};
|
||||
(&$method:ident, { $x:expr, $y:expr, $z:expr }) => {
|
||||
$x.$method(&$y).$method(&$z)
|
||||
};
|
||||
(&$method:ident, { $x:expr, $y:expr, $z:expr, $w:expr }) => {
|
||||
$x.$method(&$y).$method(&$z).$method(&$w)
|
||||
};
|
||||
($method:ident, { $x:expr }) => {
|
||||
$x
|
||||
};
|
||||
($method:ident, { $x:expr, $y:expr }) => {
|
||||
$x.$method($y)
|
||||
};
|
||||
($method:ident, { $x:expr, $y:expr, $z:expr }) => {
|
||||
$x.$method($y).$method($z)
|
||||
};
|
||||
($method:ident, { $x:expr, $y:expr, $z:expr, $w:expr }) => {
|
||||
$x.$method($y).$method($z).$method($w)
|
||||
};
|
||||
}
|
||||
|
||||
/// Generate array conversion implementations for a compound array type
|
||||
|
@ -252,17 +268,19 @@ macro_rules! impl_index_operators {
|
|||
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: $I) -> &'a $Output {
|
||||
let v: &[$S; $n] = self.as_ref(); &v[i]
|
||||
let v: &[$S; $n] = self.as_ref();
|
||||
&v[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S> IndexMut<$I> for $VectorN<$S> {
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, i: $I) -> &'a mut $Output {
|
||||
let v: &mut [$S; $n] = self.as_mut(); &mut v[i]
|
||||
}
|
||||
let v: &mut [$S; $n] = self.as_mut();
|
||||
&mut v[i]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Generates a binary operator implementation for the permutations of by-ref and by-val, for simd
|
||||
|
@ -272,11 +290,11 @@ macro_rules! impl_operator_simd {
|
|||
([$Simd:ident]; $Op:ident for $Lhs:ty {
|
||||
fn $op:ident($x:ident) -> $Output:ty { $body:expr }
|
||||
}) => {
|
||||
|
||||
impl $Op for $Lhs {
|
||||
#[inline]
|
||||
fn $op(self) -> $Output {
|
||||
let $x: $Simd = self.into(); $body
|
||||
let $x: $Simd = self.into();
|
||||
$body
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -287,15 +305,16 @@ macro_rules! impl_operator_simd {
|
|||
impl $Op<$Rhs> for $Lhs {
|
||||
#[inline]
|
||||
fn $op(self, other: $Rhs) -> $Output {
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = (self.into(), $Simd::splat(other)); $body
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = (self.into(), $Simd::splat(other));
|
||||
$body
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a> $Op<$Rhs> for &'a $Lhs {
|
||||
#[inline]
|
||||
fn $op(self, other: $Rhs) -> $Output {
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = ((*self).into(), $Simd::splat(other)); $body
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = ((*self).into(), $Simd::splat(other));
|
||||
$body
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -304,33 +323,35 @@ macro_rules! impl_operator_simd {
|
|||
([$Simd:ident]; $Op:ident<$Rhs:ty> for $Lhs:ty {
|
||||
fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
|
||||
}) => {
|
||||
|
||||
impl $Op<$Rhs> for $Lhs {
|
||||
#[inline]
|
||||
fn $op(self, other: $Rhs) -> $Output {
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = (self.into(), other.into()); $body
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = (self.into(), other.into());
|
||||
$body
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a> $Op<&'a $Rhs> for $Lhs {
|
||||
#[inline]
|
||||
fn $op(self, other: &'a $Rhs) -> $Output {
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = (self.into(), (*other).into()); $body
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = (self.into(), (*other).into());
|
||||
$body
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> $Op<$Rhs> for &'a $Lhs {
|
||||
#[inline]
|
||||
fn $op(self, other: $Rhs) -> $Output {
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = ((*self).into(), other.into()); $body
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = ((*self).into(), other.into());
|
||||
$body
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> $Op<&'a $Rhs> for &'b $Lhs {
|
||||
#[inline]
|
||||
fn $op(self, other: &'a $Rhs) -> $Output {
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = ((*self).into(), (*other).into()); $body
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = ((*self).into(), (*other).into());
|
||||
$body
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -342,14 +363,16 @@ macro_rules! impl_operator_simd {
|
|||
impl $Op<$Rhs> for $Lhs {
|
||||
#[inline]
|
||||
fn $op(self, other: $Rhs) -> $Output {
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = ($Simd::splat(self), other.into()); $body
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = ($Simd::splat(self), other.into());
|
||||
$body
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> $Op<&'a $Rhs> for $Lhs {
|
||||
#[inline]
|
||||
fn $op(self, other: &'a $Rhs) -> $Output {
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = ($Simd::splat(self), (*other).into()); $body
|
||||
let ($lhs, $rhs): ($Simd, $Simd) = ($Simd::splat(self), (*other).into());
|
||||
$body
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
115
src/matrix.rs
115
src/matrix.rs
|
@ -13,12 +13,12 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use num_traits::{cast, NumCast};
|
||||
#[cfg(feature = "rand")]
|
||||
use rand::{
|
||||
distributions::{Distribution, Standard},
|
||||
Rng,
|
||||
distributions::{Standard, Distribution},
|
||||
};
|
||||
use num_traits::{cast, NumCast};
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
use std::mem;
|
||||
|
@ -159,6 +159,34 @@ impl<S> Matrix3<S> {
|
|||
}
|
||||
|
||||
impl<S: BaseFloat> Matrix3<S> {
|
||||
/// Create a homogeneous transformation matrix from a translation vector.
|
||||
#[inline]
|
||||
pub fn from_translation(v: Vector2<S>) -> Matrix3<S> {
|
||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||
Matrix3::new(
|
||||
S::one(), S::zero(), S::zero(),
|
||||
S::zero(), S::one(), S::zero(),
|
||||
v.x, v.y, S::one(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a homogeneous transformation matrix from a scale value.
|
||||
#[inline]
|
||||
pub fn from_scale(value: S) -> Matrix3<S> {
|
||||
Matrix3::from_nonuniform_scale(value, value)
|
||||
}
|
||||
|
||||
/// Create a homogeneous transformation matrix from a set of scale values.
|
||||
#[inline]
|
||||
pub fn from_nonuniform_scale(x: S, y: S) -> Matrix3<S> {
|
||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||
Matrix3::new(
|
||||
x, S::zero(), S::zero(),
|
||||
S::zero(), y, S::zero(),
|
||||
S::zero(), S::zero(), S::one(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a rotation matrix that will cause a vector to point at
|
||||
/// `dir`, using `up` for orientation.
|
||||
pub fn look_at(dir: Vector3<S>, up: Vector3<S>) -> Matrix3<S> {
|
||||
|
@ -257,7 +285,12 @@ impl<S> Matrix4<S> {
|
|||
|
||||
/// Create a new matrix, providing columns.
|
||||
#[inline]
|
||||
pub const fn from_cols(c0: Vector4<S>, c1: Vector4<S>, c2: Vector4<S>, c3: Vector4<S>) -> Matrix4<S> {
|
||||
pub const fn from_cols(
|
||||
c0: Vector4<S>,
|
||||
c1: Vector4<S>,
|
||||
c2: Vector4<S>,
|
||||
c3: Vector4<S>,
|
||||
) -> Matrix4<S> {
|
||||
Matrix4 {
|
||||
x: c0,
|
||||
y: c1,
|
||||
|
@ -668,21 +701,28 @@ impl<S: BaseFloat> SquareMatrix for Matrix3<S> {
|
|||
self[1].cross(self[2]) / det,
|
||||
self[2].cross(self[0]) / det,
|
||||
self[0].cross(self[1]) / det,
|
||||
).transpose(),
|
||||
)
|
||||
.transpose(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_diagonal(&self) -> bool {
|
||||
ulps_eq!(self[0][1], &S::zero()) && ulps_eq!(self[0][2], &S::zero())
|
||||
&& ulps_eq!(self[1][0], &S::zero()) && ulps_eq!(self[1][2], &S::zero())
|
||||
&& ulps_eq!(self[2][0], &S::zero()) && ulps_eq!(self[2][1], &S::zero())
|
||||
ulps_eq!(self[0][1], &S::zero())
|
||||
&& ulps_eq!(self[0][2], &S::zero())
|
||||
&& ulps_eq!(self[1][0], &S::zero())
|
||||
&& ulps_eq!(self[1][2], &S::zero())
|
||||
&& ulps_eq!(self[2][0], &S::zero())
|
||||
&& ulps_eq!(self[2][1], &S::zero())
|
||||
}
|
||||
|
||||
fn is_symmetric(&self) -> bool {
|
||||
ulps_eq!(self[0][1], &self[1][0]) && ulps_eq!(self[0][2], &self[2][0])
|
||||
&& ulps_eq!(self[1][0], &self[0][1]) && ulps_eq!(self[1][2], &self[2][1])
|
||||
&& ulps_eq!(self[2][0], &self[0][2]) && ulps_eq!(self[2][1], &self[1][2])
|
||||
ulps_eq!(self[0][1], &self[1][0])
|
||||
&& ulps_eq!(self[0][2], &self[2][0])
|
||||
&& ulps_eq!(self[1][0], &self[0][1])
|
||||
&& ulps_eq!(self[1][2], &self[2][1])
|
||||
&& ulps_eq!(self[2][0], &self[0][2])
|
||||
&& ulps_eq!(self[2][1], &self[1][2])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -835,21 +875,33 @@ impl<S: BaseFloat> SquareMatrix for Matrix4<S> {
|
|||
}
|
||||
|
||||
fn is_diagonal(&self) -> bool {
|
||||
ulps_eq!(self[0][1], &S::zero()) && ulps_eq!(self[0][2], &S::zero())
|
||||
&& ulps_eq!(self[0][3], &S::zero()) && ulps_eq!(self[1][0], &S::zero())
|
||||
&& ulps_eq!(self[1][2], &S::zero()) && ulps_eq!(self[1][3], &S::zero())
|
||||
&& ulps_eq!(self[2][0], &S::zero()) && ulps_eq!(self[2][1], &S::zero())
|
||||
&& ulps_eq!(self[2][3], &S::zero()) && ulps_eq!(self[3][0], &S::zero())
|
||||
&& ulps_eq!(self[3][1], &S::zero()) && ulps_eq!(self[3][2], &S::zero())
|
||||
ulps_eq!(self[0][1], &S::zero())
|
||||
&& ulps_eq!(self[0][2], &S::zero())
|
||||
&& ulps_eq!(self[0][3], &S::zero())
|
||||
&& ulps_eq!(self[1][0], &S::zero())
|
||||
&& ulps_eq!(self[1][2], &S::zero())
|
||||
&& ulps_eq!(self[1][3], &S::zero())
|
||||
&& ulps_eq!(self[2][0], &S::zero())
|
||||
&& ulps_eq!(self[2][1], &S::zero())
|
||||
&& ulps_eq!(self[2][3], &S::zero())
|
||||
&& ulps_eq!(self[3][0], &S::zero())
|
||||
&& ulps_eq!(self[3][1], &S::zero())
|
||||
&& ulps_eq!(self[3][2], &S::zero())
|
||||
}
|
||||
|
||||
fn is_symmetric(&self) -> bool {
|
||||
ulps_eq!(self[0][1], &self[1][0]) && ulps_eq!(self[0][2], &self[2][0])
|
||||
&& ulps_eq!(self[0][3], &self[3][0]) && ulps_eq!(self[1][0], &self[0][1])
|
||||
&& ulps_eq!(self[1][2], &self[2][1]) && ulps_eq!(self[1][3], &self[3][1])
|
||||
&& ulps_eq!(self[2][0], &self[0][2]) && ulps_eq!(self[2][1], &self[1][2])
|
||||
&& ulps_eq!(self[2][3], &self[3][2]) && ulps_eq!(self[3][0], &self[0][3])
|
||||
&& ulps_eq!(self[3][1], &self[1][3]) && ulps_eq!(self[3][2], &self[2][3])
|
||||
ulps_eq!(self[0][1], &self[1][0])
|
||||
&& ulps_eq!(self[0][2], &self[2][0])
|
||||
&& ulps_eq!(self[0][3], &self[3][0])
|
||||
&& ulps_eq!(self[1][0], &self[0][1])
|
||||
&& ulps_eq!(self[1][2], &self[2][1])
|
||||
&& ulps_eq!(self[1][3], &self[3][1])
|
||||
&& ulps_eq!(self[2][0], &self[0][2])
|
||||
&& ulps_eq!(self[2][1], &self[1][2])
|
||||
&& ulps_eq!(self[2][3], &self[3][2])
|
||||
&& ulps_eq!(self[3][0], &self[0][3])
|
||||
&& ulps_eq!(self[3][1], &self[1][3])
|
||||
&& ulps_eq!(self[3][2], &self[2][3])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1266,7 +1318,7 @@ macro_rules! index_operators {
|
|||
From::from(&mut v[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
index_operators!(Matrix2<S>, 2, Vector2<S>, usize);
|
||||
|
@ -1553,9 +1605,10 @@ impl<S: fmt::Debug> fmt::Debug for Matrix4<S> {
|
|||
|
||||
#[cfg(feature = "rand")]
|
||||
impl<S> Distribution<Matrix2<S>> for Standard
|
||||
where
|
||||
where
|
||||
Standard: Distribution<Vector2<S>>,
|
||||
S: BaseFloat {
|
||||
S: BaseFloat,
|
||||
{
|
||||
#[inline]
|
||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Matrix2<S> {
|
||||
Matrix2 {
|
||||
|
@ -1567,8 +1620,10 @@ impl<S> Distribution<Matrix2<S>> for Standard
|
|||
|
||||
#[cfg(feature = "rand")]
|
||||
impl<S> Distribution<Matrix3<S>> for Standard
|
||||
where Standard: Distribution<Vector3<S>>,
|
||||
S: BaseFloat {
|
||||
where
|
||||
Standard: Distribution<Vector3<S>>,
|
||||
S: BaseFloat,
|
||||
{
|
||||
#[inline]
|
||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Matrix3<S> {
|
||||
Matrix3 {
|
||||
|
@ -1581,8 +1636,10 @@ impl<S> Distribution<Matrix3<S>> for Standard
|
|||
|
||||
#[cfg(feature = "rand")]
|
||||
impl<S> Distribution<Matrix4<S>> for Standard
|
||||
where Standard: Distribution<Vector4<S>>,
|
||||
S: BaseFloat {
|
||||
where
|
||||
Standard: Distribution<Vector4<S>>,
|
||||
S: BaseFloat,
|
||||
{
|
||||
#[inline]
|
||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Matrix4<S> {
|
||||
Matrix4 {
|
||||
|
|
10
src/num.rs
10
src/num.rs
|
@ -36,8 +36,7 @@ pub trait BaseNum:
|
|||
{
|
||||
}
|
||||
|
||||
impl<T> BaseNum for T
|
||||
where
|
||||
impl<T> BaseNum for T where
|
||||
T: Copy
|
||||
+ Clone
|
||||
+ fmt::Debug
|
||||
|
@ -48,7 +47,7 @@ where
|
|||
+ SubAssign
|
||||
+ MulAssign
|
||||
+ DivAssign
|
||||
+ RemAssign,
|
||||
+ RemAssign
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -62,12 +61,11 @@ pub trait BaseFloat:
|
|||
{
|
||||
}
|
||||
|
||||
impl<T> BaseFloat for T
|
||||
where
|
||||
impl<T> BaseFloat for T where
|
||||
T: BaseNum
|
||||
+ Float
|
||||
+ approx::AbsDiffEq<Epsilon = Self>
|
||||
+ approx::RelativeEq<Epsilon = Self>
|
||||
+ approx::UlpsEq<Epsilon = Self>,
|
||||
+ approx::UlpsEq<Epsilon = Self>
|
||||
{
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use num_traits::Zero;
|
||||
use num_traits::cast;
|
||||
use num_traits::Zero;
|
||||
|
||||
use structure::Angle;
|
||||
|
||||
|
@ -38,7 +38,8 @@ pub fn perspective<S: BaseFloat, A: Into<Rad<S>>>(
|
|||
aspect: aspect,
|
||||
near: near,
|
||||
far: far,
|
||||
}.into()
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Create a perspective matrix from a view frustum.
|
||||
|
@ -54,7 +55,8 @@ pub fn frustum<S: BaseFloat>(left: S, right: S, bottom: S, top: S, near: S, far:
|
|||
top: top,
|
||||
near: near,
|
||||
far: far,
|
||||
}.into()
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Create an orthographic projection matrix.
|
||||
|
@ -70,7 +72,8 @@ pub fn ortho<S: BaseFloat>(left: S, right: S, bottom: S, top: S, near: S, far: S
|
|||
top: top,
|
||||
near: near,
|
||||
far: far,
|
||||
}.into()
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
/// A perspective projection based on a vertical field-of-view angle.
|
||||
|
|
|
@ -17,12 +17,12 @@ use std::iter;
|
|||
use std::mem;
|
||||
use std::ops::*;
|
||||
|
||||
use num_traits::{cast, NumCast};
|
||||
#[cfg(feature = "rand")]
|
||||
use rand::{
|
||||
Rng,
|
||||
distributions::{Distribution, Standard},
|
||||
Rng,
|
||||
};
|
||||
use num_traits::{cast, NumCast};
|
||||
|
||||
use structure::*;
|
||||
|
||||
|
@ -626,17 +626,19 @@ macro_rules! index_operators {
|
|||
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, i: $I) -> &'a $Output {
|
||||
let v: &[$S; 4] = self.as_ref(); &v[i]
|
||||
let v: &[$S; 4] = self.as_ref();
|
||||
&v[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<$S: BaseFloat> IndexMut<$I> for Quaternion<$S> {
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, i: $I) -> &'a mut $Output {
|
||||
let v: &mut [$S; 4] = self.as_mut(); &mut v[i]
|
||||
}
|
||||
let v: &mut [$S; 4] = self.as_mut();
|
||||
&mut v[i]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
index_operators!(S, S, usize);
|
||||
|
@ -647,9 +649,11 @@ index_operators!(S, [S], RangeFull);
|
|||
|
||||
#[cfg(feature = "rand")]
|
||||
impl<S> Distribution<Quaternion<S>> for Standard
|
||||
where Standard: Distribution<S>,
|
||||
where
|
||||
Standard: Distribution<S>,
|
||||
Standard: Distribution<Vector3<S>>,
|
||||
S: BaseFloat {
|
||||
S: BaseFloat,
|
||||
{
|
||||
#[inline]
|
||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Quaternion<S> {
|
||||
Quaternion::from_sv(rng.gen(), rng.gen())
|
||||
|
|
|
@ -54,7 +54,7 @@ impl InnerSpace for Quaternion<f32> {
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{
|
||||
impl_operator_simd! {
|
||||
[Simdf32x4]; Neg for Quaternion<f32> {
|
||||
fn neg(lhs) -> Quaternion<f32> {
|
||||
(-lhs).into()
|
||||
|
@ -62,7 +62,7 @@ impl_operator_simd!{
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{@rs
|
||||
impl_operator_simd! {@rs
|
||||
[Simdf32x4]; Mul<f32> for Quaternion<f32> {
|
||||
fn mul(lhs, rhs) -> Quaternion<f32> {
|
||||
(lhs * rhs).into()
|
||||
|
@ -78,7 +78,7 @@ impl MulAssign<f32> for Quaternion<f32> {
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{@rs
|
||||
impl_operator_simd! {@rs
|
||||
[Simdf32x4]; Div<f32> for Quaternion<f32> {
|
||||
fn div(lhs, rhs) -> Quaternion<f32> {
|
||||
(lhs / rhs).into()
|
||||
|
@ -94,7 +94,7 @@ impl DivAssign<f32> for Quaternion<f32> {
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{
|
||||
impl_operator_simd! {
|
||||
[Simdf32x4]; Add<Quaternion<f32>> for Quaternion<f32> {
|
||||
fn add(lhs, rhs) -> Quaternion<f32> {
|
||||
(lhs + rhs).into()
|
||||
|
@ -111,7 +111,7 @@ impl AddAssign for Quaternion<f32> {
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{
|
||||
impl_operator_simd! {
|
||||
[Simdf32x4]; Sub<Quaternion<f32>> for Quaternion<f32> {
|
||||
fn sub(lhs, rhs) -> Quaternion<f32> {
|
||||
(lhs - rhs).into()
|
||||
|
@ -128,7 +128,7 @@ impl SubAssign for Quaternion<f32> {
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{
|
||||
impl_operator_simd! {
|
||||
[Simdf32x4]; Mul<Quaternion<f32>> for Quaternion<f32> {
|
||||
fn mul(lhs, rhs) -> Quaternion<f32> {
|
||||
{
|
||||
|
|
|
@ -62,17 +62,18 @@ where
|
|||
}
|
||||
|
||||
/// A two-dimensional rotation.
|
||||
pub trait Rotation2<S: BaseFloat>
|
||||
: Rotation<Point2<S>> + Into<Matrix2<S>> + Into<Basis2<S>> {
|
||||
pub trait Rotation2<S: BaseFloat>:
|
||||
Rotation<Point2<S>> + Into<Matrix2<S>> + Into<Basis2<S>>
|
||||
{
|
||||
/// Create a rotation by a given angle. Thus is a redundant case of both
|
||||
/// from_axis_angle() and from_euler() for 2D space.
|
||||
fn from_angle<A: Into<Rad<S>>>(theta: A) -> Self;
|
||||
}
|
||||
|
||||
/// A three-dimensional rotation.
|
||||
pub trait Rotation3<S: BaseFloat>
|
||||
: Rotation<Point3<S>> + Into<Matrix3<S>> + Into<Basis3<S>> + Into<Quaternion<S>> + From<Euler<Rad<S>>>
|
||||
{
|
||||
pub trait Rotation3<S: BaseFloat>:
|
||||
Rotation<Point3<S>> + Into<Matrix3<S>> + Into<Basis3<S>> + Into<Quaternion<S>> + From<Euler<Rad<S>>>
|
||||
{
|
||||
/// Create a rotation using an angle around a given axis.
|
||||
///
|
||||
/// The specified axis **must be normalized**, or it represents an invalid rotation.
|
||||
|
|
|
@ -607,7 +607,11 @@ where
|
|||
#[inline]
|
||||
fn normalize_signed(self) -> Self {
|
||||
let rem = self.normalize();
|
||||
if Self::turn_div_2() < rem { rem - Self::full_turn() } else { rem }
|
||||
if Self::turn_div_2() < rem {
|
||||
rem - Self::full_turn()
|
||||
} else {
|
||||
rem
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the angle rotated by half a turn.
|
||||
|
|
|
@ -225,10 +225,10 @@ where
|
|||
#[cfg(feature = "serde")]
|
||||
#[doc(hidden)]
|
||||
mod serde_ser {
|
||||
use structure::VectorSpace;
|
||||
use super::Decomposed;
|
||||
use serde::{self, Serialize};
|
||||
use serde::ser::SerializeStruct;
|
||||
use serde::{self, Serialize};
|
||||
use structure::VectorSpace;
|
||||
|
||||
impl<V, R> Serialize for Decomposed<V, R>
|
||||
where
|
||||
|
@ -252,11 +252,11 @@ mod serde_ser {
|
|||
#[cfg(feature = "serde")]
|
||||
#[doc(hidden)]
|
||||
mod serde_de {
|
||||
use structure::VectorSpace;
|
||||
use super::Decomposed;
|
||||
use serde::{self, Deserialize};
|
||||
use std::marker::PhantomData;
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
use structure::VectorSpace;
|
||||
|
||||
enum DecomposedField {
|
||||
Scale,
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use num_traits::{Bounded, NumCast};
|
||||
#[cfg(feature = "rand")]
|
||||
use rand::{
|
||||
Rng,
|
||||
distributions::{Distribution, Standard},
|
||||
Rng,
|
||||
};
|
||||
use num_traits::{Bounded, NumCast};
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
use std::mem;
|
||||
|
|
|
@ -69,7 +69,7 @@ impl Into<Simdf32x4> for Vector4<f32> {
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{
|
||||
impl_operator_simd! {
|
||||
[Simdf32x4]; Add<Vector4<f32>> for Vector4<f32> {
|
||||
fn add(lhs, rhs) -> Vector4<f32> {
|
||||
(lhs + rhs).into()
|
||||
|
@ -77,7 +77,7 @@ impl_operator_simd!{
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{
|
||||
impl_operator_simd! {
|
||||
[Simdf32x4]; Sub<Vector4<f32>> for Vector4<f32> {
|
||||
fn sub(lhs, rhs) -> Vector4<f32> {
|
||||
(lhs - rhs).into()
|
||||
|
@ -85,7 +85,7 @@ impl_operator_simd!{
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{@rs
|
||||
impl_operator_simd! {@rs
|
||||
[Simdf32x4]; Mul<f32> for Vector4<f32> {
|
||||
fn mul(lhs, rhs) -> Vector4<f32> {
|
||||
(lhs * rhs).into()
|
||||
|
@ -93,7 +93,7 @@ impl_operator_simd!{@rs
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{@rs
|
||||
impl_operator_simd! {@rs
|
||||
[Simdf32x4]; Div<f32> for Vector4<f32> {
|
||||
fn div(lhs, rhs) -> Vector4<f32> {
|
||||
(lhs / rhs).into()
|
||||
|
@ -101,7 +101,7 @@ impl_operator_simd!{@rs
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{
|
||||
impl_operator_simd! {
|
||||
[Simdf32x4]; Neg for Vector4<f32> {
|
||||
fn neg(lhs) -> Vector4<f32> {
|
||||
(-lhs).into()
|
||||
|
@ -262,7 +262,7 @@ impl Into<Simdi32x4> for Vector4<i32> {
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{
|
||||
impl_operator_simd! {
|
||||
[Simdi32x4]; Add<Vector4<i32>> for Vector4<i32> {
|
||||
fn add(lhs, rhs) -> Vector4<i32> {
|
||||
(lhs + rhs).into()
|
||||
|
@ -270,7 +270,7 @@ impl_operator_simd!{
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{
|
||||
impl_operator_simd! {
|
||||
[Simdi32x4]; Sub<Vector4<i32>> for Vector4<i32> {
|
||||
fn sub(lhs, rhs) -> Vector4<i32> {
|
||||
(lhs - rhs).into()
|
||||
|
@ -278,7 +278,7 @@ impl_operator_simd!{
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{@rs
|
||||
impl_operator_simd! {@rs
|
||||
[Simdi32x4]; Mul<i32> for Vector4<i32> {
|
||||
fn mul(lhs, rhs) -> Vector4<i32> {
|
||||
(lhs * rhs).into()
|
||||
|
@ -286,7 +286,7 @@ impl_operator_simd!{@rs
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{
|
||||
impl_operator_simd! {
|
||||
[Simdi32x4]; Neg for Vector4<i32> {
|
||||
fn neg(lhs) -> Vector4<i32> {
|
||||
(-lhs).into()
|
||||
|
@ -342,7 +342,7 @@ impl Into<Simdu32x4> for Vector4<u32> {
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{
|
||||
impl_operator_simd! {
|
||||
[Simdu32x4]; Add<Vector4<u32>> for Vector4<u32> {
|
||||
fn add(lhs, rhs) -> Vector4<u32> {
|
||||
(lhs + rhs).into()
|
||||
|
@ -350,7 +350,7 @@ impl_operator_simd!{
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{
|
||||
impl_operator_simd! {
|
||||
[Simdu32x4]; Sub<Vector4<u32>> for Vector4<u32> {
|
||||
fn sub(lhs, rhs) -> Vector4<u32> {
|
||||
(lhs - rhs).into()
|
||||
|
@ -358,7 +358,7 @@ impl_operator_simd!{
|
|||
}
|
||||
}
|
||||
|
||||
impl_operator_simd!{@rs
|
||||
impl_operator_simd! {@rs
|
||||
[Simdu32x4]; Mul<u32> for Vector4<u32> {
|
||||
fn mul(lhs, rhs) -> Vector4<u32> {
|
||||
(lhs * rhs).into()
|
||||
|
|
829
tests/matrix.rs
829
tests/matrix.rs
File diff suppressed because it is too large
Load diff
|
@ -17,7 +17,7 @@ extern crate approx;
|
|||
extern crate cgmath;
|
||||
|
||||
macro_rules! impl_test_mul {
|
||||
($s:expr, $v:expr) => (
|
||||
($s:expr, $v:expr) => {
|
||||
// point * scalar ops
|
||||
assert_eq!($v * $s, Quaternion::from_sv($v.s * $s, $v.v * $s));
|
||||
assert_eq!($s * $v, Quaternion::from_sv($s * $v.s, $s * $v.v));
|
||||
|
@ -25,17 +25,17 @@ macro_rules! impl_test_mul {
|
|||
assert_eq!($s * &$v, $s * $v);
|
||||
// commutativity
|
||||
assert_eq!($v * $s, $s * $v);
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_test_div {
|
||||
($s:expr, $v:expr) => (
|
||||
($s:expr, $v:expr) => {
|
||||
// point / scalar ops
|
||||
assert_eq!($v / $s, Quaternion::from_sv($v.s / $s, $v.v / $s));
|
||||
assert_eq!($s / $v, Quaternion::from_sv($s / $v.s, $s / $v.v));
|
||||
assert_eq!(&$v / $s, $v / $s);
|
||||
assert_eq!($s / &$v, $s / $v);
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
mod operators {
|
||||
|
|
|
@ -29,7 +29,8 @@ fn test_invert() {
|
|||
rot: Quaternion::new(0.5f64, 0.5, 0.5, 0.5),
|
||||
disp: Vector3::new(6.0f64, -7.0, 8.0),
|
||||
};
|
||||
let ti = t.inverse_transform()
|
||||
let ti = t
|
||||
.inverse_transform()
|
||||
.expect("Expected successful inversion");
|
||||
let vt = t.transform_vector(v);
|
||||
assert_ulps_eq!(&v, &ti.transform_vector(vt));
|
||||
|
@ -43,7 +44,8 @@ fn test_inverse_vector() {
|
|||
rot: Quaternion::new(0.5f64, 0.5, 0.5, 0.5),
|
||||
disp: Vector3::new(6.0f64, -7.0, 8.0),
|
||||
};
|
||||
let vt = t.inverse_transform_vector(v)
|
||||
let vt = t
|
||||
.inverse_transform_vector(v)
|
||||
.expect("Expected successful inversion");
|
||||
assert_ulps_eq!(v, t.transform_vector(vt));
|
||||
}
|
||||
|
|
|
@ -212,14 +212,8 @@ fn test_is_perpendicular() {
|
|||
assert!(
|
||||
Vector3::new(0.0f64, 1.0f64, 0.0f64).is_perpendicular(Vector3::new(0.0f64, 0.0f64, 1.0f64))
|
||||
);
|
||||
assert!(
|
||||
Vector4::new(1.0f64, 0.0f64, 0.0f64, 0.0f64).is_perpendicular(Vector4::new(
|
||||
0.0f64,
|
||||
0.0f64,
|
||||
0.0f64,
|
||||
1.0f64
|
||||
))
|
||||
);
|
||||
assert!(Vector4::new(1.0f64, 0.0f64, 0.0f64, 0.0f64)
|
||||
.is_perpendicular(Vector4::new(0.0f64, 0.0f64, 0.0f64, 1.0f64)));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -292,30 +286,18 @@ fn test_angle() {
|
|||
);
|
||||
|
||||
assert_ulps_eq!(
|
||||
Vector4::new(1.0f64, 0.0f64, 1.0f64, 0.0f64).angle(Vector4::new(
|
||||
0.0f64,
|
||||
1.0f64,
|
||||
0.0f64,
|
||||
1.0f64
|
||||
)),
|
||||
Vector4::new(1.0f64, 0.0f64, 1.0f64, 0.0f64)
|
||||
.angle(Vector4::new(0.0f64, 1.0f64, 0.0f64, 1.0f64)),
|
||||
&Rad(f64::consts::FRAC_PI_2)
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
Vector4::new(10.0f64, 0.0f64, 10.0f64, 0.0f64).angle(Vector4::new(
|
||||
0.0f64,
|
||||
5.0f64,
|
||||
0.0f64,
|
||||
5.0f64
|
||||
)),
|
||||
Vector4::new(10.0f64, 0.0f64, 10.0f64, 0.0f64)
|
||||
.angle(Vector4::new(0.0f64, 5.0f64, 0.0f64, 5.0f64)),
|
||||
&Rad(f64::consts::FRAC_PI_2)
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
Vector4::new(-1.0f64, 0.0f64, -1.0f64, 0.0f64).angle(Vector4::new(
|
||||
0.0f64,
|
||||
1.0f64,
|
||||
0.0f64,
|
||||
1.0f64
|
||||
)),
|
||||
Vector4::new(-1.0f64, 0.0f64, -1.0f64, 0.0f64)
|
||||
.angle(Vector4::new(0.0f64, 1.0f64, 0.0f64, 1.0f64)),
|
||||
&Rad(f64::consts::FRAC_PI_2)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -135,12 +135,8 @@ fn test_rem() {
|
|||
#[test]
|
||||
fn test_dot() {
|
||||
assert_eq!(
|
||||
Vector4::new(1.0f32, 2.0f32, 3.0f32, 4.0f32).dot(Vector4::new(
|
||||
5.0f32,
|
||||
6.0f32,
|
||||
7.0f32,
|
||||
8.0f32
|
||||
)),
|
||||
Vector4::new(1.0f32, 2.0f32, 3.0f32, 4.0f32)
|
||||
.dot(Vector4::new(5.0f32, 6.0f32, 7.0f32, 8.0f32)),
|
||||
70.0f32
|
||||
);
|
||||
}
|
||||
|
@ -164,14 +160,8 @@ fn test_product() {
|
|||
|
||||
#[test]
|
||||
fn test_is_perpendicular() {
|
||||
assert!(
|
||||
Vector4::new(1.0f32, 0.0f32, 0.0f32, 0.0f32).is_perpendicular(Vector4::new(
|
||||
0.0f32,
|
||||
0.0f32,
|
||||
0.0f32,
|
||||
1.0f32
|
||||
))
|
||||
);
|
||||
assert!(Vector4::new(1.0f32, 0.0f32, 0.0f32, 0.0f32)
|
||||
.is_perpendicular(Vector4::new(0.0f32, 0.0f32, 0.0f32, 1.0f32)));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -210,30 +200,18 @@ mod test_magnitude {
|
|||
#[test]
|
||||
fn test_angle() {
|
||||
assert_ulps_eq!(
|
||||
Vector4::new(1.0f32, 0.0f32, 1.0f32, 0.0f32).angle(Vector4::new(
|
||||
0.0f32,
|
||||
1.0f32,
|
||||
0.0f32,
|
||||
1.0f32
|
||||
)),
|
||||
Vector4::new(1.0f32, 0.0f32, 1.0f32, 0.0f32)
|
||||
.angle(Vector4::new(0.0f32, 1.0f32, 0.0f32, 1.0f32)),
|
||||
&Rad(f32::consts::FRAC_PI_2)
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
Vector4::new(10.0f32, 0.0f32, 10.0f32, 0.0f32).angle(Vector4::new(
|
||||
0.0f32,
|
||||
5.0f32,
|
||||
0.0f32,
|
||||
5.0f32
|
||||
)),
|
||||
Vector4::new(10.0f32, 0.0f32, 10.0f32, 0.0f32)
|
||||
.angle(Vector4::new(0.0f32, 5.0f32, 0.0f32, 5.0f32)),
|
||||
&Rad(f32::consts::FRAC_PI_2)
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
Vector4::new(-1.0f32, 0.0f32, -1.0f32, 0.0f32).angle(Vector4::new(
|
||||
0.0f32,
|
||||
1.0f32,
|
||||
0.0f32,
|
||||
1.0f32
|
||||
)),
|
||||
Vector4::new(-1.0f32, 0.0f32, -1.0f32, 0.0f32)
|
||||
.angle(Vector4::new(0.0f32, 1.0f32, 0.0f32, 1.0f32)),
|
||||
&Rad(f32::consts::FRAC_PI_2)
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue