1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//!
//! Structs for interpreting geometric algebra as vector spaces and orthogonal transformations
//!
//! This module aims to streamline the use of the algebra for geometric uses by adding additional
//! constraints onto the types from [`crate::algebra`]. This is accomplished by wrapping the
//! algebraic types in additional structs where the allowed operations are much more limited.
//!
//! For example, in order to preserve the fact it represents a rotation, a [`Rotor`] cannot be
//! added to another `Rotor`, and to preserve its unit length, a [`UnitBlade`] cannot be multiplied
//! by a scalar.
//!
//! # Organization
//!
//!  To this aim, there are five main structs in this module:
//! - [`SimpleBlade`]: A [`Blade`] that is guarranteed to be the wedge product of vectors.
//! - [`UnitBlade`]: A [`SimpleBlade`] guarranteed to have a length of 1
//! - [`Rotor`]: An [`Even`] representing a rotation
//! - [`Reflector`]: An [`Odd`] representing a reflection combined with a possible rotation
//! - [`Versor`]: An [`Even`] *or* [`Odd`] representing a general orthogonal transformation
//!
//!

use std::borrow::{Borrow, BorrowMut};
use std::convert::{AsRef, AsMut};
use std::iter::{IntoIterator, FromIterator, Sum, Product};
use std::cmp::{PartialEq, Eq};
use std::hash::Hash;
use std::ops::{
    Index, IndexMut,
    Deref, DerefMut,
    Add, AddAssign, Sub, SubAssign, Neg,
    Mul, MulAssign, Div, DivAssign, Rem, BitXor
};
use std::fmt::{
    Formatter, Result as FmtResult,
    Debug, Display, Binary, Octal, LowerHex, UpperHex, LowerExp, UpperExp
};

use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use num_traits::{Zero, One, Inv};
use typenum::{True, IsLessOrEqual};

use crate::base::*;
use crate::algebra::*;

// #[cfg(test)] use crate::TEST_DIM;

pub type Iter<'a, T> = std::slice::Iter<'a, T>;
pub type IterMut<'a, T> = std::slice::IterMut<'a, T>;

///
/// A [`Blade`] that is the wedge product of `G` vectors
///
/// This is usually used to represent weighted vector spaces or when the cost to normalize to
/// a [`UnitBlade`] is too high.
///
#[repr(transparent)]
#[derive(Derivative)]
#[derivative(Copy(bound = "T:Copy, Blade<T,N,G>:Copy"))]
#[derivative(Clone(bound = "T:Clone"))]
#[derivative(Hash(bound = "T:Hash"))]
pub struct SimpleBlade<T:AllocBlade<N,G>,N:Dim,G:Dim> {
    data: Blade<T,N,G>
}

///
/// A [`SimpleBlade`] with unit length
///
/// Primary use is to represent oriented vector spaces of dimension `G`. If the quantity is going
/// to be stored/cached for an extended period of time, this can also provide an optimization over
/// a `SimpleBlade` since the length does not have to be accounted for.
///
#[repr(transparent)]
#[derive(Derivative)]
#[derivative(Copy(bound = "T:Copy, Blade<T,N,G>:Copy"))]
#[derivative(Clone(bound = "T:Clone"))]
#[derivative(Hash(bound = "T:Hash"))]
pub struct UnitBlade<T:AllocBlade<N,G>,N:Dim,G:Dim> {
    data: Blade<T,N,G>
}

/// Represents a rotation in `N` dimensions
#[repr(transparent)]
#[derive(Derivative)]
#[derivative(Copy(bound = "T:Copy, Even<T,N>:Copy"))]
#[derivative(Clone(bound = "T:Clone"))]
#[derivative(Hash(bound = "T:Hash"))]
pub struct Rotor<T:AllocEven<N>,N:Dim> {
    data: Even<T,N>
}

/// Represents a reflection in `N` dimensions (with an optional rotation component)
#[repr(transparent)]
#[derive(Derivative)]
#[derivative(Copy(bound = "T:Copy, Odd<T,N>:Copy"))]
#[derivative(Clone(bound = "T:Clone"))]
#[derivative(Hash(bound = "T:Hash"))]
pub struct Reflector<T:AllocOdd<N>,N:Dim> {
    data: Odd<T,N>
}

/// A general orthogonal transformation in `N` dimensions
#[derive(Derivative)]
#[derivative(Copy(bound = "T:Copy, Rotor<T,N>:Copy, Reflector<T,N>:Copy"))]
#[derivative(Clone(bound = "T:Clone"))]
#[derivative(Hash(bound = "T:Hash"))]
pub enum Versor<T:AllocVersor<N>, N:Dim> {
    Even(Rotor<T,N>),
    Odd(Reflector<T,N>)
}

macro_rules! maybe_ref {
    ($e:expr; ) => { $e };
    ($e:expr; $a:lifetime) => { &$e };
}

pub use self::common::*;
pub use self::mutable::*;
pub use self::involute::*;
pub use self::ops::*;
pub use self::blade::*;
pub use self::versor::*;
pub use self::aliases::*;
pub use self::constructors::*;

mod common;
mod mutable;
mod involute;
mod ops;
mod blade;
mod versor;
mod cast;
mod aliases;
mod constructors;