mod algebra; mod ast; mod compile; mod emit; mod glsl; mod rust; mod rust_gpu; use crate::{ algebra::{BasisElement, GeometricAlgebra, Involution, MultiVectorClass, MultiVectorClassRegistry, Product}, ast::{AstNode, DataType, Parameter}, emit::Emitter, }; fn main() { let mut args = std::env::args(); let _executable = args.next().unwrap(); let config = args.next().unwrap(); let mut config_iter = config.split(';'); let algebra_descriptor = config_iter.next().unwrap(); let mut algebra_descriptor_iter = algebra_descriptor.split(':'); let algebra_name = algebra_descriptor_iter.next().unwrap(); let generator_squares = algebra_descriptor_iter .next() .unwrap() .split(',') .map(|x| x.parse::().unwrap()) .collect::>(); let algebra = GeometricAlgebra { generator_squares: generator_squares.as_slice(), }; let involutions = Involution::involutions(&algebra); let products = Product::products(&algebra); let basis = algebra.sorted_basis(); for b in basis.iter() { for a in basis.iter() { print!("{:1$} ", BasisElement::product(a, b, &algebra), generator_squares.len() + 2); } println!(); } let mut registry = MultiVectorClassRegistry::default(); for multi_vector_descriptor in config_iter { let mut multi_vector_descriptor_iter = multi_vector_descriptor.split(':'); registry.register(MultiVectorClass { class_name: multi_vector_descriptor_iter.next().unwrap().to_owned(), grouped_basis: multi_vector_descriptor_iter .next() .unwrap() .split('|') .map(|group_descriptor| { group_descriptor .split(',') .map(|element_name| BasisElement::parse(element_name, &algebra)) .collect::>() }) .collect::>(), }); } let mut emitter = Emitter::new(&std::path::Path::new("../src/").join(std::path::Path::new(algebra_name))); emitter.emit(&AstNode::Preamble).unwrap(); for class in registry.classes.iter() { emitter.emit(&AstNode::ClassDefinition { class }).unwrap(); } let mut trait_implementations = std::collections::BTreeMap::new(); for class_a in registry.classes.iter() { let parameter_a = Parameter { name: "self", data_type: DataType::MultiVector(class_a), }; let mut single_trait_implementations = std::collections::BTreeMap::new(); for name in &["Zero", "One"] { let ast_node = class_a.constant(name); emitter.emit(&ast_node).unwrap(); if ast_node != AstNode::None { single_trait_implementations.insert(name.to_string(), ast_node); } } for (name, involution) in involutions.iter() { let ast_node = MultiVectorClass::involution(name, involution, ¶meter_a, ®istry, false); emitter.emit(&ast_node).unwrap(); if ast_node != AstNode::None { single_trait_implementations.insert(name.to_string(), ast_node); } } let mut pair_trait_implementations = std::collections::BTreeMap::new(); for class_b in registry.classes.iter() { let mut trait_implementations = std::collections::BTreeMap::new(); let parameter_b = Parameter { name: "other", data_type: DataType::MultiVector(class_b), }; if class_a != class_b { let name = "Into"; let ast_node = MultiVectorClass::involution(name, &Involution::projection(class_b), ¶meter_a, ®istry, true); emitter.emit(&ast_node).unwrap(); if ast_node != AstNode::None { trait_implementations.insert(name.to_string(), ast_node); } } for name in &["Add", "Sub"] { let ast_node = MultiVectorClass::element_wise(*name, ¶meter_a, ¶meter_b, ®istry); emitter.emit(&ast_node).unwrap(); if ast_node != AstNode::None { trait_implementations.insert(name.to_string(), ast_node); } } if class_a == class_b { for name in &["Mul", "Div"] { let ast_node = MultiVectorClass::element_wise(*name, ¶meter_a, ¶meter_b, ®istry); emitter.emit(&ast_node).unwrap(); if ast_node != AstNode::None { trait_implementations.insert(name.to_string(), ast_node); } } } for (name, product) in products.iter() { let ast_node = MultiVectorClass::product(name, product, ¶meter_a, ¶meter_b, ®istry); emitter.emit(&ast_node).unwrap(); if ast_node != AstNode::None { trait_implementations.insert(name.to_string(), ast_node); } } pair_trait_implementations.insert( parameter_b.multi_vector_class().class_name.clone(), (parameter_b.clone(), trait_implementations), ); } for (parameter_b, pair_trait_implementations) in pair_trait_implementations.values() { if let Some(scalar_product) = pair_trait_implementations.get("ScalarProduct") { if let Some(reversal) = single_trait_implementations.get("Reversal") { if parameter_a.multi_vector_class() == parameter_b.multi_vector_class() { let squared_magnitude = MultiVectorClass::derive_squared_magnitude("SquaredMagnitude", scalar_product, reversal, ¶meter_a); emitter.emit(&squared_magnitude).unwrap(); let magnitude = MultiVectorClass::derive_magnitude("Magnitude", &squared_magnitude, ¶meter_a); emitter.emit(&magnitude).unwrap(); single_trait_implementations.insert(result_of_trait!(squared_magnitude).name.to_string(), squared_magnitude); single_trait_implementations.insert(result_of_trait!(magnitude).name.to_string(), magnitude); } } } } for (parameter_b, pair_trait_implementations) in pair_trait_implementations.values() { if let Some(geometric_product) = pair_trait_implementations.get("GeometricProduct") { if parameter_b.data_type.is_scalar() { if !parameter_a.data_type.is_scalar() { let scale = MultiVectorClass::derive_scale("Mul", geometric_product, ¶meter_a, parameter_b); emitter.emit(&scale).unwrap(); } if let Some(magnitude) = single_trait_implementations.get("Magnitude") { let signum = MultiVectorClass::derive_signum("Signum", geometric_product, magnitude, ¶meter_a); emitter.emit(&signum).unwrap(); single_trait_implementations.insert(result_of_trait!(signum).name.to_string(), signum); } if let Some(squared_magnitude) = single_trait_implementations.get("SquaredMagnitude") { if let Some(reversal) = single_trait_implementations.get("Reversal") { let inverse = MultiVectorClass::derive_inverse("Inverse", geometric_product, squared_magnitude, reversal, ¶meter_a); emitter.emit(&inverse).unwrap(); single_trait_implementations.insert(result_of_trait!(inverse).name.to_string(), inverse); } } } } } trait_implementations.insert( parameter_a.multi_vector_class().class_name.clone(), (parameter_a.clone(), single_trait_implementations, pair_trait_implementations), ); } for (parameter_a, single_trait_implementations, pair_trait_implementations) in trait_implementations.values() { for (parameter_b, pair_trait_implementations) in pair_trait_implementations.values() { if let Some(geometric_product) = pair_trait_implementations.get("GeometricProduct") { let geometric_product_result = result_of_trait!(geometric_product); if parameter_a.multi_vector_class() == parameter_b.multi_vector_class() && geometric_product_result.multi_vector_class() == parameter_a.multi_vector_class() { if let Some(constant_one) = single_trait_implementations.get("One") { if let Some(inverse) = single_trait_implementations.get("Inverse") { let power_of_integer = MultiVectorClass::derive_power_of_integer( "Powi", geometric_product, constant_one, inverse, parameter_a, &Parameter { name: "exponent", data_type: DataType::Integer, }, ); emitter.emit(&power_of_integer).unwrap(); } } } if let Some(b_trait_implementations) = trait_implementations.get(¶meter_b.multi_vector_class().class_name) { if let Some(inverse) = b_trait_implementations.1.get("Inverse") { let division = MultiVectorClass::derive_division("GeometricQuotient", geometric_product, inverse, parameter_a, parameter_b); emitter.emit(&division).unwrap(); } } if let Some(reversal) = single_trait_implementations.get("Reversal") { if let Some(b_trait_implementations) = trait_implementations.get(&geometric_product_result.multi_vector_class().class_name) { if let Some(b_pair_trait_implementations) = b_trait_implementations.2.get(¶meter_a.multi_vector_class().class_name) { if let Some(geometric_product_2) = b_pair_trait_implementations.1.get("GeometricProduct") { let geometric_product_2_result = result_of_trait!(geometric_product_2); if let Some(c_trait_implementations) = trait_implementations.get(&geometric_product_2_result.multi_vector_class().class_name) { if let Some(c_pair_trait_implementations) = c_trait_implementations.2.get(¶meter_b.multi_vector_class().class_name) { let transformation = MultiVectorClass::derive_sandwich_product( "Transformation", geometric_product, geometric_product_2, reversal, c_pair_trait_implementations.1.get("Into"), parameter_a, parameter_b, ); emitter.emit(&transformation).unwrap(); } } } } } } } } } }