# Equations

Calculate with symbols as numbers:

```
:x+:y
:x*:y
:x/:y
:x^3
sqrt(:x)&@equ x=y^2 # :y
simplify(:a/:a) # 1, so beware of cases where a=0
print(simplify((:a+:b)^2)) # a a + 2 a b + b b
```

Specify equations conveniently with the equ macros:

```
x=@equ x=a*b^sqrt(y)+c/d
x&@equs(a=3, b=2, y=9, c=8, d=4)
```

Operate on equations:

```
tri=@equ c^2=a^2+b^2
print(sqrt(tri))
#c = √(a a + b b)
```

Interpolate with $:

```
b=3;@equ a=$b #:a ≖ 3
@equ P=Ten($(map(x->pi^x,1:3)),i)
@equs(e=$ℯ, pi=$pi, M=$(rand(3,2)))
```

Substitute with & (see the plasma tests for real usage examples):

```
energy=@equ E=m*c^2
c=@equ c=299792458
m=@equ m=3*n
n=@equ n=9
@assert (energy&c&m&n).rhs == 3*9*299792458^2
```

& also does pattern matching:

```
print((Der(:x^:n,:x)-Der(-0.1*:x^:m,:x)+1/:a*Der(:a*sqrt(:x),:x))&relations["Der"])
#n Pow(x,n + (-1)) + 0.1 m Pow(x,m + (-1)) + 0.5 /(Pow(x,0.5))
```

Write your own patterns as equations:

```
relation=@equ Log(:a,:a)=1
Log(:e)&relation
Log(9,9)&relation
Log(:x+:y,:x+:y)&relation
```

Use the Oneable type for optional coefficients:

```
rel=@equ Oneable(a)*x*z=y
:q*:r&rel
```

& is overloaded to apply custom functions enabling chains of arbitrary behavior:

```
eq=3*:x^2-5*:x+1.5 ≖ 0
meq=eq&quadratic
@assert evaluate(eq.lhs,Dict(:x=>meq[1].rhs))==0
f1(ex::Expression)=ex[1][1]
f2(fac::Factor)=3*fac
@assert (:a+:b)&[f1,f2]==3*:a
f3(eq::Equation)=eq'
f4(eq::Equation)=sqrt(eq)
@equ(a=b^2)&[f3,f4]
```

Tensors are available! The summation convention applies automatically. See the tensors file in examples for usage.

```
Ten(:I,[:i,:i])&@equ I=[1 0;0 1] # 2
Ten(:A,[:i,:i])&@equ A=[:a 0;0 :b] # a+b
Ten(:A,:i)*Ten(:B,:j)&@equs(A=[1,2,3],B=[3,2,1], j=i)
Ten(:A,[:j,:i,:i])*Ten(:B,:j)&@equs(A=ones(3,3,3), B=[1,2,3]) # 18
Alt([:i,:j,:k])*Ten([:a1,:a2,:a3],:j)*Ten([:b1,:b2,:b3],:k)&@equ i=1
```

To include units use the U type (sensitive to ordering, put unitless stuff last):

```
l=U(:l,:meter);t=U(:t,:second);v=l/t;print(v)
```

Equations can also be constructed without macros (the ≖ is written as \eqcirc+tab) and results derived by checking for matches:

```
rule=Der(:a*:x,:x)≖:a # equivalent to Equation(Der(:a*:x,:x),:a)
ex=Der(3*:x,:x)
m=matches(ex,rule)[1] # equivalent to ex&rule
```

Simplification is automatic when using & however sometimes has to be carried out manually:

```
simplify((:x+:y)^3)
simplify(:x*:y/:x)
simplify(sqrt(:x*:z*:y*:z*:y*:x))
```

Equations have a left hand side (lhs) and a right hand side (rhs) that when omitted defaults to 0.

```
eq=Equation(:x*:z+:y)
eq.rhs
matches(eq)
eq=Equation(:x^2,9)
matches(eq,Sqrt)
```

If you try to evaluate an equation that has been constructed through division matching by setting one of the divided symbols to zero an error will be thrown:

```
meq=matches(:x^2+:a*:x≖0,Div)[1]
evaluate(meq,Dict(:x=>0))
```