|
1 | 1 | #[cfg(test)]
|
2 | 2 | mod test {
|
3 |
| - use crate::algebra::ClBasis; |
| 3 | + use crate::algebra::{ClBasis, NonDegenerate}; |
| 4 | + use crate::types::{DivRing, FromComplex, IntoComplex64}; |
4 | 5 | use core::f64;
|
| 6 | + use std::fmt::Debug; |
5 | 7 | use std::hint::black_box;
|
6 | 8 | use std::time;
|
7 | 9 |
|
8 | 10 | use crate::algebra::ClAlgebra;
|
9 | 11 | use crate::declare_algebra;
|
10 | 12 | use crate::{Multivector, SparseMultivector};
|
11 | 13 | use ndarray::Array2;
|
12 |
| - use num::complex::Complex64; |
| 14 | + use num::complex::{Complex32, Complex64}; |
13 | 15 | use num::One;
|
14 | 16 | use num::Zero;
|
15 | 17 |
|
16 | 18 | #[test]
|
17 | 19 | fn basis_test() {
|
18 | 20 | declare_algebra!(Cl44, [+,+,+,+,-,-,-,-], ["e1", "e2", "e3", "e4", "g1", "g2", "g3", "g4"]);
|
| 21 | + // Check unpacking |
19 | 22 | let [e1, e2, e3, e4, g1, g2, g3, g4] = Cl44::basis::<f64>();
|
20 | 23 | println!("{}", e1 + e2 + e3 + e4 + g1 + g2 + g3 + g4);
|
21 | 24 |
|
| 25 | + // Check basis multiplication |
| 26 | + let sig = Cl44::signaturef(); |
22 | 27 | let b = Cl44::basis_sparse::<Complex64>();
|
23 |
| - println!("{}", &b[1] * &b[2]); |
24 | 28 | for i in 0..b.len() {
|
| 29 | + assert_eq!( |
| 30 | + &b[i] * &b[i], |
| 31 | + SparseMultivector::<Complex64, Cl44>::from_scalar(sig[i].into()) |
| 32 | + ); |
25 | 33 | for j in 0..i {
|
26 | 34 | assert_eq!(&b[i] * &b[j], -(&b[j] * &b[i]))
|
27 | 35 | }
|
28 |
| - //println!("{}", b[i].to_dense().fft().unwrap()); |
29 |
| - } |
30 |
| - |
31 |
| - declare_algebra!(Cl4, [+,+,+,+], ["a", "b", "c", "d"]); |
32 |
| - let e = Cl4::basis::<f64>(); |
33 |
| - for ei in e { |
34 |
| - println!("{}", ei.fft()); |
35 | 36 | }
|
36 | 37 | }
|
37 | 38 |
|
38 | 39 | #[test]
|
39 | 40 | fn fft_test() {
|
40 |
| - declare_algebra!(Oct, [-,-,-,-,-,-], ["e1", "e2", "e3", "e4", "e5", "e6"]); |
41 |
| - // Associative map of real octonions |
42 |
| - let e = Oct::basis::<f64>(); |
43 |
| - for i in 0..e.len() { |
44 |
| - let fei = e[i].fft(); |
45 |
| - // Check the the square of fft square is negative identity |
46 |
| - assert_eq!( |
47 |
| - (&fei * &fei).into_array2(), |
48 |
| - Array2::from_diag_elem(8, -Complex64::one()) |
49 |
| - ); |
50 |
| - for j in 0..i { |
51 |
| - let eij = &fei * &e[j].fft(); |
52 |
| - let eji = &e[j].fft() * &fei; |
53 |
| - // Check anticommutativity |
54 |
| - assert_eq!(eij, -&eji); |
55 |
| - |
56 |
| - let prod = eij.ifft(); |
57 |
| - // Check that naive and fft products agree |
58 |
| - assert_eq!(prod, e[i].naive_wedge_impl(&e[j])); |
59 |
| - // And that the fft product is correct at all |
60 |
| - assert!(prod.get_by_idx((1 << i) | (1 << j)).is_one()); |
61 |
| - assert!(prod.set_by_idx((1 << i) | (1 << j), 0.).is_zero()); |
62 |
| - } |
63 |
| - } |
64 |
| - // Associative map of complex octonions |
65 |
| - let e = Oct::basis::<Complex64>(); |
66 |
| - for i in 0..e.len() { |
67 |
| - let fei = e[i].fft(); |
68 |
| - // Check the the square of fft square is negative identity |
69 |
| - assert_eq!( |
70 |
| - (&fei * &fei).into_array2(), |
71 |
| - Array2::from_diag_elem(8, -Complex64::one()) |
72 |
| - ); |
73 |
| - for j in 0..i { |
74 |
| - let eij = &fei * &e[j].fft(); |
75 |
| - let eji = &e[j].fft() * &fei; |
76 |
| - // Check anticommutativity |
77 |
| - assert_eq!(eij, -&eji); |
78 |
| - |
79 |
| - let prod = eij.ifft(); |
80 |
| - // Check that naive and fft products agree |
81 |
| - assert_eq!(prod, e[i].naive_wedge_impl(&e[j])); |
82 |
| - // And that the fft product is correct at all |
83 |
| - assert!(prod.get_by_idx((1 << i) | (1 << j)).is_one()); |
84 |
| - assert!(prod |
85 |
| - .set_by_idx((1 << i) | (1 << j), Complex64::zero()) |
86 |
| - .is_zero()); |
| 41 | + fn fft_test_case< |
| 42 | + const DIM: usize, |
| 43 | + const REPR_DIM: usize, |
| 44 | + T: DivRing + Clone + IntoComplex64 + FromComplex + Debug, |
| 45 | + A: ClAlgebra + ClBasis<DIM> + NonDegenerate + Debug, |
| 46 | + >() { |
| 47 | + let e = A::basis::<T>(); |
| 48 | + for i in 0..e.len() { |
| 49 | + let fei = e[i].fft(); |
| 50 | + // Check the the square of fft square is negative identity |
| 51 | + assert_eq!( |
| 52 | + (&fei * &fei).into_array2(), |
| 53 | + Array2::from_diag_elem(REPR_DIM, Complex64::one() * A::signaturef()[i]) |
| 54 | + ); |
| 55 | + for j in 0..i { |
| 56 | + let eij = &fei * &e[j].fft(); |
| 57 | + let eji = &e[j].fft() * &fei; |
| 58 | + // Check anticommutativity |
| 59 | + assert_eq!(eij, -&eji); |
| 60 | + |
| 61 | + let prod = eij.ifft(); |
| 62 | + // Check that naive and fft products agree |
| 63 | + assert_eq!(prod, e[i].naive_wedge_impl(&e[j])); |
| 64 | + // And that the fft product is correct at all |
| 65 | + assert!(prod.get_by_idx((1 << i) | (1 << j)).is_one()); |
| 66 | + assert!(prod.set_by_idx((1 << i) | (1 << j), T::zero()).is_zero()); |
| 67 | + } |
87 | 68 | }
|
88 | 69 | }
|
| 70 | + |
| 71 | + declare_algebra!(Oct, [-,-,-,-,-,-]); |
| 72 | + fft_test_case::<6, 8, f32, Oct>(); |
| 73 | + fft_test_case::<6, 8, f64, Oct>(); |
| 74 | + fft_test_case::<6, 8, Complex32, Oct>(); |
| 75 | + fft_test_case::<6, 8, Complex64, Oct>(); |
| 76 | + declare_algebra!(ClOdd, [-,-,-,+,-,+,-]); |
| 77 | + fft_test_case::<7, 16, f32, ClOdd>(); |
| 78 | + fft_test_case::<7, 16, f64, ClOdd>(); |
| 79 | + fft_test_case::<7, 16, Complex32, ClOdd>(); |
| 80 | + fft_test_case::<7, 16, Complex64, ClOdd>(); |
89 | 81 | }
|
90 | 82 |
|
91 | 83 | #[test]
|
92 | 84 | fn ops_test() {
|
93 |
| - declare_algebra!(Oct, [-,-,-,-,-,-], ["e1", "e2", "e3", "e4", "e5", "e6"]); |
| 85 | + declare_algebra!(Oct, [-,-,-,-,-,-]); |
94 | 86 | type MV = SparseMultivector<f64, Oct>;
|
95 | 87 |
|
| 88 | + // Check values of blade exponents |
96 | 89 | let mut theta = 0.0;
|
97 | 90 | while theta < f64::consts::TAU {
|
98 | 91 | let b = MV::zero().set_by_idx(0b11, theta);
|
|
0 commit comments