-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: helehex <helehex@gmail.com>
- Loading branch information
Showing
5 changed files
with
171 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Infrared | ||
Infrared is a geometric algebra library for Mojo. | ||
|
||
## Geometric Algebra | ||
[Geometric algebras](https://en.wikipedia.org/wiki/Geometric_algebra) are [Clifford algebras](https://en.wikipedia.org/wiki/Clifford_algebra) in the context of geometry. | ||
|
||
It's an alternative paradigm to linear algebra that uses 'multivectors' instead of matrices. | ||
|
||
Multivectors can represent geometric objects and transformations such as lines, planes, rotations, etc. | ||
|
||
Multivectors can be multiplied together using the 'geometric product'. | ||
|
||
## Using Infrared | ||
With infrared, you can generate the geometric product table for an arbitrary signature. | ||
|
||
Multivectors are also parameterized on a basis masks, to avoid unnecessary overhead. | ||
|
||
Example: | ||
```mojo | ||
alias sig = Signature(2, 0, 1) | ||
var m = Multivector[sig, sig.vector_mask()](0.0, 1.0, 2.0) | ||
print(m * m) | ||
``` | ||
|
||
Infrared has no dependecies other than max. | ||
|
||
Developers can use infrared as a mathematical abstraction over geometry (projective, conformal, spacetime, dimension-agnostic, etc.) | ||
|
||
## Contributing | ||
I'm accepting contributions, but haven't made a contributors guide yet. | ||
|
||
Some issues and areas of work include: | ||
- performance improvements, signature generation could use bitwise operations | ||
- constructors for geometric objects and a better model for initializing multivectors | ||
- better basis masking, currently uses a list of bools | ||
- examples and benchmarks | ||
|
||
If you want to reach out, you can email me at helehex@gmail.com, or message me on discord (my alias in the modular server is ghostfire) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
context: | ||
version: "0.1.0" | ||
|
||
package: | ||
name: "infrared" | ||
version: ${{ version }} | ||
|
||
source: | ||
- git: https://github.com/helehex/infrared.git | ||
rev: 1776092af17ce25af4d3c1273bee9974a4bc66c4 | ||
|
||
build: | ||
number: 0 | ||
script: | ||
- mojo package src -o ${{ PREFIX }}/lib/mojo/infrared.mojopkg | ||
requirements: | ||
host: | ||
- max | ||
run: | ||
- ${{ pin_compatible('max') }} | ||
|
||
tests: | ||
- script: | ||
- if: unix | ||
then: | ||
- mojo run test.mojo | ||
files: | ||
recipe: | ||
- test.mojo | ||
|
||
about: | ||
homepage: https://github.com/helehex/infrared | ||
license: MIT | ||
license_file: LICENSE | ||
summary: A geometric algebra library for mojo. | ||
repository: https://github.com/helehex/infrared | ||
|
||
extra: | ||
maintainers: | ||
- helehex |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
from testing import assert_true, assert_false, assert_equal, assert_not_equal | ||
from infrared.algebra import * | ||
|
||
|
||
def main(): | ||
test_eq() | ||
test_ne() | ||
test_subspace_constructor() | ||
test_getattr() | ||
test_normalized() | ||
test_add() | ||
test_sub() | ||
test_mul() | ||
test_sandwich() | ||
|
||
|
||
def test_eq(): | ||
alias g3 = Signature(3, 0, 0) | ||
assert_true(Multivector[g3, g3.empty_mask()]().__eq__(Float64(0))) | ||
assert_true(Multivector[g3, g3.vector_mask()](1, 2, 3).__eq__(Multivector[g3, g3.vector_mask()](1, 2, 3))) | ||
assert_false(Multivector[g3, g3.vector_mask()](1, 2, 3).__eq__(Multivector[g3, g3.vector_mask()](1, 4, 3))) | ||
assert_false(Multivector[g3, g3.vector_mask()](1, 2, 3).__eq__(Float64(1))) | ||
|
||
|
||
def test_ne(): | ||
alias g3 = Signature(3, 0, 0) | ||
assert_false(Multivector[g3, g3.empty_mask()]().__ne__(Float64(0))) | ||
assert_false(Multivector[g3, g3.vector_mask()](1, 2, 3).__ne__(Multivector[g3, g3.vector_mask()](1, 2, 3))) | ||
assert_true(Multivector[g3, g3.vector_mask()](1, 2, 3).__ne__(Multivector[g3, g3.vector_mask()](1, 4, 3))) | ||
assert_true(Multivector[g3, g3.vector_mask()](1, 2, 3).__ne__(Float64(1))) | ||
|
||
|
||
def test_subspace_constructor(): | ||
assert_true(scalar[G3](6) == Multivector[G3](6)) | ||
assert_true(scalar[G3](0) != Multivector[G3](6)) | ||
|
||
assert_true(vector[G3](1, 2, 3) == Multivector[G3, G3.vector_mask()](1, 2, 3)) | ||
assert_true(vector[G3](1, 0, 3) != Multivector[G3, G3.vector_mask()](1, 2, 3)) | ||
|
||
assert_true(bivector[G3](4, 5, 6) == Multivector[G3, G3.bivector_mask()](4, 5, 6)) | ||
assert_true(bivector[G3](4, 0, 6) != Multivector[G3, G3.bivector_mask()](4, 5, 6)) | ||
|
||
|
||
def test_getattr(): | ||
alias g3 = Signature(3, 0, 0) | ||
alias scalar_vector_mask = List(True, True, True, True, False, False, False, False) | ||
assert_equal(Multivector[g3](6).s, Float64(6)) | ||
assert_equal(Multivector[g3, g3.vector_mask()](7, 8, 9).s, Float64(0)) | ||
assert_equal(Multivector[g3, scalar_vector_mask](6, 7, 8, 9).s, Float64(6)) | ||
|
||
|
||
def test_normalized(): | ||
alias g3 = Signature(3, 0, 0) | ||
assert_true(Multivector[g3, g3.vector_mask()](1, 2, 3).normalized() == Multivector[g3, g3.vector_mask()](0.2672612419124244, 0.53452248382484879, 0.80178372573727319)) | ||
assert_true(Multivector[g3, g3.bivector_mask()](1, 2, 3).normalized() == Multivector[g3, g3.bivector_mask()](0.2672612419124244, 0.53452248382484879, 0.80178372573727319)) | ||
|
||
|
||
def test_add(): | ||
alias g3 = Signature(3, 0, 0) | ||
alias scalar_vector_mask = List(True, True, True, True, False, False, False, False) | ||
assert_true(Multivector[g3, g3.vector_mask()](1, 2, 3).__add__(Multivector[g3, g3.vector_mask()](1, 2, 3)) == Multivector[g3, g3.vector_mask()](2, 4, 6)) | ||
assert_true(Multivector[g3, g3.vector_mask()](1, 2, 3).__add__(Float64(1)) == Multivector[g3, scalar_vector_mask](1, 1, 2, 3)) | ||
|
||
|
||
def test_sub(): | ||
alias g3 = Signature(3, 0, 0) | ||
alias scalar_vector_mask = List(True, True, True, True, False, False, False, False) | ||
assert_true(Multivector[g3, g3.vector_mask()](2, 4, 6).__sub__(Multivector[g3, g3.vector_mask()](1, 2, 3)) == Multivector[g3, g3.vector_mask()](1, 2, 3)) | ||
assert_true(Multivector[g3, g3.vector_mask()](1, 2, 3).__sub__(Float64(1)) == Multivector[g3, scalar_vector_mask](-1, 1, 2, 3)) | ||
|
||
|
||
def test_mul(): | ||
alias g3 = Signature(3, 0, 0) | ||
assert_true(Multivector[g3, g3.vector_mask()](1, 2, 3).__mul__(Float64(2)) == Multivector[g3, g3.vector_mask()](2, 4, 6)) | ||
assert_true(Multivector[g3, g3.vector_mask()](1, 2, 3).__mul__(Multivector[g3, g3.antiscalar_mask()](1)) == Multivector[g3, g3.bivector_mask()](3, -2, 1)) | ||
|
||
alias ug3 = Signature(1, 1, 1, flip_ze = False) | ||
alias v1_mask = List(False, True, False, False, False, False, False, False) | ||
assert_true(Multivector[ug3, v1_mask](2).__mul__(Multivector[ug3, v1_mask](2)) == Float64(4)) | ||
alias v2_mask = List(False, False, True, False, False, False, False, False) | ||
assert_true(Multivector[ug3, v2_mask](2).__mul__(Multivector[ug3, v2_mask](2)) == Float64(-4)) | ||
alias v3_mask = List(False, False, False, True, False, False, False, False) | ||
assert_true(Multivector[ug3, v3_mask](2).__mul__(Multivector[ug3, v3_mask](2)) == Float64(0)) | ||
|
||
alias pg3 = Signature(3, 0, 1, flip_ze = True) | ||
alias niltrivector_mask = List(False, False, False, False, False, False, False, False, False, False, False, True, True, True, False, False) | ||
assert_true(Multivector[pg3, pg3.vector_mask()](1, 2, 3, 4).__mul__(Float64(2)) == Multivector[pg3, pg3.vector_mask()](2, 4, 6, 8)) | ||
assert_true(Multivector[pg3, pg3.vector_mask()](1, 2, 3, 4).__mul__(Multivector[pg3, pg3.antiscalar_mask()](1)) == Multivector[pg3, niltrivector_mask](-4, 3, -2)) | ||
|
||
|
||
def test_sandwich(): | ||
alias g3 = Signature(3, 0, 0) | ||
assert_true(Multivector[g3, g3.even_mask()](0, 1, 0, 0)(Multivector[g3, g3.vector_mask()](1, 2, 3)) == Multivector[g3, g3.vector_mask()](-1, -2, 3)) |