Asi ga-codegen
Geometric Algebra code generation for C++, C#, Rust, Python from ganja.js templates
install
source · Clone the upstream repo
git clone https://github.com/plurigrid/asi
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/ga-codegen" ~/.claude/skills/plurigrid-asi-ga-codegen && rm -rf "$T"
manifest:
skills/ga-codegen/SKILL.mdsource content
ga-codegen
Generate Clifford Algebra implementations for any language from ganja.js
Version: 1.0.0
Trit: +1 (PLUS - generative)
Overview
ganja.js includes a template-based code generator that produces optimized Geometric Algebra implementations for:
- C++ (header-only)
- C# (.NET)
- Rust (no-std compatible)
- Python (numpy-based)
Supported Algebras
Pre-generated algebras in
ganja.js/codegen/:
| Algebra | Signature | File Pattern |
|---|---|---|
| R2 | Cl(2,0,0) | |
| R3 | Cl(3,0,0) | |
| R4 | Cl(4,0,0) | |
| PGA2D | Cl(2,0,1) | |
| PGA3D | Cl(3,0,1) | |
| CGA2D | Cl(3,1,0) | |
| CGA3D | Cl(4,1,0) | |
| Quaternions | Cl(0,2,0) | |
| Dual Quaternions | Cl(0,2,1) | |
Code Structure
Each generated file contains:
// C++ Example: PGA3D.cpp namespace PGA3D { // Multivector with flat storage struct Multivector { float data[16]; // 2^4 components // Constructors static Multivector scalar(float s); static Multivector vector(float e1, float e2, float e3, float e0); static Multivector bivector(...); // Products Multivector operator*(const Multivector& b) const; // Geometric Multivector operator^(const Multivector& b) const; // Wedge Multivector operator|(const Multivector& b) const; // Dot Multivector operator&(const Multivector& b) const; // Vee // Involutions Multivector reverse() const; Multivector conjugate() const; Multivector dual() const; // Transformations Multivector sandwich(const Multivector& v) const; Multivector exp() const; Multivector log() const; }; // Helper constructors Multivector point(float x, float y, float z); Multivector line(float px, float py, float pz, float dx, float dy, float dz); Multivector plane(float a, float b, float c, float d); Multivector rotor(float angle, Multivector axis); Multivector translator(float dist, Multivector dir); }
Rust Implementation
// PGA3D.rs #![no_std] #[derive(Clone, Copy, Debug)] pub struct Multivector([f32; 16]); impl Multivector { pub const fn zero() -> Self { Self([0.0; 16]) } pub const fn scalar(s: f32) -> Self { let mut m = [0.0; 16]; m[0] = s; Self(m) } // Geometric product - generated multiplication table pub fn mul(&self, b: &Self) -> Self { let mut res = [0.0; 16]; // Generated from Cayley table res[0] = self.0[0]*b.0[0] + self.0[1]*b.0[1] + ...; // ... 16 lines of optimized multiplications Self(res) } pub fn wedge(&self, b: &Self) -> Self { ... } pub fn dot(&self, b: &Self) -> Self { ... } pub fn dual(&self) -> Self { ... } pub fn reverse(&self) -> Self { ... } pub fn exp(&self) -> Self { // Closed-form for bivectors let theta = self.norm(); if theta < 1e-6 { return Self::scalar(1.0).add(&self); } Self::scalar(theta.cos()) .add(&self.scale(theta.sin() / theta)) } } // Operator overloading impl core::ops::Mul for Multivector { type Output = Self; fn mul(self, rhs: Self) -> Self { self.mul(&rhs) } }
Python Implementation
# PGA3D.py import numpy as np class Multivector: def __init__(self, data=None): self.data = np.zeros(16) if data is None else np.array(data) @classmethod def scalar(cls, s): m = cls(); m.data[0] = s; return m def __mul__(self, other): """Geometric product""" res = Multivector() # Generated multiplication res.data[0] = self.data[0]*other.data[0] + ... return res def __xor__(self, other): """Wedge product (^)""" return self.wedge(other) def __and__(self, other): """Vee product (&)""" return self.dual().wedge(other.dual()).dual() def exp(self): """Exponential map""" theta = np.sqrt(abs(self.dot(self).data[0])) if theta < 1e-6: return Multivector.scalar(1) + self return Multivector.scalar(np.cos(theta)) + self * (np.sin(theta)/theta) def point(x, y, z): m = Multivector() m.data[14] = 1 # e123 m.data[11] = -x # e023 m.data[12] = y # e013 m.data[13] = -z # e012 return m
Template System
The generator uses Node.js templates:
// codegen/generate.js const Algebra = require('../ganja.js'); function generateCPP(p, q, r, name) { const A = Algebra({p, q, r}); const {basis, mulTable} = A.describe(true); // Generate multiplication code const mulCode = mulTable.map((row, i) => `res[${i}] = ` + row.map((term, j) => term !== '0' ? `a[${j}]*b[${getBasisIndex(term)}]` : null ).filter(Boolean).join(' + ') + ';' ).join('\n'); return ` namespace ${name} { struct Multivector { float data[${basis.length}]; Multivector operator*(const Multivector& b) const { Multivector res; ${mulCode} return res; } }; }`; }
Custom Algebra Generation
// Generate algebra for your signature const Algebra = require('ganja.js'); // Generate Cl(1,3) for spacetime const spacetime = Algebra({p:1, q:3}); // Get multiplication table const info = spacetime.describe(true); console.log('Basis:', info.basis); console.log('Cayley table:', info.mulTable); // Use template to generate code const code = generateRust(1, 3, 0, 'Spacetime');
GF(3) Integration
Assign trits to generated algebras:
const algebraTrits = { 'R2': 0, // Real 2D - ergodic 'PGA2D': +1, // Projective 2D - generative 'CGA2D': -1, // Conformal 2D - contractive }; function getAlgebraTrit(name) { return algebraTrits[name] || 0; }
Build Integration
CMake (C++)
add_library(pga3d INTERFACE) target_include_directories(pga3d INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/ganja.js/codegen/cpp)
Cargo (Rust)
[dependencies] pga3d = { path = "ganja.js/codegen/rust/pga3d" }
pip (Python)
pip install ganja-algebras # Hypothetical package
GF(3) Triads
ga-codegen (+1) ⊗ clifford-acset-bridge (0) ⊗ sheaf-cohomology (-1) = 0 ✓ ga-codegen (+1) ⊗ pga-motor-interpolation (0) ⊗ conformal-ga (-1) = 0 ✓
Commands
# Generate all algebras cd ganja.js/codegen && node generate.js # Generate specific algebra node -e "require('./generate').cpp(3,0,1,'PGA3D')" > PGA3D.hpp # List available pre-generated ls ganja.js/codegen/{cpp,rust,python,csharp}/
Files
- Generator:
ganja.js/codegen/generate.js - C++ output:
codegen/cpp/*.hpp - Rust output:
codegen/rust/*/src/lib.rs - Python output:
codegen/python/*.py
References
- ganja.js codegen
- klein C++ library (alternative)
- Grassmann.jl (Julia native)
Autopoietic Marginalia
The interaction IS the skill improving itself.
Every use of this skill is an opportunity for worlding:
- MEMORY (-1): Record what was learned
- REMEMBERING (0): Connect patterns to other skills
- WORLDING (+1): Evolve the skill based on use
Add Interaction Exemplars here as the skill is used.