Skip to content
computer algebra system written in lua
HTML Lua
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
export
js
matrix
op
physics
tensor
tests
visitor
Array.lua
Constant.lua
Derivative.lua
Expression.lua
Function.lua
Heaviside.lua
Integral.lua
Invalid.lua
LICENSE
Matrix.lua
README.contents.md
README.md
Sum.lua
Tensor.lua
Variable.lua
Vector.lua
abs.lua
acos.lua
acosh.lua
asin.lua
asinh.lua
atan.lua
atan2.lua
atanh.lua
clone.lua
commutativeRemove.lua
complex.lua
cos.lua
cosh.lua
distributeDivision.lua
eval.lua
exp.lua
expand.lua
factor.lua
factorDivision.lua
factorLinearSystem.lua
log.lua
make_README.lua
map.lua
nodeCommutativeEqual.lua
polyCoeffs.lua
primeFactors.lua
prune.lua
replace.lua
setup.lua
simplify.lua
sin.lua
sinh.lua
solve.lua
sqrt.lua
symmath-dev-1.rockspec
symmath.lua
tableCommutativeEqual.lua
tan.lua
tanh.lua
taylor.lua
tidy.lua

README.md

Symbolic Math library for Lua

TLDR

require 'symmath'.setup{implicitVars=true}
Tensor.coords{{variables={r,theta,phi}}}
u = Tensor('^I', r*sin(theta)*cos(phi), r*sin(theta)*sin(phi), r*cos(theta))
print('u^I:\n'..u)
e = Tensor'_i^I'
e['_a^I'] = u'^I_,a'()
print('e_a^I:\n'..e)
delta = Tensor('_IJ', table.unpack(Matrix.identity(3)))
print('delta_IJ:\n'..delta)
g = (e'_a^I' * e'_b^J' * delta'_IJ')()
print('g_ab:\n'..g)
Tensor.metric(g)
dg = Tensor'_abc'
dg['_abc'] = g'_ab,c'()
print('g_ab,c:\n'..dg)
GammaL = ((dg'_abc' + dg'_acb' - dg'_bca')/2)()
print('Gamma_abc:\n'..GammaL)
Gamma = GammaL'^a_bc'()
print('Gamma^a_bc:\n'..Gamma)
dGamma = Tensor'^a_bcd'
dGamma['^a_bcd'] = Gamma'^a_bc,d'()
print('Gamma^a_bc,d:\n'..dGamma)
GammaSq = Tensor'^a_bcd'
GammaSq['^a_bcd'] = (Gamma'^a_ce' * Gamma'^e_db')()
Riemann = Tensor'^a_bcd'
Riemann['^a_bcd'] = (dGamma'^a_dbc' - dGamma'^a_cbd' + GammaSq'^a_bcd' - GammaSq'^a_bdc')()
print('Riemann^a_bcd:\n'..Riemann)

...makes this...

u^I:
       I↓        
┌r sin(θ) cos(φ)┐
│               │
│r sin(θ) sin(φ)│
│               │
└   r cos(θ)    ┘
e_a^I:
                       i↓I→                       
┌                                                ┐
│   sin(θ) cos(φ)     sin(θ) sin(φ)      cos(θ)  │
│                                                │
│  r cos(θ) cos(φ)   r cos(θ) sin(φ)   - r sin(θ)│
│                                                │
│ - r sin(θ) sin(φ)  r sin(θ) cos(φ)       0     │
└                                                ┘
delta_IJ:
  I↓J→   
┌       ┐
│1  0  0│
│       │
│0  1  0│
│       │
│0  0  1│
└       ┘
g_ab:
       a↓b→        
┌                 ┐
│1   0       0    │
│                 │
│    2            │
│0  r        0    │
│                 │
│        2       2│
│0   0  r  sin(θ) │
└                 ┘
g_ab,c:
                 a↓[b↓c→]                 
┌                 b↓c→                   ┐
│               ┌       ┐                │
│               │0  0  0│                │
│               │       │                │
│               │0  0  0│                │
│               │       │                │
│               │0  0  0│                │
│               └       ┘                │
│                                        │
│                 b↓c→                   │
│             ┌           ┐              │
│             │  0    0  0│              │
│             │           │              │
│             │2.0 r  0  0│              │
│             │           │              │
│             │  0    0  0│              │
│             └           ┘              │
│                                        │
│                  b↓c→                  │
│┌                                      ┐│
││      0                  0           0││
││                                      ││
││      0                  0           0││
││                                      ││
││            2       2                 ││
││2.0 r sin(θ)   2.0 r  sin(θ) cos(θ)  0││
└└                                      ┘┘
Gamma_abc:
                    a↓[b↓c→]                     
┌             ┌                   ┐             ┐
│             │0   0        0     │             │
│             │                   │             │
│             │0  -r        0     │             │
│             │                   │             │
│             │                  2│             │
│             │0   0   - r sin(θ) │             │
│             └                   ┘             │
│                                               │
│          ┌                         ┐          │
│          │0  r           0         │          │
│          │                         │          │
│          │r  0           0         │          │
│          │                         │          │
│          │          2              │          │
│          │0  0   - r  sin(θ) cos(θ)│          │
│          └                         ┘          │
│                                               │
│┌                                             ┐│
││                                         2   ││
││    0              0             r sin(θ)    ││
││                                             ││
││                              2              ││
││    0              0         r  sin(θ) cos(θ)││
││                                             ││
││        2   2                                ││
││r sin(θ)   r  sin(θ) cos(θ)          0       ││
└└                                             ┘┘
Gamma^a_bc:
           a↓[b↓c→]           
┌   ┌                   ┐    ┐
│   │0   0        0     │    │
│   │                   │    │
│   │0  -r        0     │    │
│   │                   │    │
│   │                  2│    │
│   │0   0   - r sin(θ) │    │
│   └                   ┘    │
│                            │
│┌                          ┐│
││      1                   ││
││ 0   ╶─╴          0       ││
││      r                   ││
││                          ││
││ 1                        ││
││╶─╴   0           0       ││
││ r                        ││
││                          ││
││ 0    0    - sin(θ) cos(θ)││
│└                          ┘│
│                            │
│ ┌                       ┐  │
│ │                   1   │  │
│ │ 0       0        ╶─╴  │  │
│ │                   r   │  │
│ │                       │  │
│ │                cos(θ) │  │
│ │ 0       0     ╶──────╴│  │
│ │                sin(θ) │  │
│ │                       │  │
│ │ 1    cos(θ)           │  │
│ │╶─╴  ╶──────╴      0   │  │
│ │ r    sin(θ)           │  │
└ └                       ┘  ┘
Gamma^a_bc,d:
                                   a↓b→[c↓d→]                                   
┌                                                                              ┐
│                                                        c↓d→                  │
│     c↓d→                c↓d→          ┌                                     ┐│
│   ┌       ┐          ┌        ┐       │     0                 0            0││
│   │0  0  0│          │ 0  0  0│       │                                     ││
│   │       │          │        │       │     0                 0            0││
│   │0  0  0│          │-1  0  0│       │                                     ││
│   │       │          │        │       │         2                           ││
│   │0  0  0│          │ 0  0  0│       │ - sin(θ)    - 2.0 r sin(θ) cos(θ)  0││
│   └       ┘          └        ┘       └                                     ┘│
│                                                                              │
│     c↓d→                c↓d→                                                 │
│┌             ┐     ┌             ┐                      c↓d→                 │
││   0     0  0│     │     1       │         ┌                            ┐    │
││             │     │   ╶──╴      │         │0             0            0│    │
││     1       │     │ -   2   0  0│         │                            │    │
││   ╶──╴      │     │    r        │         │0             0            0│    │
││ -   2   0  0│     │             │         │                            │    │
││    r        │     │   0     0  0│         │      ╭                2╮   │    │
││             │     │             │         │0   - ╰1.0 - 2.0 sin(θ) ╯  0│    │
││   0     0  0│     │   0     0  0│         └                            ┘    │
│└             ┘     └             ┘                                           │
│                                                                              │
│                                                         c↓d→                 │
│                                              ┌                        ┐      │
│     c↓d→                c↓d→                 │     1                  │      │
│┌             ┐  ┌                  ┐         │   ╶──╴                 │      │
││   0     0  0│  │0        0       0│         │ -   2         0       0│      │
││             │  │                  │         │    r                   │      │
││   0     0  0│  │0        0       0│         │                        │      │
││             │  │                  │         │                1       │      │
││     1       │  │          1       │         │            ╶───────╴   │      │
││   ╶──╴      │  │      ╶───────╴   │         │   0      -        2   0│      │
││ -   2   0  0│  │0   -        2   0│         │             sin(θ)     │      │
││    r        │  │       sin(θ)     │         │                        │      │
│└             ┘  └                  ┘         │   0           0       0│      │
│                                              └                        ┘      │
└                                                                              ┘
Riemann^a_bcd:
           a↓b→[c↓d→]            
┌                               ┐
│  c↓d→       c↓d→       c↓d→   │
│┌       ┐  ┌       ┐  ┌       ┐│
││0  0  0│  │0  0  0│  │0  0  0││
││       │  │       │  │       ││
││0  0  0│  │0  0  0│  │0  0  0││
││       │  │       │  │       ││
││0  0  0│  │0  0  0│  │0  0  0││
│└       ┘  └       ┘  └       ┘│
│                               │
│  c↓d→       c↓d→       c↓d→   │
│┌       ┐  ┌       ┐  ┌       ┐│
││0  0  0│  │0  0  0│  │0  0  0││
││       │  │       │  │       ││
││0  0  0│  │0  0  0│  │0  0  0││
││       │  │       │  │       ││
││0  0  0│  │0  0  0│  │0  0  0││
│└       ┘  └       ┘  └       ┘│
│                               │
│  c↓d→       c↓d→       c↓d→   │
│┌       ┐  ┌       ┐  ┌       ┐│
││0  0  0│  │0  0  0│  │0  0  0││
││       │  │       │  │       ││
││0  0  0│  │0  0  0│  │0  0  0││
││       │  │       │  │       ││
││0  0  0│  │0  0  0│  │0  0  0││
│└       ┘  └       ┘  └       ┘│
└                               ┘

Goals:

  • Everything done in pure Lua / Lua syntax. No/minimal parsing.
  • Originally intended for computational physics. Implement equations in Lua, perform symbolic manipulation, generate functions (via symmath.compile)

Online demo and API at http://christopheremoore.net/symbolic-lua
Example used at http://christopheremoore.net/metric
and http://christopheremoore.net/gravitational-wave-simulation

Overall

symmath.setup(args)
Use this if you want to copy the symmath namespace into the global namespace.
args can include the following:
implicitVars - set this to true to create a variable from any reference to an uninitialized variable. Otherwise variables must be initialized manually.

Using symmath without symmath.setup().

local symmath = require 'symmath'
local a, r, theta, rho, M, Q = symmath.vars('a','r','\\theta','\\rho','M','Q')
print(Delta:eq(r^2 + a^2 + Q^2 - 2 * M * r))
print((Delta - (r^2 + a^2)) * a * symmath.sin(theta)^2 / rho^2)

Using symmath with symmath.setup() but without implicitVars removes the need to reference the symmath namespace, but still requires explicit creation of variables.

require 'symmath'.setup()
local a, r, theta, rho, M, Q = vars('a','r','\\theta','\\rho','M','Q')
print(Delta:eq(r^2 + a^2 + Q^2 - 2 * M * r))
print((Delta - (r^2 + a^2)) * a * sin(theta)^2 / rho^2)

Using symmath with symmath.setup{implicitVars=true} removes the need for symmath namespace references and the need for explicit creation of variables.
Notice that underscores and Greek letters are automatically converted to appropriate TeX symbols.

require 'symmath'.setup{implicitVars=true}
print(Delta:eq(r^2 + a^2 + Q^2 - 2 * M * r))
print((Delta - (r^2 + a^2)) * a * sin(theta)^2 / rho^2)

Alternatively, you can run Lua with -lsymmath.setup, which is equivalent to require 'symmath.setup, which calls require 'symmath'.setup().

Numbers

For the most part Lua numbers will work, and will automatically be replaced by symmath Constants (found in symmath.Constant). This is because Constant is a subclass of Expression, and I was too lazy to implement all the ridiculous number of edge cases required to handle Lua numbers, though I am thinking about doing this. Constant can be constructed with numbers (Constant(0), Constant(1), etc) or with complex values (Constant{re=1, im=0}, etc).

Complex values can be represented by symmath.complex, which uses builtin complex types when run within LuaJIT, or uses a pure-Lua alternative otherwise.

Some day I will properly represent sets (naturals, integers, rationals, reals, complex, etc), and maybe groups, rings, etc, but not for now.

Some day I will also add support for infinite precision or big integers, but not right now.

Variables

var = symmath.Variable(name[, dependencies])
var = symmath.var(name[, dependencies])
var1, var2, ... = symmath.vars(name1, name2, ...)
Create a variable with given name, and optionally a list of which variables it is dependent on for differentiation. By default variables of different names have a derivative of zero.

var:depends(var1, var2, ...)
Specify the variables that var is dependent on for differentiation.

func, code = symmath.compile(expr, {var1, var2, ...}, language)
func, code = expr:compile{var1, var2, ...}
Compiles an expression to a Lua function with the listed vars as parameters.
language can be one of the following:

  • Lua
  • JavaScript
  • C
  • LaTeX
  • MathJax
  • GnuPlot

symmath.GnuPlot:plot(args)
Produces SVG of a plot. Requires my lua-gnuplot library.
Arguments are forwarded to the gnuplot lua module, with the expression provided in place of the plot command.

symmath.fixVariableNames = true Set this flag to true to have the LaTex and console outputs replace variable names with their associated unicode characters. For example, var'theta' will produce a variable with the name θ.

Arithmetic

symmath.op.unm(a)
-a when used with symmath expressions
Creates an expression representing the negative of the parameter.

symmath.op.add(a, b)
a + b when used with symmath expressions
Creates an expression representing the sum of the parameters.

symmath.op.mul(a, b)
a * b when used with symmath expressions
Creates an expression representing the product of the parameters.

symmath.op.sub(a, b)
a - b when used with symmath expressions
Creates an expression representing the difference of the parameters.

symmath.op.div(a, b)
a / b when used with symmath expressions
Creates an expression representing a fraction of the parameters.

symmath.op.pow(a, b)
a ^ b when used with symmath expressions
Creates an expression representing the first parameter raised to the power of the second parameter.

symmath.op.mod(a, b)
a % b when used with symmath expressions
Creates an expression representing the first parameter modulo the second.

Equations

eqn = symmath.op.eq(lhs, rhs)
eqn = lhs:eq(rhs)
Creates an equation representing the equality lhs = rhs.

eqn = symmath.op.ne(lhs, rhs)
eqn = lhs:ne(rhs)
Creates an equation representing the inequality lhs ≠ rhs.

eqn = symmath.op.lt(lhs, rhs)
eqn = lhs:lt(rhs)
Creates an equation representing the inequality lhs < rhs.

eqn = symmath.op.le(lhs, rhs)
eqn = lhs:le(rhs)
Creates an equation representing the inequality lhs ≤ rhs.

eqn = symmath.op.gt(lhs, rhs)
eqn = lhs:gt(rhs)
Creates an equation representing the inequality lhs > rhs.

eqn = symmath.op.ge(lhs, rhs)
eqn = lhs:ge(rhs)
Creates an equation representing the inequality lhs ≥ rhs.

lhs = eqn:lhs()
Returns the left hand side of the equation.

rhs = eqn:rhs()
Returns the right hand side of the equation.

soln1, soln2, ... = symmath.solve(eqn, var)
soln1, soln2, ... = eqn:solve(var)
Returns solutions to the equation. If eqn is not an Equation then returns solutions to eqn = 0.

newexpr = expr:subst(eqn)
Shorthand for expr:replace(eqn:lhs(), eqn:rhs()).

Expressions

symmath.simplify(expr)
expr:simplify()
expr()
Simplifies the expression.

symmath.clone(expr)
Clones an expression.
This also replaces Lua numbers with symmath Constant objects.

symmath.replace(expr, find, repl, callback)
expr:replace(find, repl, callback)
Replaces portions of an expression with another.
expr = expression to change.
find = sub-expression to find.
repl = sub-expression to replace.
callback(node) = callback per node, returns 'true' if we don't want to find/replace this tree.

symmath.map(expr, callback)
expr:map(callback)
Maps sub-expressions in an expression to new sub-expressions.
expr = expression.
callback(node) = callback that returns nil if it leaves the tree untouched, returns a value if it wishes to change the tree.

symmath.eval(expr, {[var1]=value, var2name=value, ...})
expr:eval{[var1]=value, var2name=value, ...}
Calculates the numeric value of the expression.

symmath.polyCoeffs(expr, var)
expr:polyCoeffs(var)
Returns a table of coefficients with keys 0 through the degree of the polynomial, and 'extra' containing all non-polynomial terms.

Calculus

symmath.diff(expr, var1, var2, ...)
expr:diff(var1, var2, ...)
Differentiates the expression with respect to the given variable.

Linear Algebra

A = symmath.Matrix({expr11, expr12 ...}, {expr21, expr22, ...}, ...)
Create a matrix of expressions.

A = symmath.Array(...)
Create an array of expressions. Same deal as Matrix but with any arbitrary nesting depth, and without Matrix-specific operations.

AInv, I, message = A:inverse([b, callback, allowRectangular])
returns
AInv = the inverse of matrix A.
I = what's left of the Gauss-Jordan solver (typically the identity matrix).
message = any error that occured during solving.
args:
b = solution vector. If specified, returns x such that A x = b.
callback = function to be called after each Gauss-Jordan operation.
allowRectangular = set to true to allow inverting rectangular matrices.

APlus, determinable = A:pseudoInverse()
Returns the pseudoinverse of A (stored in APlus) and whether the pseudoinverse is determinable.

d = A:determinant()
Returns the determinant of A.

At = A:transpose()
Returns the transpose of A

I = Matrix.identity([m, n])
Returns 1 if no arguments are provided.
Returns a m x m identity matrix if one argument is provided.
Returns a m x n identity matrix if two arguments are provided.

D = Matrix.diagonal(d1, d2, d3, ...)
Returns a n x n matrix with diagonal elements set to d1 ... dn, for n the number of arguments provided.

tr = A:trace()
Returns the trace of A.

Tensors

Tensor.coords{ {variables={t,x,y,z}} }
Specifies that tensors will be using coordinates t,x,y,z

Tensor.coords{ {variables={t,x,y,z}, meric=g} }
Specifies that tensors will be using coordinates t,x,y,z with metric 'g' (a Matrix or 2D array). The metric inverse will be automatically computed.

Tensor.coords{ {variables={t,x,y,z}, meric=g, metricInverse=gU} }
Specifies that tensors will be using coordinates t,x,y,z with metric 'g' (a Matrix or 2D array) and metric inverse 'gU'.

Tensor.coords{ {variables={t,x,y,z}}, {symbols='ijklmn', variables={x,y,z}} }
Specifies that tensors will be using coordinates t,x,y,z, except for indexes ijklmn which will only use x,y,z.
At the moment conversion between maps is very ugly/incomplete.

Tensor.metric(g, [gU, symbol])
Specifies to use metric 'g' for the default coordinate system (assuming one has been defined with Tensor.coords).

t = Tensor'_abc'
Creates a degree-3 covariant tensor 't' with all values initialized to 0.

... tensor summation / multiplication ...
( u'^a' * v'_b' * eps'_a^bc_d' )() produces a degree-2 tensor perpendicular to 'u' and 'v' (assuming eps is defined as the Levi-Civita tensor).

... comma derivatives (semicolon derivatives almost there, just need to store the connection coefficients) ...

... assignment: S = T'_ab' - T'_ba'
in this case the indexes of 'S' are picked on a first-come, first-serve basis. If you want to be certain of the assignment, use the following:

S = Tensor'_ab'
S['_ab'] = (T'_ab' - T'_ba')()
(the final () is shorthand for :simplify(), which will evaluate the expression into the tensor structure).

... index gymnastics (so long as you defined a metric): v = Tensor('_a', ...) print(v'^a'()) will show you the contents of v^a = g^ab v_b.

t:permute'_ba' Rearranges the internal storage of t

t:print't'
Prints the tensor's contents.

t:printElem't'
Prints the individual nonzero values of the tensor, or '0' if they are all zero.

Dependencies:

Some tests use:

make_README.lua uses (for building the README.md):

  • LuaSocket, for its URL building functions.

TODO

  • solving equalities

  • integrals. symbolic, numeric explicit, then eventually get to numeric implicit (this involves derivatives based on both the dependent and the state variable)

  • functions that lua has that I don't: ceil, floor, deg, rad, fmod, frexp, log10, min, max

  • support for numbers rather than only Constant

  • combine symmath with the lua-parser to decompile lua code -> ast -> symmath, perform symbolic differentiation on it, then recompile it ... i.e. f = [[function(x) return x^2 end]] g = symmath:luaDiff(f, 'x') <=> g = [[function(x) return 2*x end]]

  • subindexes, so you can store a tensor of tensors: g_ab = Tensor('_ab', {-alpha^2+beta^2, beta_j}, {beta_i, gamma_ij}) (Though this is a lot of work for a rarely used feature...)

  • change canonical form from 'div add sub mul' to 'add sub mul div'. also split apart div mul's into mul divs and then factor add mul's into mul add's for simplification of fractions

  • sets associated with variables. easy ones for starters: *) naturals *) integers *) rings *) rationals *) irrationals *) algebraic *) transcendental *) reals (extended reals by default? or a separate set for extended reals?) *) complex *) quaternions *) octonions

    ... and associated properties ...

    Natural + Natural => Natural Natural - Natural => Integer Natural * Natural => Natural Natural / Natural => Rational

    Natural + Integer => Integer Natural - Integer => Integer Natural * Integer => Integer Natural / Integer => Rational

    Integer + Natural => Integer Integer - Natural => Integer Integer * Natural => Integer Integer / Natural => Rational

    Integer + Integer => Integer Integer - Integer => Integer Integer * Integer => Integer Integer / Integer => Rational

    Natural (+-/) Rational => Rational Integer (+-/) Rational => Rational

    etc...

  • ranges/sets/conditions associated with expressions so x in Reals, 1/x, simplified, gives 1/x (x~=0) and x in Reals, sqrt(x), simplified, gives sqrt(x) (x>=0) and x in Reals, sqrt(f(x)), simplified, gives sqrt(f(x)) (f(x)>=0) and x in Reals, sqrt(x+1), simplified, gives sqrt(x+1) (x>=-1)

  • better rules for processing everything. something where you provide patterns and it searches through and replaces accordingly. patterns like... unm: -(-a) => a [-c] => -[c] ... for c > 0 add: a + 0 => a 0 + a => a a + (b + c) => (a + b) + c ... only if a,b,c are associative under + [c1] + [c2] => [c1+c2] a + b => b + a ... only if a and b are commutative under +, and if our precedence of variables states precedence(b) < precedence(a) sub: a - 0 => a 0 - a => -a a - (-b) => a + b a - (b - c) => (a - b) + c a - (b + c) => (a - b) - c a + (b - c) => (a + b) - c [c1] - [c2] => [c1-c2] mul: 1 * 1 => 1 1 * -1 => -1 a * 0 => 0 0 * a => 0 a * 1 => a 1 * a => a a * -1 => -a -1 * a => -a [-c1] * a => -([c1] * a) ... for c1 > 0 (-a) * b => -(a * b) a * (-b) => -(a * b) (-a) * (-b) => a * b a * (b * c) => (a * b) * c ... only if a,b,c are associative under * a * (b + c) => a * b + a * c (a + b) * c => a * c + b * c [c1] * [c2] => [c1*c2] [c1] * a + [c2] * a => [c1+c2] * a [c1] * a - [c2] * a => [c1-c2] * a a * b => b * a ... only if a and b are commutative under *, and if our precedence of variables states precedence(b) < precedence(a) div: [c1] / [c2] => [factors(c1)\gcd(c1,c2)] / [factors(c2)\gcd(c1,c2)] for integers c1,c2 [c1] / 0 => undefined a / 0 => undefined 0 / a => 0 (for a ~= 0) a / 1 => a a / -1 => -a 1 / -a => -1 / a (for a ~= 0) a / a => 1 1 / (1 / a) => a (for a ~= 0) (-a) / b => -(a / b) a / (-b) => -(a / b) (-a) / (-b) => a / b (a * b) / a => b (for a ~= 0) (b * a) / a => b (for a = 0) (a + b) / c => a / c + b / c (a - b) / c => a / c - b / c a * (b / c) => (a * b) / c a / (b / c) => (a * c) / b (a / b) / c => a / (b * c) pow: a ^ 0 => 1 0 ^ 0 => 1 0 ^ a => { a=0: 1, a=0: 0} a ^ 1 => a 1 ^ a => 1 a ^ -1 => 1 / a a ^ -b => 1 / (a ^ b) a * a => a ^ 2 a * a ^ b => a ^ (1 + b) a ^ b * a => a ^ (b + 1) a ^ b * a ^ c => a ^ (b + c) (a ^ b) ^ c => a ^ (b * c)

distinct functions for all languages:

  • __call = produces a single expression of code, without checking variables
  • generate = produces the function body. multiple expressions. doing tree searches and moving common variables out front would be good.
  • compile = produces the Lua function. only for Lua. maybe for C if you are using LuaJIT and have access to a compiler

Output CDN URLs:

tests/output/ADM Levi-Civita

tests/output/ADM gravity using expressions

tests/output/ADM metric - mixed

tests/output/ADM metric

tests/output/Alcubierre

tests/output/BSSN

tests/output/Building Curvature by ADM

tests/output/EFE discrete solution - 1-var

tests/output/EFE discrete solution - 2-var

tests/output/Einstein field equations - expression

tests/output/Ernst

tests/output/FLRW

tests/output/Faraday tensor in general relativity

tests/output/Faraday tensor in special relativity

tests/output/FiniteVolume

tests/output/GLM-Maxwell

tests/output/Gravitation 16.1 - dense

tests/output/Gravitation 16.1 - expression

tests/output/Gravitation 16.1 - mixed

tests/output/Kaluza-Klein - index

tests/output/Kaluza-Klein - varying scalar field - index

tests/output/Kaluza-Klein

tests/output/Kerr-Schild - dense

tests/output/Kerr-Schild - expression

tests/output/Kerr-Schild degenerate case

tests/output/MHD inverse

tests/output/MHD symmetrization

tests/output/Maxwell equations in hyperbolic conservation form

tests/output/Newton method

tests/output/SRHD

tests/output/Schwarzschild - isotropic

tests/output/Schwarzschild - spherical - derivation - varying time 2

tests/output/Schwarzschild - spherical - derivation - varying time

tests/output/Schwarzschild - spherical - derivation

tests/output/Schwarzschild - spherical - mass varying with time

tests/output/Schwarzschild - spherical

tests/output/TOV

tests/output/electrovacuum/black hole electron

tests/output/electrovacuum/general case

tests/output/electrovacuum/infinite wire no charge

tests/output/electrovacuum/infinite wire

tests/output/electrovacuum/uniform field - Cartesian

tests/output/electrovacuum/uniform field - cylindrical

tests/output/electrovacuum/uniform field - spherical

tests/output/electrovacuum/verify cylindrical transform

tests/output/exp_metric

tests/output/hydrodynamics

tests/output/linearized Euler fluid equations

tests/output/metric catalog

tests/output/natural units

tests/output/numeric integration

tests/output/remove beta from adm metric

tests/output/rotation group

tests/output/run all tests

tests/output/scalar metric

tests/output/simple_ag

tests/output/spacetime embedding radius

tests/output/spinors

tests/output/spring force

tests/output/symbols

tests/output/tensor coordinate invariance

tests/output/toy-1+1 spacetime

tests/output/unit/linear solver

tests/output/unit/matrix

tests/output/unit/partial replace

tests/output/unit/sub-tensor assignment

tests/output/unit/tensor use case

tests/output/unit/test

tests/output/unit/tidyIndexes

tests/output/wave equation with metric of space and time - based on bssnok-scalar

You can’t perform that action at this time.