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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/// Simpler variadic generation of [`Alpha`] values.
/// This is the recommended way of creating raw alpha values if they are needed. Arguments
/// are u8s in the range 0-3.
///
/// # Panics
///
/// Panics if the specified alpha indices do not correspond to an allowed alpha (see
/// [`ALLOWED_ALPHA_FORMS`]).
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate arthroprod; fn main() {
/// use arthroprod::algebra::*;
///
/// let a1 = alpha!(0 2 3);
/// let a2 = -alpha!(0 1);
/// let a3 = alpha!();
///
/// assert_eq!(a1, Alpha::new(Sign::Pos, Form::Trivector(Index::Zero, Index::Two, Index::Three)).unwrap());
/// assert_eq!(a2, Alpha::new(Sign::Neg, Form::Bivector(Index::Zero, Index::One)).unwrap());
/// assert_eq!(a3, Alpha::new(Sign::Pos, Form::Point).unwrap());
/// # }
/// ```
#[macro_export]
macro_rules! alpha(
    ($($num:expr) *) => {
        {
            let sign = $crate::algebra::Sign::Pos;
            #[allow(unused_mut)]
            let mut ixs = Vec::new();
            $(ixs.push($crate::algebra::Index::try_from_u8($num).unwrap());)*

            $crate::algebra::Alpha::try_from_indices(sign, &ixs).unwrap()
        }
    };
);

/// Simpler variadic generation of [`Term`] values.
/// Terms created this way will have a default value (if one is not provided) and a
/// magnitude of 1. See [`alpha`] for more information on how the underlying [`Alpha`]
/// value is generated. It is also possible to specify a set of [`Xi`] values to use
/// for the term by providing a list of strings to use as the Xi symbolic values.
///
/// # Panics
///
/// Panics if the specified alpha indices do not correspond to an allowed alpha (see
/// [`ALLOWED_ALPHA_FORMS`]) or if the [`Xi`] values can not be converted to Strings.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate arthroprod; fn main() {
/// use arthroprod::algebra::*;
///
/// let t1 = term!(0 2 3);
/// let t2 = -term!("symbolic", 0 1);
/// let t3 = term!(["X", "Y"], 2);
///
/// let a1 = Alpha::new(Sign::Pos, Form::Trivector(Index::Zero, Index::Two, Index::Three)).unwrap();
/// let a2 = Alpha::new(Sign::Neg, Form::Bivector(Index::Zero, Index::One)).unwrap();
/// let a3 = Alpha::new(Sign::Pos, Form::Vector(Index::Two)).unwrap();
///
/// assert_eq!(t1, Term::new(None, a1));
/// assert_eq!(t2, Term::new(Some("symbolic"), a2));
/// assert_eq!(t3, Term::from_xis_and_alpha(vec!["X", "Y"], a3));
/// # }
/// ```
#[macro_export]
macro_rules! term(
    ($($num:expr) *) => {
        {
            let sign = $crate::algebra::Sign::Pos;
            #[allow(unused_mut)]
            let mut ixs = Vec::new();
            $(ixs.push($crate::algebra::Index::try_from_u8($num).unwrap());)*
            let alpha = $crate::algebra::Alpha::try_from_indices(sign, &ixs).unwrap();

            $crate::algebra::Term::new(None, alpha)
        }
    };

    ([$($xi:expr),+], $($num:expr) *) => {
        {
            let sign = $crate::algebra::Sign::Pos;
            #[allow(unused_mut)]
            let mut ixs = Vec::new();
            let mut xis = vec![];
            $(xis.push($xi);)+
            $(ixs.push($crate::algebra::Index::try_from_u8($num).unwrap());)*
            let alpha = $crate::algebra::Alpha::try_from_indices(sign, &ixs).unwrap();

            $crate::algebra::Term::from_xis_and_alpha(xis, alpha)
        }
    };

    ($sym:tt, $($num:expr) +) => {
        {
            let sign = $crate::algebra::Sign::Pos;
            #[allow(unused_mut)]
            let mut ixs = Vec::new();
            $(ixs.push($crate::algebra::Index::try_from_u8($num).unwrap());)+
            let alpha = $crate::algebra::Alpha::try_from_indices(sign, &ixs).unwrap();

            $crate::algebra::Term::new(Some($sym), alpha)
        }
    };
);

/// Simpler variadic generation of [`MultiVector`] values.
/// Each argument must impliment the AR trait so that it is possible to convert them to
/// [`Term`]s, with the resulting MultiVector is the sum of all terms generated this way.
///
/// # Panics
///
/// Panics if any of the arguments do not impliment the AR trait.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate arthroprod; fn main() {
/// use arthroprod::algebra::*;
///
/// let m1 = mvec![alpha!(1), -term!(0 3)];
/// let mut m2 = MultiVector::new();
/// m2.push(Term::new(None, alpha!(1)));
/// m2.push(-term!(0 3));
///
/// assert_eq!(m1, m2);
/// # }
/// ```
#[macro_export]
macro_rules! mvec(
    [$($ar_elem:expr),+] => {
        {
            let mut terms = Vec::new();
            $(terms.extend($ar_elem.as_terms());)+

            $crate::algebra::MultiVector::from_terms(terms)
        }
    };
);

/// A simple helper for constructing hashmaps with less verbosity.
/// # Examples
///
/// ```
/// # #[macro_use] extern crate arthroprod; fn main() {
/// use std::collections::HashMap;
///
/// let m = map!{
///     "foo" => vec![1, 2, 3],
///     "bar" => vec![4, 5, 6]
/// };
///
/// assert_eq!(m.get("foo"), Some(&vec![1, 2, 3]));
/// # }
/// ```
#[macro_export]
macro_rules! map(
    { $($key:expr => $value:expr),+ } => {
        {
            let mut _map = ::std::collections::HashMap::new();
            $(_map.insert($key, $value);)+
            _map
        }
    };
);