From 87965cafb5b8d57e3918f34908a5a24fbb7e360d Mon Sep 17 00:00:00 2001 From: Lily Iliana Luna Ylva Anderson Grigaitis Date: Wed, 20 Aug 2025 20:32:43 -0500 Subject: [PATCH] Hyperbolic Asteroids, first commit. Rendering Poincare disk, circles, and lines. --- .gitignore | 1 + Cargo.lock | 154 ++++++++ Cargo.toml | 22 ++ flake.lock | 27 ++ flake.nix | 23 ++ index.html | 14 + src/cga.rs | 1024 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 213 +++++++++++ 8 files changed, 1478 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 index.html create mode 100644 src/cga.rs create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..471f821 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,154 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "hyperbolic_asteroids" +version = "0.1.0" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7f1f76c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "hyperbolic_asteroids" +version = "0.1.0" +edition = "2024" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +wasm-bindgen = "0.2" + +[dependencies.web-sys] +version = "0.3" +features = [ + "Window", + "Document", + "HtmlCanvasElement", + "CanvasRenderingContext2d", + "console", +] + + diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..f418c37 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1755615617, + "narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..3c06902 --- /dev/null +++ b/flake.nix @@ -0,0 +1,23 @@ +{ + description = "Rust Wasm Shell"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = { self, nixpkgs }: + let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + in { + devShells.${system}.default = pkgs.mkShell { + buildInputs = [ + pkgs.rustc + pkgs.cargo + pkgs.wasm-pack + pkgs.lld + pkgs.python3 + ]; + }; + }; +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..8701c32 --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + + + Rust WASM Game Window + + + + + + diff --git a/src/cga.rs b/src/cga.rs new file mode 100644 index 0000000..1d07707 --- /dev/null +++ b/src/cga.rs @@ -0,0 +1,1024 @@ +//Licensed from ganja.js (https://github.com/enkimute/ganja.js) under the MIT License +//Origin at: +//https://github.com/enkimute/ganja.js/blob/6e97cb45d780cd7c661d9240f1610eb005707417/codegen/rust/cga.rs + +// 3D Projective Geometric Algebra +// Written by a generator written by enki. +#![allow(unused_imports)] +#![allow(dead_code)] +#![allow(non_upper_case_globals)] +#![allow(non_snake_case)] +#![allow(non_camel_case_types)] +//#![feature(const_slice_len)] + +use std::fmt; +use std::ops::{Index,IndexMut,Add,Sub,Mul,BitAnd,BitOr,BitXor,Not}; + +type float_t = f64; + +// use std::f64::consts::PI; +const PI: float_t = 3.14159265358979323846; + +const basis: &'static [&'static str] = &[ "1","e1","e2","e3","e4","e5","e12","e13","e14","e15","e23","e24","e25","e34","e35","e45","e123","e124","e125","e134","e135","e145","e234","e235","e245","e345","e1234","e1235","e1245","e1345","e2345","e12345" ]; +const basis_count: usize = basis.len(); + +#[derive(Default,Debug,Clone,PartialEq)] +pub struct CGA { + mvec: Vec +} + +impl CGA { + pub fn zero() -> Self { + Self { + mvec: vec![0.0; basis_count] + } + } + + pub fn new(f: float_t, idx: usize) -> Self { + let mut ret = Self::zero(); + ret.mvec[idx] = f; + ret + } + + // basis vectors are available as methods + pub fn e1() -> Self { CGA::new(1.0, 1) } + pub fn e2() -> Self { CGA::new(1.0, 2) } + pub fn e3() -> Self { CGA::new(1.0, 3) } + pub fn e4() -> Self { CGA::new(1.0, 4) } + pub fn e5() -> Self { CGA::new(1.0, 5) } + pub fn e12() -> Self { CGA::new(1.0, 6) } + pub fn e13() -> Self { CGA::new(1.0, 7) } + pub fn e14() -> Self { CGA::new(1.0, 8) } + pub fn e15() -> Self { CGA::new(1.0, 9) } + pub fn e23() -> Self { CGA::new(1.0, 10) } + pub fn e24() -> Self { CGA::new(1.0, 11) } + pub fn e25() -> Self { CGA::new(1.0, 12) } + pub fn e34() -> Self { CGA::new(1.0, 13) } + pub fn e35() -> Self { CGA::new(1.0, 14) } + pub fn e45() -> Self { CGA::new(1.0, 15) } + pub fn e123() -> Self { CGA::new(1.0, 16) } + pub fn e124() -> Self { CGA::new(1.0, 17) } + pub fn e125() -> Self { CGA::new(1.0, 18) } + pub fn e134() -> Self { CGA::new(1.0, 19) } + pub fn e135() -> Self { CGA::new(1.0, 20) } + pub fn e145() -> Self { CGA::new(1.0, 21) } + pub fn e234() -> Self { CGA::new(1.0, 22) } + pub fn e235() -> Self { CGA::new(1.0, 23) } + pub fn e245() -> Self { CGA::new(1.0, 24) } + pub fn e345() -> Self { CGA::new(1.0, 25) } + pub fn e1234() -> Self { CGA::new(1.0, 26) } + pub fn e1235() -> Self { CGA::new(1.0, 27) } + pub fn e1245() -> Self { CGA::new(1.0, 28) } + pub fn e1345() -> Self { CGA::new(1.0, 29) } + pub fn e2345() -> Self { CGA::new(1.0, 30) } + pub fn e12345() -> Self { CGA::new(1.0, 31) } +} + +impl Index for CGA { + type Output = float_t; + + fn index<'a>(&'a self, index: usize) -> &'a Self::Output { + &self.mvec[index] + } +} + +impl IndexMut for CGA { + fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut Self::Output { + &mut self.mvec[index] + } +} + +impl fmt::Display for CGA { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut n = 0; + let ret = self.mvec.iter().enumerate().filter_map(|(i, &coeff)| { + if coeff > 0.00001 || coeff < -0.00001 { + n = 1; + Some(format!("{}{}", + format!("{:.*}", 7, coeff).trim_end_matches('0').trim_end_matches('.'), + if i > 0 { basis[i] } else { "" } + ) + ) + } else { + None + } + }).collect::>().join(" + "); + if n==0 { write!(f,"0") } else { write!(f, "{}", ret) } + } +} + +macro_rules! define_binary_op( + ( + // Operator, operator method, and scalar bounds. + $Op: ident, $op: ident; + // Argument identifiers and types + output. + $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Result: ty; + // Operator actual implementation. + $action: expr; + // Lifetime. + $($lives: tt),* + ) => { + impl<$($lives ,)*> $Op<$Rhs> for $Lhs { + type Output = $Result; + + #[inline] + fn $op($lhs, $rhs: $Rhs) -> Self::Output { + $action + } + } + } +); + +macro_rules! define_binary_op_all( + ( + // Operator, operator method, and scalar bounds. + $Op: ident, $op: ident; + // Argument identifiers and types + output. + $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Result: ty; + // Operators actual implementations. + [val val] => $action_val_val: expr; + [ref val] => $action_ref_val: expr; + [val ref] => $action_val_ref: expr; + [ref ref] => $action_ref_ref: expr; + ) => { + define_binary_op!( + $Op, $op; + $lhs: $Lhs, $rhs: $Rhs, Output = $Result; + $action_val_val; + ); + + define_binary_op!( + $Op, $op; + $lhs: &'a $Lhs, $rhs: $Rhs, Output = $Result; + $action_ref_val; + 'a + ); + + define_binary_op!( + $Op, $op; + $lhs: $Lhs, $rhs: &'b $Rhs, Output = $Result; + $action_val_ref; + 'b + ); + + define_binary_op!( + $Op, $op; + $lhs: &'a $Lhs, $rhs: &'b $Rhs, Output = $Result; + $action_ref_ref; + 'a, 'b + ); + } +); + +// TODO define_unary_op + + + +// Reverse +// Reverse the order of the basis blades. +impl CGA { + pub fn Reverse(self: & Self) -> CGA { + let mut res = CGA::zero(); + let a = self; + res[0]=a[0]; + res[1]=a[1]; + res[2]=a[2]; + res[3]=a[3]; + res[4]=a[4]; + res[5]=a[5]; + res[6]=-a[6]; + res[7]=-a[7]; + res[8]=-a[8]; + res[9]=-a[9]; + res[10]=-a[10]; + res[11]=-a[11]; + res[12]=-a[12]; + res[13]=-a[13]; + res[14]=-a[14]; + res[15]=-a[15]; + res[16]=-a[16]; + res[17]=-a[17]; + res[18]=-a[18]; + res[19]=-a[19]; + res[20]=-a[20]; + res[21]=-a[21]; + res[22]=-a[22]; + res[23]=-a[23]; + res[24]=-a[24]; + res[25]=-a[25]; + res[26]=a[26]; + res[27]=a[27]; + res[28]=a[28]; + res[29]=a[29]; + res[30]=a[30]; + res[31]=a[31]; + res + } +} + +// Dual +// Poincare duality operator. +impl CGA { + pub fn Dual(self: & Self) -> CGA { + let mut res = CGA::zero(); + let a = self; + res[0]=-a[31]; + res[1]=-a[30]; + res[2]=a[29]; + res[3]=-a[28]; + res[4]=a[27]; + res[5]=a[26]; + res[6]=a[25]; + res[7]=-a[24]; + res[8]=a[23]; + res[9]=a[22]; + res[10]=a[21]; + res[11]=-a[20]; + res[12]=-a[19]; + res[13]=a[18]; + res[14]=a[17]; + res[15]=-a[16]; + res[16]=a[15]; + res[17]=-a[14]; + res[18]=-a[13]; + res[19]=a[12]; + res[20]=a[11]; + res[21]=-a[10]; + res[22]=-a[9]; + res[23]=-a[8]; + res[24]=a[7]; + res[25]=-a[6]; + res[26]=-a[5]; + res[27]=-a[4]; + res[28]=a[3]; + res[29]=-a[2]; + res[30]=a[1]; + res[31]=a[0]; + res + } +} + +impl Not for & CGA { + type Output = CGA; + + fn not(self: Self) -> CGA { + let mut res = CGA::zero(); + let a = self; + res[0]=-a[31]; + res[1]=-a[30]; + res[2]=a[29]; + res[3]=-a[28]; + res[4]=a[27]; + res[5]=a[26]; + res[6]=a[25]; + res[7]=-a[24]; + res[8]=a[23]; + res[9]=a[22]; + res[10]=a[21]; + res[11]=-a[20]; + res[12]=-a[19]; + res[13]=a[18]; + res[14]=a[17]; + res[15]=-a[16]; + res[16]=a[15]; + res[17]=-a[14]; + res[18]=-a[13]; + res[19]=a[12]; + res[20]=a[11]; + res[21]=-a[10]; + res[22]=-a[9]; + res[23]=-a[8]; + res[24]=a[7]; + res[25]=-a[6]; + res[26]=-a[5]; + res[27]=-a[4]; + res[28]=a[3]; + res[29]=-a[2]; + res[30]=a[1]; + res[31]=a[0]; + res + } +} + +// Conjugate +// Clifford Conjugation +impl CGA { + pub fn Conjugate(self: & Self) -> CGA { + let mut res = CGA::zero(); + let a = self; + res[0]=a[0]; + res[1]=-a[1]; + res[2]=-a[2]; + res[3]=-a[3]; + res[4]=-a[4]; + res[5]=-a[5]; + res[6]=-a[6]; + res[7]=-a[7]; + res[8]=-a[8]; + res[9]=-a[9]; + res[10]=-a[10]; + res[11]=-a[11]; + res[12]=-a[12]; + res[13]=-a[13]; + res[14]=-a[14]; + res[15]=-a[15]; + res[16]=a[16]; + res[17]=a[17]; + res[18]=a[18]; + res[19]=a[19]; + res[20]=a[20]; + res[21]=a[21]; + res[22]=a[22]; + res[23]=a[23]; + res[24]=a[24]; + res[25]=a[25]; + res[26]=a[26]; + res[27]=a[27]; + res[28]=a[28]; + res[29]=a[29]; + res[30]=a[30]; + res[31]=-a[31]; + res + } +} + +// Involute +// Main involution +impl CGA { + pub fn Involute(self: & Self) -> CGA { + let mut res = CGA::zero(); + let a = self; + res[0]=a[0]; + res[1]=-a[1]; + res[2]=-a[2]; + res[3]=-a[3]; + res[4]=-a[4]; + res[5]=-a[5]; + res[6]=a[6]; + res[7]=a[7]; + res[8]=a[8]; + res[9]=a[9]; + res[10]=a[10]; + res[11]=a[11]; + res[12]=a[12]; + res[13]=a[13]; + res[14]=a[14]; + res[15]=a[15]; + res[16]=-a[16]; + res[17]=-a[17]; + res[18]=-a[18]; + res[19]=-a[19]; + res[20]=-a[20]; + res[21]=-a[21]; + res[22]=-a[22]; + res[23]=-a[23]; + res[24]=-a[24]; + res[25]=-a[25]; + res[26]=a[26]; + res[27]=a[27]; + res[28]=a[28]; + res[29]=a[29]; + res[30]=a[30]; + res[31]=-a[31]; + res + } +} + +// Mul +// The geometric product. + +define_binary_op_all!( + Mul, + mul; + self: CGA, b: CGA, Output = CGA; + [val val] => &self * &b; + [ref val] => self * &b; + [val ref] => &self * b; + [ref ref] => { + let mut res = CGA::zero(); + let a = self; + res[0]=b[0]*a[0]+b[1]*a[1]+b[2]*a[2]+b[3]*a[3]+b[4]*a[4]-b[5]*a[5]-b[6]*a[6]-b[7]*a[7]-b[8]*a[8]+b[9]*a[9]-b[10]*a[10]-b[11]*a[11]+b[12]*a[12]-b[13]*a[13]+b[14]*a[14]+b[15]*a[15]-b[16]*a[16]-b[17]*a[17]+b[18]*a[18]-b[19]*a[19]+b[20]*a[20]+b[21]*a[21]-b[22]*a[22]+b[23]*a[23]+b[24]*a[24]+b[25]*a[25]+b[26]*a[26]-b[27]*a[27]-b[28]*a[28]-b[29]*a[29]-b[30]*a[30]-b[31]*a[31]; + res[1]=b[1]*a[0]+b[0]*a[1]-b[6]*a[2]-b[7]*a[3]-b[8]*a[4]+b[9]*a[5]+b[2]*a[6]+b[3]*a[7]+b[4]*a[8]-b[5]*a[9]-b[16]*a[10]-b[17]*a[11]+b[18]*a[12]-b[19]*a[13]+b[20]*a[14]+b[21]*a[15]-b[10]*a[16]-b[11]*a[17]+b[12]*a[18]-b[13]*a[19]+b[14]*a[20]+b[15]*a[21]+b[26]*a[22]-b[27]*a[23]-b[28]*a[24]-b[29]*a[25]-b[22]*a[26]+b[23]*a[27]+b[24]*a[28]+b[25]*a[29]-b[31]*a[30]-b[30]*a[31]; + res[2]=b[2]*a[0]+b[6]*a[1]+b[0]*a[2]-b[10]*a[3]-b[11]*a[4]+b[12]*a[5]-b[1]*a[6]+b[16]*a[7]+b[17]*a[8]-b[18]*a[9]+b[3]*a[10]+b[4]*a[11]-b[5]*a[12]-b[22]*a[13]+b[23]*a[14]+b[24]*a[15]+b[7]*a[16]+b[8]*a[17]-b[9]*a[18]-b[26]*a[19]+b[27]*a[20]+b[28]*a[21]-b[13]*a[22]+b[14]*a[23]+b[15]*a[24]-b[30]*a[25]+b[19]*a[26]-b[20]*a[27]-b[21]*a[28]+b[31]*a[29]+b[25]*a[30]+b[29]*a[31]; + res[3]=b[3]*a[0]+b[7]*a[1]+b[10]*a[2]+b[0]*a[3]-b[13]*a[4]+b[14]*a[5]-b[16]*a[6]-b[1]*a[7]+b[19]*a[8]-b[20]*a[9]-b[2]*a[10]+b[22]*a[11]-b[23]*a[12]+b[4]*a[13]-b[5]*a[14]+b[25]*a[15]-b[6]*a[16]+b[26]*a[17]-b[27]*a[18]+b[8]*a[19]-b[9]*a[20]+b[29]*a[21]+b[11]*a[22]-b[12]*a[23]+b[30]*a[24]+b[15]*a[25]-b[17]*a[26]+b[18]*a[27]-b[31]*a[28]-b[21]*a[29]-b[24]*a[30]-b[28]*a[31]; + res[4]=b[4]*a[0]+b[8]*a[1]+b[11]*a[2]+b[13]*a[3]+b[0]*a[4]+b[15]*a[5]-b[17]*a[6]-b[19]*a[7]-b[1]*a[8]-b[21]*a[9]-b[22]*a[10]-b[2]*a[11]-b[24]*a[12]-b[3]*a[13]-b[25]*a[14]-b[5]*a[15]-b[26]*a[16]-b[6]*a[17]-b[28]*a[18]-b[7]*a[19]-b[29]*a[20]-b[9]*a[21]-b[10]*a[22]-b[30]*a[23]-b[12]*a[24]-b[14]*a[25]+b[16]*a[26]+b[31]*a[27]+b[18]*a[28]+b[20]*a[29]+b[23]*a[30]+b[27]*a[31]; + res[5]=b[5]*a[0]+b[9]*a[1]+b[12]*a[2]+b[14]*a[3]+b[15]*a[4]+b[0]*a[5]-b[18]*a[6]-b[20]*a[7]-b[21]*a[8]-b[1]*a[9]-b[23]*a[10]-b[24]*a[11]-b[2]*a[12]-b[25]*a[13]-b[3]*a[14]-b[4]*a[15]-b[27]*a[16]-b[28]*a[17]-b[6]*a[18]-b[29]*a[19]-b[7]*a[20]-b[8]*a[21]-b[30]*a[22]-b[10]*a[23]-b[11]*a[24]-b[13]*a[25]+b[31]*a[26]+b[16]*a[27]+b[17]*a[28]+b[19]*a[29]+b[22]*a[30]+b[26]*a[31]; + res[6]=b[6]*a[0]+b[2]*a[1]-b[1]*a[2]+b[16]*a[3]+b[17]*a[4]-b[18]*a[5]+b[0]*a[6]-b[10]*a[7]-b[11]*a[8]+b[12]*a[9]+b[7]*a[10]+b[8]*a[11]-b[9]*a[12]-b[26]*a[13]+b[27]*a[14]+b[28]*a[15]+b[3]*a[16]+b[4]*a[17]-b[5]*a[18]-b[22]*a[19]+b[23]*a[20]+b[24]*a[21]+b[19]*a[22]-b[20]*a[23]-b[21]*a[24]+b[31]*a[25]-b[13]*a[26]+b[14]*a[27]+b[15]*a[28]-b[30]*a[29]+b[29]*a[30]+b[25]*a[31]; + res[7]=b[7]*a[0]+b[3]*a[1]-b[16]*a[2]-b[1]*a[3]+b[19]*a[4]-b[20]*a[5]+b[10]*a[6]+b[0]*a[7]-b[13]*a[8]+b[14]*a[9]-b[6]*a[10]+b[26]*a[11]-b[27]*a[12]+b[8]*a[13]-b[9]*a[14]+b[29]*a[15]-b[2]*a[16]+b[22]*a[17]-b[23]*a[18]+b[4]*a[19]-b[5]*a[20]+b[25]*a[21]-b[17]*a[22]+b[18]*a[23]-b[31]*a[24]-b[21]*a[25]+b[11]*a[26]-b[12]*a[27]+b[30]*a[28]+b[15]*a[29]-b[28]*a[30]-b[24]*a[31]; + res[8]=b[8]*a[0]+b[4]*a[1]-b[17]*a[2]-b[19]*a[3]-b[1]*a[4]-b[21]*a[5]+b[11]*a[6]+b[13]*a[7]+b[0]*a[8]+b[15]*a[9]-b[26]*a[10]-b[6]*a[11]-b[28]*a[12]-b[7]*a[13]-b[29]*a[14]-b[9]*a[15]-b[22]*a[16]-b[2]*a[17]-b[24]*a[18]-b[3]*a[19]-b[25]*a[20]-b[5]*a[21]+b[16]*a[22]+b[31]*a[23]+b[18]*a[24]+b[20]*a[25]-b[10]*a[26]-b[30]*a[27]-b[12]*a[28]-b[14]*a[29]+b[27]*a[30]+b[23]*a[31]; + res[9]=b[9]*a[0]+b[5]*a[1]-b[18]*a[2]-b[20]*a[3]-b[21]*a[4]-b[1]*a[5]+b[12]*a[6]+b[14]*a[7]+b[15]*a[8]+b[0]*a[9]-b[27]*a[10]-b[28]*a[11]-b[6]*a[12]-b[29]*a[13]-b[7]*a[14]-b[8]*a[15]-b[23]*a[16]-b[24]*a[17]-b[2]*a[18]-b[25]*a[19]-b[3]*a[20]-b[4]*a[21]+b[31]*a[22]+b[16]*a[23]+b[17]*a[24]+b[19]*a[25]-b[30]*a[26]-b[10]*a[27]-b[11]*a[28]-b[13]*a[29]+b[26]*a[30]+b[22]*a[31]; + res[10]=b[10]*a[0]+b[16]*a[1]+b[3]*a[2]-b[2]*a[3]+b[22]*a[4]-b[23]*a[5]-b[7]*a[6]+b[6]*a[7]-b[26]*a[8]+b[27]*a[9]+b[0]*a[10]-b[13]*a[11]+b[14]*a[12]+b[11]*a[13]-b[12]*a[14]+b[30]*a[15]+b[1]*a[16]-b[19]*a[17]+b[20]*a[18]+b[17]*a[19]-b[18]*a[20]+b[31]*a[21]+b[4]*a[22]-b[5]*a[23]+b[25]*a[24]-b[24]*a[25]-b[8]*a[26]+b[9]*a[27]-b[29]*a[28]+b[28]*a[29]+b[15]*a[30]+b[21]*a[31]; + res[11]=b[11]*a[0]+b[17]*a[1]+b[4]*a[2]-b[22]*a[3]-b[2]*a[4]-b[24]*a[5]-b[8]*a[6]+b[26]*a[7]+b[6]*a[8]+b[28]*a[9]+b[13]*a[10]+b[0]*a[11]+b[15]*a[12]-b[10]*a[13]-b[30]*a[14]-b[12]*a[15]+b[19]*a[16]+b[1]*a[17]+b[21]*a[18]-b[16]*a[19]-b[31]*a[20]-b[18]*a[21]-b[3]*a[22]-b[25]*a[23]-b[5]*a[24]+b[23]*a[25]+b[7]*a[26]+b[29]*a[27]+b[9]*a[28]-b[27]*a[29]-b[14]*a[30]-b[20]*a[31]; + res[12]=b[12]*a[0]+b[18]*a[1]+b[5]*a[2]-b[23]*a[3]-b[24]*a[4]-b[2]*a[5]-b[9]*a[6]+b[27]*a[7]+b[28]*a[8]+b[6]*a[9]+b[14]*a[10]+b[15]*a[11]+b[0]*a[12]-b[30]*a[13]-b[10]*a[14]-b[11]*a[15]+b[20]*a[16]+b[21]*a[17]+b[1]*a[18]-b[31]*a[19]-b[16]*a[20]-b[17]*a[21]-b[25]*a[22]-b[3]*a[23]-b[4]*a[24]+b[22]*a[25]+b[29]*a[26]+b[7]*a[27]+b[8]*a[28]-b[26]*a[29]-b[13]*a[30]-b[19]*a[31]; + res[13]=b[13]*a[0]+b[19]*a[1]+b[22]*a[2]+b[4]*a[3]-b[3]*a[4]-b[25]*a[5]-b[26]*a[6]-b[8]*a[7]+b[7]*a[8]+b[29]*a[9]-b[11]*a[10]+b[10]*a[11]+b[30]*a[12]+b[0]*a[13]+b[15]*a[14]-b[14]*a[15]-b[17]*a[16]+b[16]*a[17]+b[31]*a[18]+b[1]*a[19]+b[21]*a[20]-b[20]*a[21]+b[2]*a[22]+b[24]*a[23]-b[23]*a[24]-b[5]*a[25]-b[6]*a[26]-b[28]*a[27]+b[27]*a[28]+b[9]*a[29]+b[12]*a[30]+b[18]*a[31]; + res[14]=b[14]*a[0]+b[20]*a[1]+b[23]*a[2]+b[5]*a[3]-b[25]*a[4]-b[3]*a[5]-b[27]*a[6]-b[9]*a[7]+b[29]*a[8]+b[7]*a[9]-b[12]*a[10]+b[30]*a[11]+b[10]*a[12]+b[15]*a[13]+b[0]*a[14]-b[13]*a[15]-b[18]*a[16]+b[31]*a[17]+b[16]*a[18]+b[21]*a[19]+b[1]*a[20]-b[19]*a[21]+b[24]*a[22]+b[2]*a[23]-b[22]*a[24]-b[4]*a[25]-b[28]*a[26]-b[6]*a[27]+b[26]*a[28]+b[8]*a[29]+b[11]*a[30]+b[17]*a[31]; + res[15]=b[15]*a[0]+b[21]*a[1]+b[24]*a[2]+b[25]*a[3]+b[5]*a[4]-b[4]*a[5]-b[28]*a[6]-b[29]*a[7]-b[9]*a[8]+b[8]*a[9]-b[30]*a[10]-b[12]*a[11]+b[11]*a[12]-b[14]*a[13]+b[13]*a[14]+b[0]*a[15]-b[31]*a[16]-b[18]*a[17]+b[17]*a[18]-b[20]*a[19]+b[19]*a[20]+b[1]*a[21]-b[23]*a[22]+b[22]*a[23]+b[2]*a[24]+b[3]*a[25]+b[27]*a[26]-b[26]*a[27]-b[6]*a[28]-b[7]*a[29]-b[10]*a[30]-b[16]*a[31]; + res[16]=b[16]*a[0]+b[10]*a[1]-b[7]*a[2]+b[6]*a[3]-b[26]*a[4]+b[27]*a[5]+b[3]*a[6]-b[2]*a[7]+b[22]*a[8]-b[23]*a[9]+b[1]*a[10]-b[19]*a[11]+b[20]*a[12]+b[17]*a[13]-b[18]*a[14]+b[31]*a[15]+b[0]*a[16]-b[13]*a[17]+b[14]*a[18]+b[11]*a[19]-b[12]*a[20]+b[30]*a[21]-b[8]*a[22]+b[9]*a[23]-b[29]*a[24]+b[28]*a[25]+b[4]*a[26]-b[5]*a[27]+b[25]*a[28]-b[24]*a[29]+b[21]*a[30]+b[15]*a[31]; + res[17]=b[17]*a[0]+b[11]*a[1]-b[8]*a[2]+b[26]*a[3]+b[6]*a[4]+b[28]*a[5]+b[4]*a[6]-b[22]*a[7]-b[2]*a[8]-b[24]*a[9]+b[19]*a[10]+b[1]*a[11]+b[21]*a[12]-b[16]*a[13]-b[31]*a[14]-b[18]*a[15]+b[13]*a[16]+b[0]*a[17]+b[15]*a[18]-b[10]*a[19]-b[30]*a[20]-b[12]*a[21]+b[7]*a[22]+b[29]*a[23]+b[9]*a[24]-b[27]*a[25]-b[3]*a[26]-b[25]*a[27]-b[5]*a[28]+b[23]*a[29]-b[20]*a[30]-b[14]*a[31]; + res[18]=b[18]*a[0]+b[12]*a[1]-b[9]*a[2]+b[27]*a[3]+b[28]*a[4]+b[6]*a[5]+b[5]*a[6]-b[23]*a[7]-b[24]*a[8]-b[2]*a[9]+b[20]*a[10]+b[21]*a[11]+b[1]*a[12]-b[31]*a[13]-b[16]*a[14]-b[17]*a[15]+b[14]*a[16]+b[15]*a[17]+b[0]*a[18]-b[30]*a[19]-b[10]*a[20]-b[11]*a[21]+b[29]*a[22]+b[7]*a[23]+b[8]*a[24]-b[26]*a[25]-b[25]*a[26]-b[3]*a[27]-b[4]*a[28]+b[22]*a[29]-b[19]*a[30]-b[13]*a[31]; + res[19]=b[19]*a[0]+b[13]*a[1]-b[26]*a[2]-b[8]*a[3]+b[7]*a[4]+b[29]*a[5]+b[22]*a[6]+b[4]*a[7]-b[3]*a[8]-b[25]*a[9]-b[17]*a[10]+b[16]*a[11]+b[31]*a[12]+b[1]*a[13]+b[21]*a[14]-b[20]*a[15]-b[11]*a[16]+b[10]*a[17]+b[30]*a[18]+b[0]*a[19]+b[15]*a[20]-b[14]*a[21]-b[6]*a[22]-b[28]*a[23]+b[27]*a[24]+b[9]*a[25]+b[2]*a[26]+b[24]*a[27]-b[23]*a[28]-b[5]*a[29]+b[18]*a[30]+b[12]*a[31]; + res[20]=b[20]*a[0]+b[14]*a[1]-b[27]*a[2]-b[9]*a[3]+b[29]*a[4]+b[7]*a[5]+b[23]*a[6]+b[5]*a[7]-b[25]*a[8]-b[3]*a[9]-b[18]*a[10]+b[31]*a[11]+b[16]*a[12]+b[21]*a[13]+b[1]*a[14]-b[19]*a[15]-b[12]*a[16]+b[30]*a[17]+b[10]*a[18]+b[15]*a[19]+b[0]*a[20]-b[13]*a[21]-b[28]*a[22]-b[6]*a[23]+b[26]*a[24]+b[8]*a[25]+b[24]*a[26]+b[2]*a[27]-b[22]*a[28]-b[4]*a[29]+b[17]*a[30]+b[11]*a[31]; + res[21]=b[21]*a[0]+b[15]*a[1]-b[28]*a[2]-b[29]*a[3]-b[9]*a[4]+b[8]*a[5]+b[24]*a[6]+b[25]*a[7]+b[5]*a[8]-b[4]*a[9]-b[31]*a[10]-b[18]*a[11]+b[17]*a[12]-b[20]*a[13]+b[19]*a[14]+b[1]*a[15]-b[30]*a[16]-b[12]*a[17]+b[11]*a[18]-b[14]*a[19]+b[13]*a[20]+b[0]*a[21]+b[27]*a[22]-b[26]*a[23]-b[6]*a[24]-b[7]*a[25]-b[23]*a[26]+b[22]*a[27]+b[2]*a[28]+b[3]*a[29]-b[16]*a[30]-b[10]*a[31]; + res[22]=b[22]*a[0]+b[26]*a[1]+b[13]*a[2]-b[11]*a[3]+b[10]*a[4]+b[30]*a[5]-b[19]*a[6]+b[17]*a[7]-b[16]*a[8]-b[31]*a[9]+b[4]*a[10]-b[3]*a[11]-b[25]*a[12]+b[2]*a[13]+b[24]*a[14]-b[23]*a[15]+b[8]*a[16]-b[7]*a[17]-b[29]*a[18]+b[6]*a[19]+b[28]*a[20]-b[27]*a[21]+b[0]*a[22]+b[15]*a[23]-b[14]*a[24]+b[12]*a[25]-b[1]*a[26]-b[21]*a[27]+b[20]*a[28]-b[18]*a[29]-b[5]*a[30]-b[9]*a[31]; + res[23]=b[23]*a[0]+b[27]*a[1]+b[14]*a[2]-b[12]*a[3]+b[30]*a[4]+b[10]*a[5]-b[20]*a[6]+b[18]*a[7]-b[31]*a[8]-b[16]*a[9]+b[5]*a[10]-b[25]*a[11]-b[3]*a[12]+b[24]*a[13]+b[2]*a[14]-b[22]*a[15]+b[9]*a[16]-b[29]*a[17]-b[7]*a[18]+b[28]*a[19]+b[6]*a[20]-b[26]*a[21]+b[15]*a[22]+b[0]*a[23]-b[13]*a[24]+b[11]*a[25]-b[21]*a[26]-b[1]*a[27]+b[19]*a[28]-b[17]*a[29]-b[4]*a[30]-b[8]*a[31]; + res[24]=b[24]*a[0]+b[28]*a[1]+b[15]*a[2]-b[30]*a[3]-b[12]*a[4]+b[11]*a[5]-b[21]*a[6]+b[31]*a[7]+b[18]*a[8]-b[17]*a[9]+b[25]*a[10]+b[5]*a[11]-b[4]*a[12]-b[23]*a[13]+b[22]*a[14]+b[2]*a[15]+b[29]*a[16]+b[9]*a[17]-b[8]*a[18]-b[27]*a[19]+b[26]*a[20]+b[6]*a[21]-b[14]*a[22]+b[13]*a[23]+b[0]*a[24]-b[10]*a[25]+b[20]*a[26]-b[19]*a[27]-b[1]*a[28]+b[16]*a[29]+b[3]*a[30]+b[7]*a[31]; + res[25]=b[25]*a[0]+b[29]*a[1]+b[30]*a[2]+b[15]*a[3]-b[14]*a[4]+b[13]*a[5]-b[31]*a[6]-b[21]*a[7]+b[20]*a[8]-b[19]*a[9]-b[24]*a[10]+b[23]*a[11]-b[22]*a[12]+b[5]*a[13]-b[4]*a[14]+b[3]*a[15]-b[28]*a[16]+b[27]*a[17]-b[26]*a[18]+b[9]*a[19]-b[8]*a[20]+b[7]*a[21]+b[12]*a[22]-b[11]*a[23]+b[10]*a[24]+b[0]*a[25]-b[18]*a[26]+b[17]*a[27]-b[16]*a[28]-b[1]*a[29]-b[2]*a[30]-b[6]*a[31]; + res[26]=b[26]*a[0]+b[22]*a[1]-b[19]*a[2]+b[17]*a[3]-b[16]*a[4]-b[31]*a[5]+b[13]*a[6]-b[11]*a[7]+b[10]*a[8]+b[30]*a[9]+b[8]*a[10]-b[7]*a[11]-b[29]*a[12]+b[6]*a[13]+b[28]*a[14]-b[27]*a[15]+b[4]*a[16]-b[3]*a[17]-b[25]*a[18]+b[2]*a[19]+b[24]*a[20]-b[23]*a[21]-b[1]*a[22]-b[21]*a[23]+b[20]*a[24]-b[18]*a[25]+b[0]*a[26]+b[15]*a[27]-b[14]*a[28]+b[12]*a[29]-b[9]*a[30]-b[5]*a[31]; + res[27]=b[27]*a[0]+b[23]*a[1]-b[20]*a[2]+b[18]*a[3]-b[31]*a[4]-b[16]*a[5]+b[14]*a[6]-b[12]*a[7]+b[30]*a[8]+b[10]*a[9]+b[9]*a[10]-b[29]*a[11]-b[7]*a[12]+b[28]*a[13]+b[6]*a[14]-b[26]*a[15]+b[5]*a[16]-b[25]*a[17]-b[3]*a[18]+b[24]*a[19]+b[2]*a[20]-b[22]*a[21]-b[21]*a[22]-b[1]*a[23]+b[19]*a[24]-b[17]*a[25]+b[15]*a[26]+b[0]*a[27]-b[13]*a[28]+b[11]*a[29]-b[8]*a[30]-b[4]*a[31]; + res[28]=b[28]*a[0]+b[24]*a[1]-b[21]*a[2]+b[31]*a[3]+b[18]*a[4]-b[17]*a[5]+b[15]*a[6]-b[30]*a[7]-b[12]*a[8]+b[11]*a[9]+b[29]*a[10]+b[9]*a[11]-b[8]*a[12]-b[27]*a[13]+b[26]*a[14]+b[6]*a[15]+b[25]*a[16]+b[5]*a[17]-b[4]*a[18]-b[23]*a[19]+b[22]*a[20]+b[2]*a[21]+b[20]*a[22]-b[19]*a[23]-b[1]*a[24]+b[16]*a[25]-b[14]*a[26]+b[13]*a[27]+b[0]*a[28]-b[10]*a[29]+b[7]*a[30]+b[3]*a[31]; + res[29]=b[29]*a[0]+b[25]*a[1]-b[31]*a[2]-b[21]*a[3]+b[20]*a[4]-b[19]*a[5]+b[30]*a[6]+b[15]*a[7]-b[14]*a[8]+b[13]*a[9]-b[28]*a[10]+b[27]*a[11]-b[26]*a[12]+b[9]*a[13]-b[8]*a[14]+b[7]*a[15]-b[24]*a[16]+b[23]*a[17]-b[22]*a[18]+b[5]*a[19]-b[4]*a[20]+b[3]*a[21]-b[18]*a[22]+b[17]*a[23]-b[16]*a[24]-b[1]*a[25]+b[12]*a[26]-b[11]*a[27]+b[10]*a[28]+b[0]*a[29]-b[6]*a[30]-b[2]*a[31]; + res[30]=b[30]*a[0]+b[31]*a[1]+b[25]*a[2]-b[24]*a[3]+b[23]*a[4]-b[22]*a[5]-b[29]*a[6]+b[28]*a[7]-b[27]*a[8]+b[26]*a[9]+b[15]*a[10]-b[14]*a[11]+b[13]*a[12]+b[12]*a[13]-b[11]*a[14]+b[10]*a[15]+b[21]*a[16]-b[20]*a[17]+b[19]*a[18]+b[18]*a[19]-b[17]*a[20]+b[16]*a[21]+b[5]*a[22]-b[4]*a[23]+b[3]*a[24]-b[2]*a[25]-b[9]*a[26]+b[8]*a[27]-b[7]*a[28]+b[6]*a[29]+b[0]*a[30]+b[1]*a[31]; + res[31]=b[31]*a[0]+b[30]*a[1]-b[29]*a[2]+b[28]*a[3]-b[27]*a[4]+b[26]*a[5]+b[25]*a[6]-b[24]*a[7]+b[23]*a[8]-b[22]*a[9]+b[21]*a[10]-b[20]*a[11]+b[19]*a[12]+b[18]*a[13]-b[17]*a[14]+b[16]*a[15]+b[15]*a[16]-b[14]*a[17]+b[13]*a[18]+b[12]*a[19]-b[11]*a[20]+b[10]*a[21]-b[9]*a[22]+b[8]*a[23]-b[7]*a[24]+b[6]*a[25]+b[5]*a[26]-b[4]*a[27]+b[3]*a[28]-b[2]*a[29]+b[1]*a[30]+b[0]*a[31]; + res + }; +); + + +// Wedge +// The outer product. (MEET) + +define_binary_op_all!( + BitXor, + bitxor; + self: CGA, b: CGA, Output = CGA; + [val val] => &self ^ &b; + [ref val] => self ^ &b; + [val ref] => &self ^ b; + [ref ref] => { + let mut res = CGA::zero(); + let a = self; + res[0]=b[0]*a[0]; + res[1]=b[1]*a[0]+b[0]*a[1]; + res[2]=b[2]*a[0]+b[0]*a[2]; + res[3]=b[3]*a[0]+b[0]*a[3]; + res[4]=b[4]*a[0]+b[0]*a[4]; + res[5]=b[5]*a[0]+b[0]*a[5]; + res[6]=b[6]*a[0]+b[2]*a[1]-b[1]*a[2]+b[0]*a[6]; + res[7]=b[7]*a[0]+b[3]*a[1]-b[1]*a[3]+b[0]*a[7]; + res[8]=b[8]*a[0]+b[4]*a[1]-b[1]*a[4]+b[0]*a[8]; + res[9]=b[9]*a[0]+b[5]*a[1]-b[1]*a[5]+b[0]*a[9]; + res[10]=b[10]*a[0]+b[3]*a[2]-b[2]*a[3]+b[0]*a[10]; + res[11]=b[11]*a[0]+b[4]*a[2]-b[2]*a[4]+b[0]*a[11]; + res[12]=b[12]*a[0]+b[5]*a[2]-b[2]*a[5]+b[0]*a[12]; + res[13]=b[13]*a[0]+b[4]*a[3]-b[3]*a[4]+b[0]*a[13]; + res[14]=b[14]*a[0]+b[5]*a[3]-b[3]*a[5]+b[0]*a[14]; + res[15]=b[15]*a[0]+b[5]*a[4]-b[4]*a[5]+b[0]*a[15]; + res[16]=b[16]*a[0]+b[10]*a[1]-b[7]*a[2]+b[6]*a[3]+b[3]*a[6]-b[2]*a[7]+b[1]*a[10]+b[0]*a[16]; + res[17]=b[17]*a[0]+b[11]*a[1]-b[8]*a[2]+b[6]*a[4]+b[4]*a[6]-b[2]*a[8]+b[1]*a[11]+b[0]*a[17]; + res[18]=b[18]*a[0]+b[12]*a[1]-b[9]*a[2]+b[6]*a[5]+b[5]*a[6]-b[2]*a[9]+b[1]*a[12]+b[0]*a[18]; + res[19]=b[19]*a[0]+b[13]*a[1]-b[8]*a[3]+b[7]*a[4]+b[4]*a[7]-b[3]*a[8]+b[1]*a[13]+b[0]*a[19]; + res[20]=b[20]*a[0]+b[14]*a[1]-b[9]*a[3]+b[7]*a[5]+b[5]*a[7]-b[3]*a[9]+b[1]*a[14]+b[0]*a[20]; + res[21]=b[21]*a[0]+b[15]*a[1]-b[9]*a[4]+b[8]*a[5]+b[5]*a[8]-b[4]*a[9]+b[1]*a[15]+b[0]*a[21]; + res[22]=b[22]*a[0]+b[13]*a[2]-b[11]*a[3]+b[10]*a[4]+b[4]*a[10]-b[3]*a[11]+b[2]*a[13]+b[0]*a[22]; + res[23]=b[23]*a[0]+b[14]*a[2]-b[12]*a[3]+b[10]*a[5]+b[5]*a[10]-b[3]*a[12]+b[2]*a[14]+b[0]*a[23]; + res[24]=b[24]*a[0]+b[15]*a[2]-b[12]*a[4]+b[11]*a[5]+b[5]*a[11]-b[4]*a[12]+b[2]*a[15]+b[0]*a[24]; + res[25]=b[25]*a[0]+b[15]*a[3]-b[14]*a[4]+b[13]*a[5]+b[5]*a[13]-b[4]*a[14]+b[3]*a[15]+b[0]*a[25]; + res[26]=b[26]*a[0]+b[22]*a[1]-b[19]*a[2]+b[17]*a[3]-b[16]*a[4]+b[13]*a[6]-b[11]*a[7]+b[10]*a[8]+b[8]*a[10]-b[7]*a[11]+b[6]*a[13]+b[4]*a[16]-b[3]*a[17]+b[2]*a[19]-b[1]*a[22]+b[0]*a[26]; + res[27]=b[27]*a[0]+b[23]*a[1]-b[20]*a[2]+b[18]*a[3]-b[16]*a[5]+b[14]*a[6]-b[12]*a[7]+b[10]*a[9]+b[9]*a[10]-b[7]*a[12]+b[6]*a[14]+b[5]*a[16]-b[3]*a[18]+b[2]*a[20]-b[1]*a[23]+b[0]*a[27]; + res[28]=b[28]*a[0]+b[24]*a[1]-b[21]*a[2]+b[18]*a[4]-b[17]*a[5]+b[15]*a[6]-b[12]*a[8]+b[11]*a[9]+b[9]*a[11]-b[8]*a[12]+b[6]*a[15]+b[5]*a[17]-b[4]*a[18]+b[2]*a[21]-b[1]*a[24]+b[0]*a[28]; + res[29]=b[29]*a[0]+b[25]*a[1]-b[21]*a[3]+b[20]*a[4]-b[19]*a[5]+b[15]*a[7]-b[14]*a[8]+b[13]*a[9]+b[9]*a[13]-b[8]*a[14]+b[7]*a[15]+b[5]*a[19]-b[4]*a[20]+b[3]*a[21]-b[1]*a[25]+b[0]*a[29]; + res[30]=b[30]*a[0]+b[25]*a[2]-b[24]*a[3]+b[23]*a[4]-b[22]*a[5]+b[15]*a[10]-b[14]*a[11]+b[13]*a[12]+b[12]*a[13]-b[11]*a[14]+b[10]*a[15]+b[5]*a[22]-b[4]*a[23]+b[3]*a[24]-b[2]*a[25]+b[0]*a[30]; + res[31]=b[31]*a[0]+b[30]*a[1]-b[29]*a[2]+b[28]*a[3]-b[27]*a[4]+b[26]*a[5]+b[25]*a[6]-b[24]*a[7]+b[23]*a[8]-b[22]*a[9]+b[21]*a[10]-b[20]*a[11]+b[19]*a[12]+b[18]*a[13]-b[17]*a[14]+b[16]*a[15]+b[15]*a[16]-b[14]*a[17]+b[13]*a[18]+b[12]*a[19]-b[11]*a[20]+b[10]*a[21]-b[9]*a[22]+b[8]*a[23]-b[7]*a[24]+b[6]*a[25]+b[5]*a[26]-b[4]*a[27]+b[3]*a[28]-b[2]*a[29]+b[1]*a[30]+b[0]*a[31]; + res + }; +); + + +// Vee +// The regressive product. (JOIN) + +define_binary_op_all!( + BitAnd, + bitand; + self: CGA, b: CGA, Output = CGA; + [val val] => &self & &b; + [ref val] => self & &b; + [val ref] => &self & b; + [ref ref] => { + let mut res = CGA::zero(); + let a = self; + res[31]=a[31]*b[31]; + res[30]=a[30]*b[31]+a[31]*b[30]; + res[29]=-(a[29]*-b[31]+a[31]*b[29]*-1.0); + res[28]=a[28]*b[31]+a[31]*b[28]; + res[27]=-(a[27]*-b[31]+a[31]*b[27]*-1.0); + res[26]=a[26]*b[31]+a[31]*b[26]; + res[25]=a[25]*b[31]+a[29]*-b[30]-a[30]*b[29]*-1.0+a[31]*b[25]; + res[24]=-(a[24]*-b[31]+a[28]*b[30]-a[30]*b[28]+a[31]*b[24]*-1.0); + res[23]=a[23]*b[31]+a[27]*-b[30]-a[30]*b[27]*-1.0+a[31]*b[23]; + res[22]=-(a[22]*-b[31]+a[26]*b[30]-a[30]*b[26]+a[31]*b[22]*-1.0); + res[21]=a[21]*b[31]+a[28]*b[29]*-1.0-a[29]*-b[28]+a[31]*b[21]; + res[20]=-(a[20]*-b[31]+a[27]*-b[29]*-1.0-a[29]*-b[27]*-1.0+a[31]*b[20]*-1.0); + res[19]=a[19]*b[31]+a[26]*b[29]*-1.0-a[29]*-b[26]+a[31]*b[19]; + res[18]=a[18]*b[31]+a[27]*-b[28]-a[28]*b[27]*-1.0+a[31]*b[18]; + res[17]=-(a[17]*-b[31]+a[26]*b[28]-a[28]*b[26]+a[31]*b[17]*-1.0); + res[16]=a[16]*b[31]+a[26]*b[27]*-1.0-a[27]*-b[26]+a[31]*b[16]; + res[15]=a[15]*b[31]+a[21]*b[30]-a[24]*-b[29]*-1.0+a[25]*b[28]+a[28]*b[25]-a[29]*-b[24]*-1.0+a[30]*b[21]+a[31]*b[15]; + res[14]=-(a[14]*-b[31]+a[20]*-b[30]-a[23]*b[29]*-1.0+a[25]*b[27]*-1.0+a[27]*-b[25]-a[29]*-b[23]+a[30]*b[20]*-1.0+a[31]*b[14]*-1.0); + res[13]=a[13]*b[31]+a[19]*b[30]-a[22]*-b[29]*-1.0+a[25]*b[26]+a[26]*b[25]-a[29]*-b[22]*-1.0+a[30]*b[19]+a[31]*b[13]; + res[12]=a[12]*b[31]+a[18]*b[30]-a[23]*b[28]+a[24]*-b[27]*-1.0+a[27]*-b[24]*-1.0-a[28]*b[23]+a[30]*b[18]+a[31]*b[12]; + res[11]=-(a[11]*-b[31]+a[17]*-b[30]-a[22]*-b[28]+a[24]*-b[26]+a[26]*b[24]*-1.0-a[28]*b[22]*-1.0+a[30]*b[17]*-1.0+a[31]*b[11]*-1.0); + res[10]=a[10]*b[31]+a[16]*b[30]-a[22]*-b[27]*-1.0+a[23]*b[26]+a[26]*b[23]-a[27]*-b[22]*-1.0+a[30]*b[16]+a[31]*b[10]; + res[9]=-(a[9]*-b[31]+a[18]*b[29]*-1.0-a[20]*-b[28]+a[21]*b[27]*-1.0+a[27]*-b[21]-a[28]*b[20]*-1.0+a[29]*-b[18]+a[31]*b[9]*-1.0); + res[8]=a[8]*b[31]+a[17]*-b[29]*-1.0-a[19]*b[28]+a[21]*b[26]+a[26]*b[21]-a[28]*b[19]+a[29]*-b[17]*-1.0+a[31]*b[8]; + res[7]=-(a[7]*-b[31]+a[16]*b[29]*-1.0-a[19]*b[27]*-1.0+a[20]*-b[26]+a[26]*b[20]*-1.0-a[27]*-b[19]+a[29]*-b[16]+a[31]*b[7]*-1.0); + res[6]=a[6]*b[31]+a[16]*b[28]-a[17]*-b[27]*-1.0+a[18]*b[26]+a[26]*b[18]-a[27]*-b[17]*-1.0+a[28]*b[16]+a[31]*b[6]; + res[5]=a[5]*b[31]+a[9]*-b[30]-a[12]*b[29]*-1.0+a[14]*-b[28]-a[15]*b[27]*-1.0+a[18]*b[25]-a[20]*-b[24]*-1.0+a[21]*b[23]+a[23]*b[21]-a[24]*-b[20]*-1.0+a[25]*b[18]+a[27]*-b[15]-a[28]*b[14]*-1.0+a[29]*-b[12]-a[30]*b[9]*-1.0+a[31]*b[5]; + res[4]=-(a[4]*-b[31]+a[8]*b[30]-a[11]*-b[29]*-1.0+a[13]*b[28]-a[15]*b[26]+a[17]*-b[25]-a[19]*b[24]*-1.0+a[21]*b[22]*-1.0+a[22]*-b[21]-a[24]*-b[19]+a[25]*b[17]*-1.0+a[26]*b[15]-a[28]*b[13]+a[29]*-b[11]*-1.0-a[30]*b[8]+a[31]*b[4]*-1.0); + res[3]=a[3]*b[31]+a[7]*-b[30]-a[10]*b[29]*-1.0+a[13]*b[27]*-1.0-a[14]*-b[26]+a[16]*b[25]-a[19]*b[23]+a[20]*-b[22]*-1.0+a[22]*-b[20]*-1.0-a[23]*b[19]+a[25]*b[16]+a[26]*b[14]*-1.0-a[27]*-b[13]+a[29]*-b[10]-a[30]*b[7]*-1.0+a[31]*b[3]; + res[2]=-(a[2]*-b[31]+a[6]*b[30]-a[10]*b[28]+a[11]*-b[27]*-1.0-a[12]*b[26]+a[16]*b[24]*-1.0-a[17]*-b[23]+a[18]*b[22]*-1.0+a[22]*-b[18]-a[23]*b[17]*-1.0+a[24]*-b[16]+a[26]*b[12]-a[27]*-b[11]*-1.0+a[28]*b[10]-a[30]*b[6]+a[31]*b[2]*-1.0); + res[1]=a[1]*b[31]+a[6]*b[29]*-1.0-a[7]*-b[28]+a[8]*b[27]*-1.0-a[9]*-b[26]+a[16]*b[21]-a[17]*-b[20]*-1.0+a[18]*b[19]+a[19]*b[18]-a[20]*-b[17]*-1.0+a[21]*b[16]+a[26]*b[9]*-1.0-a[27]*-b[8]+a[28]*b[7]*-1.0-a[29]*-b[6]+a[31]*b[1]; + res[0]=a[0]*b[31]+a[1]*b[30]-a[2]*-b[29]*-1.0+a[3]*b[28]-a[4]*-b[27]*-1.0+a[5]*b[26]+a[6]*b[25]-a[7]*-b[24]*-1.0+a[8]*b[23]-a[9]*-b[22]*-1.0+a[10]*b[21]-a[11]*-b[20]*-1.0+a[12]*b[19]+a[13]*b[18]-a[14]*-b[17]*-1.0+a[15]*b[16]+a[16]*b[15]-a[17]*-b[14]*-1.0+a[18]*b[13]+a[19]*b[12]-a[20]*-b[11]*-1.0+a[21]*b[10]-a[22]*-b[9]*-1.0+a[23]*b[8]-a[24]*-b[7]*-1.0+a[25]*b[6]+a[26]*b[5]-a[27]*-b[4]*-1.0+a[28]*b[3]-a[29]*-b[2]*-1.0+a[30]*b[1]+a[31]*b[0]; + res + }; +); + + +// Dot +// The inner product. + +define_binary_op_all!( + BitOr, + bitor; + self: CGA, b: CGA, Output = CGA; + [val val] => &self | &b; + [ref val] => self | &b; + [val ref] => &self | b; + [ref ref] => { + let mut res = CGA::zero(); + let a = self; + res[0]=b[0]*a[0]+b[1]*a[1]+b[2]*a[2]+b[3]*a[3]+b[4]*a[4]-b[5]*a[5]-b[6]*a[6]-b[7]*a[7]-b[8]*a[8]+b[9]*a[9]-b[10]*a[10]-b[11]*a[11]+b[12]*a[12]-b[13]*a[13]+b[14]*a[14]+b[15]*a[15]-b[16]*a[16]-b[17]*a[17]+b[18]*a[18]-b[19]*a[19]+b[20]*a[20]+b[21]*a[21]-b[22]*a[22]+b[23]*a[23]+b[24]*a[24]+b[25]*a[25]+b[26]*a[26]-b[27]*a[27]-b[28]*a[28]-b[29]*a[29]-b[30]*a[30]-b[31]*a[31]; + res[1]=b[1]*a[0]+b[0]*a[1]-b[6]*a[2]-b[7]*a[3]-b[8]*a[4]+b[9]*a[5]+b[2]*a[6]+b[3]*a[7]+b[4]*a[8]-b[5]*a[9]-b[16]*a[10]-b[17]*a[11]+b[18]*a[12]-b[19]*a[13]+b[20]*a[14]+b[21]*a[15]-b[10]*a[16]-b[11]*a[17]+b[12]*a[18]-b[13]*a[19]+b[14]*a[20]+b[15]*a[21]+b[26]*a[22]-b[27]*a[23]-b[28]*a[24]-b[29]*a[25]-b[22]*a[26]+b[23]*a[27]+b[24]*a[28]+b[25]*a[29]-b[31]*a[30]-b[30]*a[31]; + res[2]=b[2]*a[0]+b[6]*a[1]+b[0]*a[2]-b[10]*a[3]-b[11]*a[4]+b[12]*a[5]-b[1]*a[6]+b[16]*a[7]+b[17]*a[8]-b[18]*a[9]+b[3]*a[10]+b[4]*a[11]-b[5]*a[12]-b[22]*a[13]+b[23]*a[14]+b[24]*a[15]+b[7]*a[16]+b[8]*a[17]-b[9]*a[18]-b[26]*a[19]+b[27]*a[20]+b[28]*a[21]-b[13]*a[22]+b[14]*a[23]+b[15]*a[24]-b[30]*a[25]+b[19]*a[26]-b[20]*a[27]-b[21]*a[28]+b[31]*a[29]+b[25]*a[30]+b[29]*a[31]; + res[3]=b[3]*a[0]+b[7]*a[1]+b[10]*a[2]+b[0]*a[3]-b[13]*a[4]+b[14]*a[5]-b[16]*a[6]-b[1]*a[7]+b[19]*a[8]-b[20]*a[9]-b[2]*a[10]+b[22]*a[11]-b[23]*a[12]+b[4]*a[13]-b[5]*a[14]+b[25]*a[15]-b[6]*a[16]+b[26]*a[17]-b[27]*a[18]+b[8]*a[19]-b[9]*a[20]+b[29]*a[21]+b[11]*a[22]-b[12]*a[23]+b[30]*a[24]+b[15]*a[25]-b[17]*a[26]+b[18]*a[27]-b[31]*a[28]-b[21]*a[29]-b[24]*a[30]-b[28]*a[31]; + res[4]=b[4]*a[0]+b[8]*a[1]+b[11]*a[2]+b[13]*a[3]+b[0]*a[4]+b[15]*a[5]-b[17]*a[6]-b[19]*a[7]-b[1]*a[8]-b[21]*a[9]-b[22]*a[10]-b[2]*a[11]-b[24]*a[12]-b[3]*a[13]-b[25]*a[14]-b[5]*a[15]-b[26]*a[16]-b[6]*a[17]-b[28]*a[18]-b[7]*a[19]-b[29]*a[20]-b[9]*a[21]-b[10]*a[22]-b[30]*a[23]-b[12]*a[24]-b[14]*a[25]+b[16]*a[26]+b[31]*a[27]+b[18]*a[28]+b[20]*a[29]+b[23]*a[30]+b[27]*a[31]; + res[5]=b[5]*a[0]+b[9]*a[1]+b[12]*a[2]+b[14]*a[3]+b[15]*a[4]+b[0]*a[5]-b[18]*a[6]-b[20]*a[7]-b[21]*a[8]-b[1]*a[9]-b[23]*a[10]-b[24]*a[11]-b[2]*a[12]-b[25]*a[13]-b[3]*a[14]-b[4]*a[15]-b[27]*a[16]-b[28]*a[17]-b[6]*a[18]-b[29]*a[19]-b[7]*a[20]-b[8]*a[21]-b[30]*a[22]-b[10]*a[23]-b[11]*a[24]-b[13]*a[25]+b[31]*a[26]+b[16]*a[27]+b[17]*a[28]+b[19]*a[29]+b[22]*a[30]+b[26]*a[31]; + res[6]=b[6]*a[0]+b[16]*a[3]+b[17]*a[4]-b[18]*a[5]+b[0]*a[6]-b[26]*a[13]+b[27]*a[14]+b[28]*a[15]+b[3]*a[16]+b[4]*a[17]-b[5]*a[18]+b[31]*a[25]-b[13]*a[26]+b[14]*a[27]+b[15]*a[28]+b[25]*a[31]; + res[7]=b[7]*a[0]-b[16]*a[2]+b[19]*a[4]-b[20]*a[5]+b[0]*a[7]+b[26]*a[11]-b[27]*a[12]+b[29]*a[15]-b[2]*a[16]+b[4]*a[19]-b[5]*a[20]-b[31]*a[24]+b[11]*a[26]-b[12]*a[27]+b[15]*a[29]-b[24]*a[31]; + res[8]=b[8]*a[0]-b[17]*a[2]-b[19]*a[3]-b[21]*a[5]+b[0]*a[8]-b[26]*a[10]-b[28]*a[12]-b[29]*a[14]-b[2]*a[17]-b[3]*a[19]-b[5]*a[21]+b[31]*a[23]-b[10]*a[26]-b[12]*a[28]-b[14]*a[29]+b[23]*a[31]; + res[9]=b[9]*a[0]-b[18]*a[2]-b[20]*a[3]-b[21]*a[4]+b[0]*a[9]-b[27]*a[10]-b[28]*a[11]-b[29]*a[13]-b[2]*a[18]-b[3]*a[20]-b[4]*a[21]+b[31]*a[22]-b[10]*a[27]-b[11]*a[28]-b[13]*a[29]+b[22]*a[31]; + res[10]=b[10]*a[0]+b[16]*a[1]+b[22]*a[4]-b[23]*a[5]-b[26]*a[8]+b[27]*a[9]+b[0]*a[10]+b[30]*a[15]+b[1]*a[16]+b[31]*a[21]+b[4]*a[22]-b[5]*a[23]-b[8]*a[26]+b[9]*a[27]+b[15]*a[30]+b[21]*a[31]; + res[11]=b[11]*a[0]+b[17]*a[1]-b[22]*a[3]-b[24]*a[5]+b[26]*a[7]+b[28]*a[9]+b[0]*a[11]-b[30]*a[14]+b[1]*a[17]-b[31]*a[20]-b[3]*a[22]-b[5]*a[24]+b[7]*a[26]+b[9]*a[28]-b[14]*a[30]-b[20]*a[31]; + res[12]=b[12]*a[0]+b[18]*a[1]-b[23]*a[3]-b[24]*a[4]+b[27]*a[7]+b[28]*a[8]+b[0]*a[12]-b[30]*a[13]+b[1]*a[18]-b[31]*a[19]-b[3]*a[23]-b[4]*a[24]+b[7]*a[27]+b[8]*a[28]-b[13]*a[30]-b[19]*a[31]; + res[13]=b[13]*a[0]+b[19]*a[1]+b[22]*a[2]-b[25]*a[5]-b[26]*a[6]+b[29]*a[9]+b[30]*a[12]+b[0]*a[13]+b[31]*a[18]+b[1]*a[19]+b[2]*a[22]-b[5]*a[25]-b[6]*a[26]+b[9]*a[29]+b[12]*a[30]+b[18]*a[31]; + res[14]=b[14]*a[0]+b[20]*a[1]+b[23]*a[2]-b[25]*a[4]-b[27]*a[6]+b[29]*a[8]+b[30]*a[11]+b[0]*a[14]+b[31]*a[17]+b[1]*a[20]+b[2]*a[23]-b[4]*a[25]-b[6]*a[27]+b[8]*a[29]+b[11]*a[30]+b[17]*a[31]; + res[15]=b[15]*a[0]+b[21]*a[1]+b[24]*a[2]+b[25]*a[3]-b[28]*a[6]-b[29]*a[7]-b[30]*a[10]+b[0]*a[15]-b[31]*a[16]+b[1]*a[21]+b[2]*a[24]+b[3]*a[25]-b[6]*a[28]-b[7]*a[29]-b[10]*a[30]-b[16]*a[31]; + res[16]=b[16]*a[0]-b[26]*a[4]+b[27]*a[5]+b[31]*a[15]+b[0]*a[16]+b[4]*a[26]-b[5]*a[27]+b[15]*a[31]; + res[17]=b[17]*a[0]+b[26]*a[3]+b[28]*a[5]-b[31]*a[14]+b[0]*a[17]-b[3]*a[26]-b[5]*a[28]-b[14]*a[31]; + res[18]=b[18]*a[0]+b[27]*a[3]+b[28]*a[4]-b[31]*a[13]+b[0]*a[18]-b[3]*a[27]-b[4]*a[28]-b[13]*a[31]; + res[19]=b[19]*a[0]-b[26]*a[2]+b[29]*a[5]+b[31]*a[12]+b[0]*a[19]+b[2]*a[26]-b[5]*a[29]+b[12]*a[31]; + res[20]=b[20]*a[0]-b[27]*a[2]+b[29]*a[4]+b[31]*a[11]+b[0]*a[20]+b[2]*a[27]-b[4]*a[29]+b[11]*a[31]; + res[21]=b[21]*a[0]-b[28]*a[2]-b[29]*a[3]-b[31]*a[10]+b[0]*a[21]+b[2]*a[28]+b[3]*a[29]-b[10]*a[31]; + res[22]=b[22]*a[0]+b[26]*a[1]+b[30]*a[5]-b[31]*a[9]+b[0]*a[22]-b[1]*a[26]-b[5]*a[30]-b[9]*a[31]; + res[23]=b[23]*a[0]+b[27]*a[1]+b[30]*a[4]-b[31]*a[8]+b[0]*a[23]-b[1]*a[27]-b[4]*a[30]-b[8]*a[31]; + res[24]=b[24]*a[0]+b[28]*a[1]-b[30]*a[3]+b[31]*a[7]+b[0]*a[24]-b[1]*a[28]+b[3]*a[30]+b[7]*a[31]; + res[25]=b[25]*a[0]+b[29]*a[1]+b[30]*a[2]-b[31]*a[6]+b[0]*a[25]-b[1]*a[29]-b[2]*a[30]-b[6]*a[31]; + res[26]=b[26]*a[0]-b[31]*a[5]+b[0]*a[26]-b[5]*a[31]; + res[27]=b[27]*a[0]-b[31]*a[4]+b[0]*a[27]-b[4]*a[31]; + res[28]=b[28]*a[0]+b[31]*a[3]+b[0]*a[28]+b[3]*a[31]; + res[29]=b[29]*a[0]-b[31]*a[2]+b[0]*a[29]-b[2]*a[31]; + res[30]=b[30]*a[0]+b[31]*a[1]+b[0]*a[30]+b[1]*a[31]; + res[31]=b[31]*a[0]+b[0]*a[31]; + res + }; +); + + +// Add +// Multivector addition + +define_binary_op_all!( + Add, + add; + self: CGA, b: CGA, Output = CGA; + [val val] => &self + &b; + [ref val] => self + &b; + [val ref] => &self + b; + [ref ref] => { + let mut res = CGA::zero(); + let a = self; + res[0] = a[0]+b[0]; + res[1] = a[1]+b[1]; + res[2] = a[2]+b[2]; + res[3] = a[3]+b[3]; + res[4] = a[4]+b[4]; + res[5] = a[5]+b[5]; + res[6] = a[6]+b[6]; + res[7] = a[7]+b[7]; + res[8] = a[8]+b[8]; + res[9] = a[9]+b[9]; + res[10] = a[10]+b[10]; + res[11] = a[11]+b[11]; + res[12] = a[12]+b[12]; + res[13] = a[13]+b[13]; + res[14] = a[14]+b[14]; + res[15] = a[15]+b[15]; + res[16] = a[16]+b[16]; + res[17] = a[17]+b[17]; + res[18] = a[18]+b[18]; + res[19] = a[19]+b[19]; + res[20] = a[20]+b[20]; + res[21] = a[21]+b[21]; + res[22] = a[22]+b[22]; + res[23] = a[23]+b[23]; + res[24] = a[24]+b[24]; + res[25] = a[25]+b[25]; + res[26] = a[26]+b[26]; + res[27] = a[27]+b[27]; + res[28] = a[28]+b[28]; + res[29] = a[29]+b[29]; + res[30] = a[30]+b[30]; + res[31] = a[31]+b[31]; + res + }; +); + + +// Sub +// Multivector subtraction + +define_binary_op_all!( + Sub, + sub; + self: CGA, b: CGA, Output = CGA; + [val val] => &self - &b; + [ref val] => self - &b; + [val ref] => &self - b; + [ref ref] => { + let mut res = CGA::zero(); + let a = self; + res[0] = a[0]-b[0]; + res[1] = a[1]-b[1]; + res[2] = a[2]-b[2]; + res[3] = a[3]-b[3]; + res[4] = a[4]-b[4]; + res[5] = a[5]-b[5]; + res[6] = a[6]-b[6]; + res[7] = a[7]-b[7]; + res[8] = a[8]-b[8]; + res[9] = a[9]-b[9]; + res[10] = a[10]-b[10]; + res[11] = a[11]-b[11]; + res[12] = a[12]-b[12]; + res[13] = a[13]-b[13]; + res[14] = a[14]-b[14]; + res[15] = a[15]-b[15]; + res[16] = a[16]-b[16]; + res[17] = a[17]-b[17]; + res[18] = a[18]-b[18]; + res[19] = a[19]-b[19]; + res[20] = a[20]-b[20]; + res[21] = a[21]-b[21]; + res[22] = a[22]-b[22]; + res[23] = a[23]-b[23]; + res[24] = a[24]-b[24]; + res[25] = a[25]-b[25]; + res[26] = a[26]-b[26]; + res[27] = a[27]-b[27]; + res[28] = a[28]-b[28]; + res[29] = a[29]-b[29]; + res[30] = a[30]-b[30]; + res[31] = a[31]-b[31]; + res + }; +); + + +// smul +// scalar/multivector multiplication + +define_binary_op_all!( + Mul, + mul; + self: float_t, b: CGA, Output = CGA; + [val val] => &self * &b; + [ref val] => self * &b; + [val ref] => &self * b; + [ref ref] => { + let mut res = CGA::zero(); + let a = self; + res[0] = a*b[0]; + res[1] = a*b[1]; + res[2] = a*b[2]; + res[3] = a*b[3]; + res[4] = a*b[4]; + res[5] = a*b[5]; + res[6] = a*b[6]; + res[7] = a*b[7]; + res[8] = a*b[8]; + res[9] = a*b[9]; + res[10] = a*b[10]; + res[11] = a*b[11]; + res[12] = a*b[12]; + res[13] = a*b[13]; + res[14] = a*b[14]; + res[15] = a*b[15]; + res[16] = a*b[16]; + res[17] = a*b[17]; + res[18] = a*b[18]; + res[19] = a*b[19]; + res[20] = a*b[20]; + res[21] = a*b[21]; + res[22] = a*b[22]; + res[23] = a*b[23]; + res[24] = a*b[24]; + res[25] = a*b[25]; + res[26] = a*b[26]; + res[27] = a*b[27]; + res[28] = a*b[28]; + res[29] = a*b[29]; + res[30] = a*b[30]; + res[31] = a*b[31]; + res + }; +); + + +// muls +// multivector/scalar multiplication + +define_binary_op_all!( + Mul, + mul; + self: CGA, b: float_t, Output = CGA; + [val val] => &self * &b; + [ref val] => self * &b; + [val ref] => &self * b; + [ref ref] => { + let mut res = CGA::zero(); + let a = self; + res[0] = a[0]*b; + res[1] = a[1]*b; + res[2] = a[2]*b; + res[3] = a[3]*b; + res[4] = a[4]*b; + res[5] = a[5]*b; + res[6] = a[6]*b; + res[7] = a[7]*b; + res[8] = a[8]*b; + res[9] = a[9]*b; + res[10] = a[10]*b; + res[11] = a[11]*b; + res[12] = a[12]*b; + res[13] = a[13]*b; + res[14] = a[14]*b; + res[15] = a[15]*b; + res[16] = a[16]*b; + res[17] = a[17]*b; + res[18] = a[18]*b; + res[19] = a[19]*b; + res[20] = a[20]*b; + res[21] = a[21]*b; + res[22] = a[22]*b; + res[23] = a[23]*b; + res[24] = a[24]*b; + res[25] = a[25]*b; + res[26] = a[26]*b; + res[27] = a[27]*b; + res[28] = a[28]*b; + res[29] = a[29]*b; + res[30] = a[30]*b; + res[31] = a[31]*b; + res + }; +); + + +// sadd +// scalar/multivector addition + +define_binary_op_all!( + Add, + add; + self: float_t, b: CGA, Output = CGA; + [val val] => &self + &b; + [ref val] => self + &b; + [val ref] => &self + b; + [ref ref] => { + let mut res = CGA::zero(); + let a = self; + res[0] = a+b[0]; + res[1] = b[1]; + res[2] = b[2]; + res[3] = b[3]; + res[4] = b[4]; + res[5] = b[5]; + res[6] = b[6]; + res[7] = b[7]; + res[8] = b[8]; + res[9] = b[9]; + res[10] = b[10]; + res[11] = b[11]; + res[12] = b[12]; + res[13] = b[13]; + res[14] = b[14]; + res[15] = b[15]; + res[16] = b[16]; + res[17] = b[17]; + res[18] = b[18]; + res[19] = b[19]; + res[20] = b[20]; + res[21] = b[21]; + res[22] = b[22]; + res[23] = b[23]; + res[24] = b[24]; + res[25] = b[25]; + res[26] = b[26]; + res[27] = b[27]; + res[28] = b[28]; + res[29] = b[29]; + res[30] = b[30]; + res[31] = b[31]; + res + }; +); + + +// adds +// multivector/scalar addition + +define_binary_op_all!( + Add, + add; + self: CGA, b: float_t, Output = CGA; + [val val] => &self + &b; + [ref val] => self + &b; + [val ref] => &self + b; + [ref ref] => { + let mut res = CGA::zero(); + let a = self; + res[0] = a[0]+b; + res[1] = a[1]; + res[2] = a[2]; + res[3] = a[3]; + res[4] = a[4]; + res[5] = a[5]; + res[6] = a[6]; + res[7] = a[7]; + res[8] = a[8]; + res[9] = a[9]; + res[10] = a[10]; + res[11] = a[11]; + res[12] = a[12]; + res[13] = a[13]; + res[14] = a[14]; + res[15] = a[15]; + res[16] = a[16]; + res[17] = a[17]; + res[18] = a[18]; + res[19] = a[19]; + res[20] = a[20]; + res[21] = a[21]; + res[22] = a[22]; + res[23] = a[23]; + res[24] = a[24]; + res[25] = a[25]; + res[26] = a[26]; + res[27] = a[27]; + res[28] = a[28]; + res[29] = a[29]; + res[30] = a[30]; + res[31] = a[31]; + res + }; +); + + +// ssub +// scalar/multivector subtraction + +define_binary_op_all!( + Sub, + sub; + self: float_t, b: CGA, Output = CGA; + [val val] => &self - &b; + [ref val] => self - &b; + [val ref] => &self - b; + [ref ref] => { + let mut res = CGA::zero(); + let a = self; + res[0] = a-b[0]; + res[1] = -b[1]; + res[2] = -b[2]; + res[3] = -b[3]; + res[4] = -b[4]; + res[5] = -b[5]; + res[6] = -b[6]; + res[7] = -b[7]; + res[8] = -b[8]; + res[9] = -b[9]; + res[10] = -b[10]; + res[11] = -b[11]; + res[12] = -b[12]; + res[13] = -b[13]; + res[14] = -b[14]; + res[15] = -b[15]; + res[16] = -b[16]; + res[17] = -b[17]; + res[18] = -b[18]; + res[19] = -b[19]; + res[20] = -b[20]; + res[21] = -b[21]; + res[22] = -b[22]; + res[23] = -b[23]; + res[24] = -b[24]; + res[25] = -b[25]; + res[26] = -b[26]; + res[27] = -b[27]; + res[28] = -b[28]; + res[29] = -b[29]; + res[30] = -b[30]; + res[31] = -b[31]; + res + }; +); + + +// subs +// multivector/scalar subtraction + +define_binary_op_all!( + Sub, + sub; + self: CGA, b: float_t, Output = CGA; + [val val] => &self - &b; + [ref val] => self - &b; + [val ref] => &self - b; + [ref ref] => { + let mut res = CGA::zero(); + let a = self; + res[0] = a[0]-b; + res[1] = a[1]; + res[2] = a[2]; + res[3] = a[3]; + res[4] = a[4]; + res[5] = a[5]; + res[6] = a[6]; + res[7] = a[7]; + res[8] = a[8]; + res[9] = a[9]; + res[10] = a[10]; + res[11] = a[11]; + res[12] = a[12]; + res[13] = a[13]; + res[14] = a[14]; + res[15] = a[15]; + res[16] = a[16]; + res[17] = a[17]; + res[18] = a[18]; + res[19] = a[19]; + res[20] = a[20]; + res[21] = a[21]; + res[22] = a[22]; + res[23] = a[23]; + res[24] = a[24]; + res[25] = a[25]; + res[26] = a[26]; + res[27] = a[27]; + res[28] = a[28]; + res[29] = a[29]; + res[30] = a[30]; + res[31] = a[31]; + res + }; +); + + +impl CGA { + pub fn norm(self: & Self) -> float_t { + let scalar_part = (self * self.Conjugate())[0]; + + scalar_part.abs().sqrt() + } + + pub fn inorm(self: & Self) -> float_t { + self.Dual().norm() + } + + pub fn normalized(self: & Self) -> Self { + self * (1.0 / self.norm()) + } + + + pub fn eo() -> Self { Self::e4() + Self::e5() } + pub fn ei() -> Self { (Self::e5() - Self::e4())*0.5 } + + pub fn up(x: float_t, y: float_t, z: float_t) -> Self { + x * Self::e1() + y * Self::e2() + z * Self::e3() + 0.5 * (x * x + y * y + z * z) * Self::ei() + Self::eo() + } + + +} + + +fn main() { + + let px = &CGA::up(1.0,2.0,3.0); + let line = px ^ CGA::eo() ^ CGA::ei(); + let sphere = (CGA::eo() - CGA::ei()).Dual(); + println!("a point : {}", px); + println!("a line : {}", line); + println!("a sphere : {}", sphere); + + +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..07297b5 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,213 @@ +use std::f64; + +use wasm_bindgen::prelude::*; +use wasm_bindgen::JsCast; +use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement}; +//use web_sys::console; + +mod cga; +use cga::CGA; + +const PI: f64 = f64::consts::PI; +const TWO_PI: f64 = 2.*PI; +const ERROR: f64 = 0.0001; + +const WIDTH: f64 = 600.; +const HEIGHT: f64 = 600.; +const CENTER_X: f64 = 300.; +const CENTER_Y: f64 = 300.; +const RADIUS: f64 = 250.; + +const BACKGROUND: &str = "#ffffff"; +const BLACK: &str = "#000000"; +const RED: &str = "#ff0000"; +const GREEN: &str = "#00ff00"; +const _BLUE: &str = "#0000ff"; + +const SCALAR: usize = 0; +const E1: usize = 1; +const E2: usize = 2; +//const E3: usize = 3; +//const E4: usize = 4; +//const E5: usize = 5; +//const E12: usize = 6; +//const E13: usize = 7; +//const E14: usize = 8; +//const E15: usize = 9; +//const E23: usize = 10; +//const E24: usize = 11; +//const E25: usize = 12; +//const E34: usize = 13; +//const E35: usize = 14; +//const E45: usize = 15; +//const E123: usize = 16; +//const E124: usize = 17; +//const E125: usize = 18; +//const E134: usize = 19; +//const E135: usize = 20; +//const E145: usize = 21; +//const E234: usize = 22; +//const E235: usize = 23; +//const E245: usize = 24; +//const E345: usize = 25; +//const E1234: usize = 26; +//const E1235: usize = 27; +//const E1245: usize = 28; +//const E1345: usize = 29; +//const E2345: usize = 30; +//const E12345: usize = 31; + +struct Ship { + _pos: CGA, + _vel: CGA, + _orientation: CGA, +} + +fn point_to_cga(x: f64, y: f64) -> CGA { + let x_vec = CGA::e1(); + let y_vec = CGA::e2(); + let _z_vec =CGA::e3(); + let e_vec = CGA::e4(); + let e_bar = CGA::e5(); + let n_vec = &e_vec + &e_bar; + let n_bar = &e_vec - &e_bar; + + let mut ux = x; + let mut uy = y; + let mut mag_sqr = ux*ux + uy*uy; + if mag_sqr > 1. { + ux /= mag_sqr.sqrt(); + uy /= mag_sqr.sqrt(); + mag_sqr = 1.; + } + + 0.5*mag_sqr*n_vec + ux*x_vec + uy*y_vec - 0.5*n_bar +} + +fn draw_point(context: &CanvasRenderingContext2d, point: &CGA) { + //Naively assume we are given a valid point + let x = point[1]*RADIUS + CENTER_X; + let y = point[2]*RADIUS + CENTER_Y; + + context.begin_path(); + context.set_fill_style_str(RED); + context.arc(x, y, 2., 0., TWO_PI).unwrap(); + context.fill(); +} + +fn draw_line(context: &CanvasRenderingContext2d, line: &CGA) { + context.begin_path(); + context.set_stroke_style_str(GREEN); + + //Naively assume we are given a valid line/circle + let n_bar = CGA::e4() - CGA::e5(); + let n_vec = CGA::e4() + CGA::e5(); + let dual = line.Dual(); + + let lambda = -(&dual | &n_vec)[SCALAR]; + let mu = (&dual | &n_bar)[SCALAR]; + let x = dual[E1]; + let y = dual[E2]; + + + if lambda.abs() < ERROR { + //Line + let norm_sqr = x*x+y*y; + if norm_sqr < ERROR { + return; + } else { + let norm = norm_sqr.sqrt(); + let px = mu * 0.5 * x / norm_sqr; + let py = mu * 0.5 * y / norm_sqr; + let tx = -y / norm; + let ty = x / norm; + let p1x = px + tx * 1000.; + let p1y = py + ty * 1000.; + let p2x = px - tx * 1000.; + let p2y = py - ty * 1000.; + context.move_to(p1x*RADIUS + CENTER_X, p1y*RADIUS + CENTER_Y); + context.line_to(p2x*RADIUS + CENTER_X, p2y*RADIUS + CENTER_Y); + + } + } else { + //Extract Center and Radius + let c_x = x/lambda; + let c_y = y/lambda; + let r_sqr = c_x*c_x + c_y*c_y - mu/lambda; + let r = r_sqr.sqrt(); + + //draw_point(context, &point_to_cga(c_x, c_y)); + + //Convert into Canvas Space + let canvas_cx = c_x*RADIUS + CENTER_X; + let canvas_cy = c_y*RADIUS + CENTER_Y; + let canvas_r = r*RADIUS; + + //Draw + context.arc(canvas_cx, canvas_cy, canvas_r, 0., TWO_PI).unwrap(); + } + context.stroke(); +} + +// Start entry point +#[wasm_bindgen(start)] +pub fn start() -> Result<(), JsValue> { + let _ship = Ship { _pos: point_to_cga(0.,0.), _vel: CGA::zero(), _orientation: CGA::zero() }; + + // Grab document and canvas + let window = web_sys::window().unwrap(); + let document = window.document().unwrap(); + let canvas = document + .get_element_by_id("game-canvas") + .unwrap() + .dyn_into::()?; + + canvas.set_width(WIDTH as u32); + canvas.set_height(HEIGHT as u32); + + let context = canvas + .get_context("2d")? + .unwrap() + .dyn_into::()?; + + //Set up play area. + context.begin_path(); + context.set_fill_style_str(BACKGROUND); + context.fill_rect(0.0, 0.0, WIDTH, HEIGHT); + context.fill(); + context.set_stroke_style_str(BLACK); + context.arc(CENTER_X, CENTER_Y, RADIUS, 0., TWO_PI).unwrap(); + context.stroke(); + + let point = point_to_cga(0.,0.); + draw_point(&context, &point); + + let p1 = point_to_cga(0.9, 0.0); + draw_point(&context, &p1); + let p2 = point_to_cga(0.0, 0.9); + draw_point(&context, &p2); + let p3 = point_to_cga(0.7, 0.6); + draw_point(&context, &p3); + let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3(); + draw_line(&context, &circle); + + let p1 = point_to_cga(0.9, 0.2); + draw_point(&context, &p1); + let p2 = point_to_cga(-0.9, -0.); + draw_point(&context, &p2); + let p3 = point_to_cga(0., 0.1); + draw_point(&context, &p3); + let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3(); + draw_line(&context, &circle); + + let p1 = point_to_cga(0.9, 0.1); + draw_point(&context, &p1); + let p2 = point_to_cga(-0.9, -0.1); + draw_point(&context, &p2); + let p3 = point_to_cga(0., 0.0); + draw_point(&context, &p3); + let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3(); + draw_line(&context, &circle); + + Ok(()) +}