# clifford-codegen
Code generator for optimized geometric algebra types from algebra specifications.
## Workflow Overview
Generating a new algebra involves three steps:
1. **Discover** - Analyze an algebra signature to find valid grade combinations
2. **Customize** - Edit the generated TOML template with proper names and options
3. **Generate** - Produce optimized Rust code from the specification
## Step 1: Discover Entities
Use the `discover` command to analyze an algebra signature and generate a TOML template:
```bash
# Signature format: "p,q,r" (positive, negative, zero basis vectors)
# For algebras without negative or zero bases, you can omit them
# Euclidean 3D: Cl(3,0,0)
clifford-codegen discover "3,0,0" -o algebras/my_euclidean3.toml
# Projective GA 3D: Cl(3,0,1)
clifford-codegen discover "3,0,1" -o algebras/my_pga3.toml
# Conformal GA 3D: Cl(4,1,0)
clifford-codegen discover "4,1,0" -o algebras/my_cga3.toml
# Print to stdout instead of file
clifford-codegen discover "3,0,0"
```
The discover command outputs:
```toml
# Auto-discovered entities for Cl(3,0,0)
# Generated by clifford-codegen discover
#
# Review and customize:
# - Rename placeholder entities (Entity_*)
# - Add/remove types as needed
# - Customize descriptions
# - Configure constraints
[algebra]
name = "" # TODO: Fill in algebra name
module_path = "" # TODO: Fill in module path
description = "Cl(3,0,0)"
[signature]
positive = ["e1", "e2", "e3"]
negative = []
zero = []
# Discovered Types (6 entities satisfy geometric constraints)
[types.Entity_0]
grades = [0]
[types.Entity_1]
grades = [1]
[types.Entity_2]
grades = [2]
[types.Entity_3]
grades = [3]
[types.Entity_0_2]
grades = [0, 2]
[types.Entity_1_3]
grades = [1, 3]
```
### Discovered Entities
The discover command finds the **minimal closed set** of geometric entities:
- **Single-grade elements**: Scalars, vectors, bivectors, etc.
- **Even subalgebra**: Grades 0, 2, 4, ... (rotors/motors live here)
- **Odd subalgebra**: Grades 1, 3, 5, ... (flectors/reflections)
Only grade combinations that satisfy the **geometric constraint** are included.
The geometric constraint requires that `u * ũ` (element times its reverse)
produces only a scalar.
### Field Constraints
Some entities require **field constraints** for the geometric constraint to hold.
For example, PGA bivectors (lines) must satisfy `e01*e23 + e02*e31 + e03*e12 = 0`
for their direction and moment to be orthogonal.
When a constraint is needed, it appears in the TOML:
```toml
[types.Entity_2]
grades = [2]
constraint = "e01*e23 + e02*e31 + e03*e12 = 0"
```
## Step 2: Customize the TOML
Edit the generated TOML to add meaningful names and configure options:
### 1. Fill in Algebra Metadata
```toml
[algebra]
name = "euclidean3" # Used for module naming
module_path = "euclidean::dim3" # Rust module path
description = "3D Euclidean Geometric Algebra"
```
### 2. Rename Entity Types
Replace placeholder names with meaningful geometric names:
```toml
# Before
[types.Entity_0]
grades = [0]
[types.Entity_1]
grades = [1]
[types.Entity_0_2]
grades = [0, 2]
# After
[types.Scalar]
grades = [0]
description = "Grade-0 scalar"
[types.Vector]
grades = [1]
description = "Grade-1 vector"
[types.Rotor]
grades = [0, 2]
description = "3D rotation element"
```
### 3. Add Field Names
Map blade names to semantic field names for better ergonomics:
```toml
[blades]
e1 = "x"
e2 = "y"
e3 = "z"
e12 = "xy"
e13 = "xz"
e23 = "yz"
e123 = "xyz"
[types.Vector]
grades = [1]
fields = ["x", "y", "z"] # Uses blade mappings
```
### 4. Add Constraints
Define unit and nonzero constraints for types that need them:
```toml
[types.Vector]
grades = [1]
fields = ["x", "y", "z"]
[types.Vector.constraints.unit]
# Generates UnitVector wrapper type
[types.Vector.constraints.nonzero]
# Generates NonZeroVector wrapper type
[types.Rotor]
grades = [0, 2]
fields = ["s", "xy", "xz", "yz"]
[types.Rotor.constraints.unit]
# Generates UnitRotor wrapper type
```
### 5. Define Products
Specify which products to generate and their result types:
```toml
[products.geometric]
Vector_Vector = "Rotor"
Rotor_Rotor = "Rotor"
UnitRotor_UnitRotor = "UnitRotor"
[products.outer]
Vector_Vector = "Bivector"
Vector_Bivector = "Trivector"
[products.scalar]
Vector_Vector = "T" # Returns the scalar type parameter
```
## Step 3: Generate Rust Code
Use the `generate` command to produce Rust code from your specification:
```bash
# Generate to the clifford crate's src directory
clifford-codegen generate algebras/euclidean3.toml -o src/specialized/euclidean/dim3/
# Preview what would be generated
clifford-codegen generate algebras/euclidean3.toml --dry-run
# Overwrite existing files
clifford-codegen generate algebras/euclidean3.toml --force
# With verbose output
clifford-codegen generate algebras/euclidean3.toml -v
```
### Generated Files
The generator creates a Rust module with:
```
my_algebra/
├── mod.rs # Module re-exports and allow attributes
├── types.rs # Type definitions (Vector, Bivector, Rotor, etc.)
├── products.rs # Product implementations (geometric, outer, inner)
├── traits.rs # Standard trait impls (Debug, Clone, PartialEq, ops)
└── conversions.rs # Multivector conversions
```
### Integrating Generated Code
The generated code is designed to be used **inside the clifford crate**. It uses
`crate::` imports for the `Float` trait, `Multivector`, `Blade`, and signatures.
To integrate generated code:
1. Generate into a subdirectory under `src/`:
```bash
clifford-codegen generate algebras/my_algebra.toml -o src/my_algebra/ --force
```
2. Add the module to `src/lib.rs`:
```rust
pub mod my_algebra;
```
3. Build and test:
```bash
cargo build
cargo test my_algebra
```
## Complete Example: Creating a 2D Euclidean Algebra
```bash
# 1. Discover entities
clifford-codegen discover "2,0,0" -o algebras/euclidean2.toml
# 2. Edit the TOML (see example below)
# 3. Generate code into the clifford crate
clifford-codegen generate algebras/euclidean2.toml -o src/specialized/euclidean/dim2/ --force
# 4. Add module to lib.rs and test
cargo test specialized::euclidean::dim2
```
Example customized `euclidean2.toml`:
```toml
[algebra]
name = "euclidean2"
module_path = "euclidean::dim2"
description = "2D Euclidean Geometric Algebra"
[signature]
positive = ["e1", "e2"]
[blades]
e1 = "x"
e2 = "y"
e12 = "xy"
[types.Scalar]
grades = [0]
description = "Grade-0 scalar"
fields = ["s"]
[types.Vector]
grades = [1]
description = "Grade-1 vector"
fields = ["x", "y"]
[types.Vector.constraints.unit]
[types.Vector.constraints.nonzero]
[types.Bivector]
grades = [2]
description = "Grade-2 pseudoscalar"
fields = ["xy"]
[types.Rotor]
grades = [0, 2]
description = "2D rotation element"
fields = ["s", "xy"]
[types.Rotor.constraints.unit]
[products.geometric]
Vector_Vector = "Rotor"
Rotor_Rotor = "Rotor"
UnitRotor_UnitRotor = "UnitRotor"
[products.outer]
Vector_Vector = "Bivector"
[products.scalar]
Vector_Vector = "T"
```
## Other Commands
### List Blades
```bash
clifford-codegen blades algebras/euclidean3.toml
clifford-codegen blades algebras/euclidean3.toml --grade 2 # Filter by grade
clifford-codegen blades algebras/euclidean3.toml --format json
```
### List Products
```bash
clifford-codegen products algebras/euclidean3.toml
clifford-codegen products algebras/euclidean3.toml --type Vector
clifford-codegen products algebras/euclidean3.toml --product geometric --table
```
### Verify Generated Code
```bash
clifford-codegen verify src/specialized/euclidean/dim3/ --spec algebras/euclidean3.toml
```
## Common Algebras
| Euclidean 2D | Cl(2,0,0) | `discover "2,0,0"` |
| Euclidean 3D | Cl(3,0,0) | `discover "3,0,0"` |
| PGA 2D | Cl(2,0,1) | `discover "2,0,1"` |
| PGA 3D | Cl(3,0,1) | `discover "3,0,1"` |
| CGA 2D | Cl(3,1,0) | `discover "3,1,0"` |
| CGA 3D | Cl(4,1,0) | `discover "4,1,0"` |
| Spacetime | Cl(1,3,0) | `discover "1,3,0"` |