-
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
163 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,30 @@ | ||
Infrared is a geometric algebra library for Mojo. | ||
|
||
Geometric algebras are clifford algebras 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 using the 'geometric product', they can be multiplied together. | ||
|
||
With infrared, you can generate product tables of arbitrary signature, and parameterize multivectors. | ||
Multivectors are also parameterized on arbitrary basis masks, to avoid unnecessary overhead. | ||
|
||
example: | ||
``` | ||
alias sig = Signature(2, 0, 1) | ||
var mv = Multivector[sig, sig.vector_mask()](2.0, -1.0) | ||
``` | ||
|
||
Infrared has no dependecies other than max/mojo | ||
|
||
Developers can use infrared to explore geometric algebra, | ||
or as a mathematical abstraction over all forms of geometry | ||
(such as projective, conformal, spacetime, dimension agnostric, etc.) | ||
|
||
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)) |