forked from M-Labs/nalgebra
Merge branch 'aepsil0n-abomonation'
This commit is contained in:
commit
613abfc1b4
@ -23,9 +23,10 @@ script:
|
||||
- cargo build --verbose
|
||||
- cargo build --verbose --features arbitrary
|
||||
- cargo build --verbose --features serde-serialize
|
||||
- cargo test --verbose --features "arbitrary debug serde-serialize"
|
||||
- cargo build --verbose --features abomonation-serialize
|
||||
- cargo test --verbose --features "arbitrary serde-serialize abomonation-serialize"
|
||||
- cd nalgebra-lapack; cargo test --verbose
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- CARGO_FEATURE_SYSTEM_NETLIB=1 CARGO_FEATURE_EXCLUDE_LAPACKE=1 CARGO_FEATURE_EXCLUDE_CBLAS=1
|
||||
- CARGO_FEATURE_SYSTEM_NETLIB=1 CARGO_FEATURE_EXCLUDE_LAPACKE=1 CARGO_FEATURE_EXCLUDE_CBLAS=1
|
@ -18,6 +18,7 @@ path = "src/lib.rs"
|
||||
[features]
|
||||
arbitrary = [ "quickcheck" ]
|
||||
serde-serialize = [ "serde", "serde_derive", "num-complex/serde" ]
|
||||
abomonation-serialize = [ "abomonation" ]
|
||||
debug = [ ]
|
||||
|
||||
[dependencies]
|
||||
@ -31,6 +32,7 @@ alga = "0.5"
|
||||
matrixmultiply = "0.1"
|
||||
serde = { version = "1.0", optional = true }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
abomonation = { version = "0.4", optional = true }
|
||||
|
||||
[dependencies.quickcheck]
|
||||
optional = true
|
||||
|
4
Makefile
4
Makefile
@ -2,10 +2,10 @@ all:
|
||||
cargo check --features "debug arbitrary serde-serialize"
|
||||
|
||||
doc:
|
||||
cargo doc --no-deps --features "debug arbitrary serde-serialize"
|
||||
cargo doc --no-deps --features "debug arbitrary serde-serialize abomonation"
|
||||
|
||||
bench:
|
||||
cargo bench
|
||||
|
||||
test:
|
||||
cargo test --features "debug arbitrary serde-serialize"
|
||||
cargo test --features "debug arbitrary serde-serialize abomonation-serialize"
|
||||
|
@ -11,6 +11,9 @@ use approx::ApproxEq;
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
use serde::{Serialize, Serializer, Deserialize, Deserializer};
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
use abomonation::Abomonation;
|
||||
|
||||
use alga::general::{Ring, Real};
|
||||
|
||||
use core::{Scalar, DefaultAllocator, Unit, VectorN, MatrixMN};
|
||||
@ -99,6 +102,21 @@ impl<'de, N, R, C, S> Deserialize<'de> for Matrix<N, R, C, S>
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
impl<N: Scalar, R: Dim, C: Dim, S: Abomonation> Abomonation for Matrix<N, R, C, S> {
|
||||
unsafe fn entomb(&self, writer: &mut Vec<u8>) {
|
||||
self.data.entomb(writer)
|
||||
}
|
||||
|
||||
unsafe fn embalm(&mut self) {
|
||||
self.data.embalm()
|
||||
}
|
||||
|
||||
unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
|
||||
self.data.exhume(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Scalar, R: Dim, C: Dim, S> Matrix<N, R, C, S> {
|
||||
/// Creates a new matrix with the given data without statically checking that the matrix
|
||||
/// dimension matches the storage dimension.
|
||||
|
@ -13,6 +13,9 @@ use std::mem;
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
use abomonation::Abomonation;
|
||||
|
||||
use typenum::Prod;
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
|
||||
@ -319,3 +322,36 @@ where N: Scalar + Deserialize<'a>,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
impl<N, R, C> Abomonation for MatrixArray<N, R, C>
|
||||
where R: DimName,
|
||||
C: DimName,
|
||||
R::Value: Mul<C::Value>,
|
||||
Prod<R::Value, C::Value>: ArrayLength<N>,
|
||||
N: Abomonation
|
||||
{
|
||||
unsafe fn entomb(&self, writer: &mut Vec<u8>) {
|
||||
for element in self.data.as_slice() {
|
||||
element.entomb(writer);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn embalm(&mut self) {
|
||||
for element in self.data.as_mut_slice() {
|
||||
element.embalm();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn exhume<'a, 'b>(&'a mut self, mut bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
|
||||
for element in self.data.as_mut_slice() {
|
||||
let temp = bytes;
|
||||
bytes = if let Some(remainder) = element.exhume(temp) {
|
||||
remainder
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(bytes)
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,9 @@ use core::storage::{Storage, StorageMut, Owned, ContiguousStorage, ContiguousSto
|
||||
use core::allocator::Allocator;
|
||||
use core::default_allocator::DefaultAllocator;
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
use abomonation::Abomonation;
|
||||
|
||||
/*
|
||||
*
|
||||
* Storage.
|
||||
@ -213,6 +216,21 @@ unsafe impl<N: Scalar, R: DimName> StorageMut<N, R, Dynamic> for MatrixVec<N, R,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
impl<N: Abomonation, R: Dim, C: Dim> Abomonation for MatrixVec<N, R, C> {
|
||||
unsafe fn entomb(&self, writer: &mut Vec<u8>) {
|
||||
self.data.entomb(writer)
|
||||
}
|
||||
|
||||
unsafe fn embalm(&mut self) {
|
||||
self.data.embalm()
|
||||
}
|
||||
|
||||
unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
|
||||
self.data.exhume(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<N: Scalar, R: DimName> ContiguousStorage<N, R, Dynamic> for MatrixVec<N, R, Dynamic>
|
||||
where DefaultAllocator: Allocator<N, R, Dynamic, Buffer = Self> {
|
||||
}
|
||||
|
@ -5,6 +5,9 @@ use approx::ApproxEq;
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
use serde::{Serialize, Serializer, Deserialize, Deserializer};
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
use abomonation::Abomonation;
|
||||
|
||||
use alga::general::SubsetOf;
|
||||
use alga::linear::NormedSpace;
|
||||
|
||||
@ -36,6 +39,21 @@ impl<'de, T: Deserialize<'de>> Deserialize<'de> for Unit<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
impl<T: Abomonation> Abomonation for Unit<T> {
|
||||
unsafe fn entomb(&self, writer: &mut Vec<u8>) {
|
||||
self.value.entomb(writer);
|
||||
}
|
||||
|
||||
unsafe fn embalm(&mut self) {
|
||||
self.value.embalm();
|
||||
}
|
||||
|
||||
unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
|
||||
self.value.exhume(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NormedSpace> Unit<T> {
|
||||
/// Normalize the given value and return it wrapped on a `Unit` structure.
|
||||
#[inline]
|
||||
|
@ -6,6 +6,9 @@ use approx::ApproxEq;
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
use serde;
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
use abomonation::Abomonation;
|
||||
|
||||
use alga::general::{Real, SubsetOf};
|
||||
use alga::linear::Rotation;
|
||||
|
||||
@ -42,6 +45,30 @@ pub struct Isometry<N: Real, D: DimName, R>
|
||||
_noconstruct: PhantomData<N>
|
||||
}
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
impl<N, D, R> Abomonation for Isometry<N, D, R>
|
||||
where N: Real,
|
||||
D: DimName,
|
||||
R: Abomonation,
|
||||
Translation<N, D>: Abomonation,
|
||||
DefaultAllocator: Allocator<N, D>
|
||||
{
|
||||
unsafe fn entomb(&self, writer: &mut Vec<u8>) {
|
||||
self.rotation.entomb(writer);
|
||||
self.translation.entomb(writer);
|
||||
}
|
||||
|
||||
unsafe fn embalm(&mut self) {
|
||||
self.rotation.embalm();
|
||||
self.translation.embalm();
|
||||
}
|
||||
|
||||
unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
|
||||
self.rotation.exhume(bytes)
|
||||
.and_then(|bytes| self.translation.exhume(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Real + hash::Hash, D: DimName + hash::Hash, R: hash::Hash> hash::Hash for Isometry<N, D, R>
|
||||
where DefaultAllocator: Allocator<N, D>,
|
||||
Owned<N, D>: hash::Hash {
|
||||
@ -66,6 +93,7 @@ impl<N: Real, D: DimName, R: Rotation<Point<N, D>> + Clone> Clone for Isometry<N
|
||||
|
||||
impl<N: Real, D: DimName, R: Rotation<Point<N, D>>> Isometry<N, D, R>
|
||||
where DefaultAllocator: Allocator<N, D> {
|
||||
|
||||
/// Creates a new isometry from its rotational and translational parts.
|
||||
#[inline]
|
||||
pub fn from_parts(translation: Translation<N, D>, rotation: R) -> Isometry<N, D, R> {
|
||||
|
@ -7,6 +7,9 @@ use approx::ApproxEq;
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
use serde;
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
use abomonation::Abomonation;
|
||||
|
||||
use core::{DefaultAllocator, Scalar, VectorN};
|
||||
use core::iter::{MatrixIter, MatrixIterMut};
|
||||
use core::dimension::{DimName, DimNameSum, DimNameAdd, U1};
|
||||
@ -66,6 +69,27 @@ where DefaultAllocator: Allocator<N, D>,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
impl<N, D> Abomonation for Point<N, D>
|
||||
where N: Scalar,
|
||||
D: DimName,
|
||||
VectorN<N, D>: Abomonation,
|
||||
DefaultAllocator: Allocator<N, D>
|
||||
{
|
||||
unsafe fn entomb(&self, writer: &mut Vec<u8>) {
|
||||
self.coords.entomb(writer)
|
||||
}
|
||||
|
||||
unsafe fn embalm(&mut self) {
|
||||
self.coords.embalm()
|
||||
}
|
||||
|
||||
unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
|
||||
self.coords.exhume(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Scalar, D: DimName> Point<N, D>
|
||||
where DefaultAllocator: Allocator<N, D> {
|
||||
|
||||
|
@ -8,6 +8,9 @@ use serde;
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
use core::storage::Owned;
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
use abomonation::Abomonation;
|
||||
|
||||
use alga::general::Real;
|
||||
|
||||
use core::{Unit, Vector3, Vector4, MatrixSlice, MatrixSliceMut, SquareMatrix, MatrixN};
|
||||
@ -25,9 +28,25 @@ pub struct Quaternion<N: Real> {
|
||||
pub coords: Vector4<N>
|
||||
}
|
||||
|
||||
impl<N: Real + Eq> Eq for Quaternion<N> {
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
impl<N: Real> Abomonation for Quaternion<N>
|
||||
where Vector4<N>: Abomonation
|
||||
{
|
||||
unsafe fn entomb(&self, writer: &mut Vec<u8>) {
|
||||
self.coords.entomb(writer)
|
||||
}
|
||||
|
||||
unsafe fn embalm(&mut self) {
|
||||
self.coords.embalm()
|
||||
}
|
||||
|
||||
unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
|
||||
self.coords.exhume(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Real + Eq> Eq for Quaternion<N> { }
|
||||
|
||||
impl<N: Real> PartialEq for Quaternion<N> {
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
self.coords == rhs.coords ||
|
||||
|
@ -9,6 +9,9 @@ use serde;
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
use core::storage::Owned;
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
use abomonation::Abomonation;
|
||||
|
||||
use alga::general::Real;
|
||||
|
||||
use core::{DefaultAllocator, Scalar, MatrixN};
|
||||
@ -45,6 +48,26 @@ impl<N: Scalar, D: DimName> Clone for Rotation<N, D>
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
impl<N, D> Abomonation for Rotation<N, D>
|
||||
where N: Scalar,
|
||||
D: DimName,
|
||||
MatrixN<N, D>: Abomonation,
|
||||
DefaultAllocator: Allocator<N, D, D>
|
||||
{
|
||||
unsafe fn entomb(&self, writer: &mut Vec<u8>) {
|
||||
self.matrix.entomb(writer)
|
||||
}
|
||||
|
||||
unsafe fn embalm(&mut self) {
|
||||
self.matrix.embalm()
|
||||
}
|
||||
|
||||
unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
|
||||
self.matrix.exhume(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
impl<N: Scalar, D: DimName> serde::Serialize for Rotation<N, D>
|
||||
where DefaultAllocator: Allocator<N, D, D>,
|
||||
|
@ -5,6 +5,9 @@ use approx::ApproxEq;
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
use serde;
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
use abomonation::Abomonation;
|
||||
|
||||
use alga::general::{Real, SubsetOf};
|
||||
use alga::linear::Rotation;
|
||||
|
||||
@ -15,6 +18,7 @@ use core::allocator::Allocator;
|
||||
use geometry::{Point, Translation, Isometry};
|
||||
|
||||
|
||||
|
||||
/// A similarity, i.e., an uniform scaling, followed by a rotation, followed by a translation.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
@ -38,6 +42,24 @@ pub struct Similarity<N: Real, D: DimName, R>
|
||||
scaling: N
|
||||
}
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
impl<N: Real, D: DimName, R> Abomonation for Similarity<N, D, R>
|
||||
where Isometry<N, D, R>: Abomonation,
|
||||
DefaultAllocator: Allocator<N, D>
|
||||
{
|
||||
unsafe fn entomb(&self, writer: &mut Vec<u8>) {
|
||||
self.isometry.entomb(writer)
|
||||
}
|
||||
|
||||
unsafe fn embalm(&mut self) {
|
||||
self.isometry.embalm()
|
||||
}
|
||||
|
||||
unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
|
||||
self.isometry.exhume(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Real + hash::Hash, D: DimName + hash::Hash, R: hash::Hash> hash::Hash for Similarity<N, D, R>
|
||||
where DefaultAllocator: Allocator<N, D>,
|
||||
Owned<N, D>: hash::Hash {
|
||||
|
@ -6,6 +6,9 @@ use approx::ApproxEq;
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
use serde;
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
use abomonation::Abomonation;
|
||||
|
||||
use alga::general::{Real, ClosedNeg};
|
||||
|
||||
use core::{DefaultAllocator, Scalar, MatrixN, VectorN};
|
||||
@ -44,6 +47,26 @@ impl<N: Scalar, D: DimName> Clone for Translation<N, D>
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "abomonation-serialize")]
|
||||
impl<N, D> Abomonation for Translation<N, D>
|
||||
where N: Scalar,
|
||||
D: DimName,
|
||||
VectorN<N, D>: Abomonation,
|
||||
DefaultAllocator: Allocator<N, D>
|
||||
{
|
||||
unsafe fn entomb(&self, writer: &mut Vec<u8>) {
|
||||
self.vector.entomb(writer)
|
||||
}
|
||||
|
||||
unsafe fn embalm(&mut self) {
|
||||
self.vector.embalm()
|
||||
}
|
||||
|
||||
unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> {
|
||||
self.vector.exhume(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-serialize")]
|
||||
impl<N: Scalar, D: DimName> serde::Serialize for Translation<N, D>
|
||||
where DefaultAllocator: Allocator<N, D>,
|
||||
|
@ -90,11 +90,16 @@ an optimized set of tools for computer graphics and physics. Those features incl
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
extern crate quickcheck;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
extern crate serde;
|
||||
#[cfg(feature = "serde")]
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[cfg(feature = "abomonation")]
|
||||
extern crate abomonation;
|
||||
|
||||
extern crate num_traits as num;
|
||||
extern crate num_complex;
|
||||
extern crate rand;
|
||||
|
51
tests/core/abomonation.rs
Normal file
51
tests/core/abomonation.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use rand::random;
|
||||
use abomonation::{Abomonation, encode, decode};
|
||||
use na::{
|
||||
DMatrix, Matrix3x4, Point3, Translation3, Rotation3, Isometry3, Quaternion,
|
||||
IsometryMatrix3, Similarity3, SimilarityMatrix3
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn abomonate_dmatrix() {
|
||||
assert_encode_and_decode(DMatrix::<f32>::new_random(3, 5));
|
||||
}
|
||||
|
||||
macro_rules! test_abomonation(
|
||||
($($test: ident, $ty: ty);* $(;)*) => {$(
|
||||
#[test]
|
||||
fn $test() {
|
||||
assert_encode_and_decode(random::<$ty>());
|
||||
}
|
||||
)*}
|
||||
);
|
||||
|
||||
test_abomonation! {
|
||||
abomonate_matrix3x4, Matrix3x4<f32>;
|
||||
abomonate_point3, Point3<f32>;
|
||||
abomonate_translation3, Translation3<f64>;
|
||||
abomonate_rotation3, Rotation3<f64>;
|
||||
abomonate_isometry3, Isometry3<f32>;
|
||||
abomonate_isometry_matrix3, IsometryMatrix3<f64>;
|
||||
abomonate_similarity3, Similarity3<f32>;
|
||||
abomonate_similarity_matrix3, SimilarityMatrix3<f32>;
|
||||
abomonate_quaternion, Quaternion<f32>;
|
||||
}
|
||||
|
||||
fn assert_encode_and_decode<T: Abomonation + PartialEq + Clone>(original_data: T) {
|
||||
use std::mem::drop;
|
||||
|
||||
// Hold on to a clone for later comparison
|
||||
let data = original_data.clone();
|
||||
|
||||
// Encode
|
||||
let mut bytes = Vec::new();
|
||||
unsafe { encode(&original_data, &mut bytes); }
|
||||
|
||||
// Drop the original, so that dangling pointers are revealed by the test
|
||||
drop(original_data);
|
||||
|
||||
if let Some((result, rest)) = unsafe { decode::<T>(&mut bytes) } {
|
||||
assert!(result == &data);
|
||||
assert!(rest.len() == 0, "binary data was not decoded completely");
|
||||
}
|
||||
}
|
@ -4,3 +4,4 @@ mod matrix;
|
||||
mod matrix_slice;
|
||||
mod blas;
|
||||
mod serde;
|
||||
mod abomonation;
|
||||
|
@ -83,7 +83,7 @@ quickcheck!(
|
||||
|
||||
/*
|
||||
*
|
||||
* Quaterion * Vector == RotationBase * Vector
|
||||
* Quaterion * Vector == Rotation * Vector
|
||||
*
|
||||
*/
|
||||
fn unit_quaternion_mul_vector(q: UnitQuaternion<f64>, v: Vector3<f64>, p: Point3<f64>) -> bool {
|
||||
|
@ -79,7 +79,7 @@ quickcheck!(
|
||||
|
||||
/*
|
||||
*
|
||||
* RotationBase matrix between vectors.
|
||||
* Rotation matrix between vectors.
|
||||
*
|
||||
*/
|
||||
fn rotation_between_is_anticommutative_2(a: Vector2<f64>, b: Vector2<f64>) -> bool {
|
||||
@ -132,7 +132,7 @@ quickcheck!(
|
||||
|
||||
/*
|
||||
*
|
||||
* RotationBase construction.
|
||||
* Rotation construction.
|
||||
*
|
||||
*/
|
||||
fn new_rotation_2(angle: f64) -> bool {
|
||||
@ -159,7 +159,7 @@ quickcheck!(
|
||||
|
||||
/*
|
||||
*
|
||||
* RotationBase pow.
|
||||
* Rotation pow.
|
||||
*
|
||||
*/
|
||||
fn powf_rotation_2(angle: f64, pow: f64) -> bool {
|
||||
|
@ -60,7 +60,7 @@ quickcheck!(
|
||||
|
||||
/*
|
||||
*
|
||||
* Quaterion * Vector == RotationBase * Vector
|
||||
* Quaterion * Vector == Rotation * Vector
|
||||
*
|
||||
*/
|
||||
fn unit_complex_mul_vector(c: UnitComplex<f64>, v: Vector2<f64>, p: Point2<f64>) -> bool {
|
||||
|
@ -5,6 +5,7 @@ extern crate quickcheck;
|
||||
extern crate approx;
|
||||
extern crate num_traits as num;
|
||||
extern crate serde_json;
|
||||
extern crate abomonation;
|
||||
extern crate rand;
|
||||
extern crate alga;
|
||||
extern crate nalgebra as na;
|
||||
|
Loading…
Reference in New Issue
Block a user