Last active
March 7, 2025 02:40
-
-
Save Orbots/56f0eebfd1190160a217c26b68c1f726 to your computer and use it in GitHub Desktop.
Ga3.jl
This file contains hidden or 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
| # Geometric Algebra G(3) Library in Julia | |
| # Types | |
| struct G3Empty end | |
| struct G3Vector{T<:Number} | |
| e1::T | |
| e2::T | |
| e3::T | |
| end | |
| struct G3Bivector{T<:Number} | |
| e23::T | |
| e31::T | |
| e12::T | |
| end | |
| struct G3Spinor{T<:Number} | |
| s::T | |
| B::G3Bivector{T} | |
| end | |
| struct G3Pseudoscalar{T<:Number} | |
| e123::T | |
| end | |
| struct G3Oddspinor{T<:Number} | |
| v::G3Vector{T} | |
| P::G3Pseudoscalar{T} | |
| end | |
| struct G3Multivector{T<:Number} | |
| s::T | |
| v::G3Vector{T} | |
| B::G3Bivector{T} | |
| P::G3Pseudoscalar{T} | |
| end | |
| # Constructors | |
| G3Vector{T}() where {T<:Number} = G3Vector{T}(zero(T), zero(T), zero(T)) | |
| G3Bivector{T}() where {T<:Number} = G3Bivector{T}(zero(T), zero(T), zero(T)) | |
| G3Pseudoscalar{T}() where {T<:Number} = G3Pseudoscalar{T}(zero(T)) | |
| G3Spinor{T}() where {T<:Number} = G3Spinor{T}(zero(T), G3Bivector{T}()) | |
| G3Oddspinor{T}() where {T<:Number} = G3Oddspinor{T}(G3Vector{T}(), G3Pseudoscalar{T}()) | |
| G3Multivector{T}() where {T<:Number} = G3Multivector{T}(zero(T), G3Vector{T}(), G3Bivector{T}(), G3Pseudoscalar{T}()) | |
| G3Vector{T}(x::Number, y::Number, z::Number) where {T<:Number} = G3Vector{T}(T(x), T(y), T(z)) | |
| G3Bivector{T}(x::Number, y::Number, z::Number) where {T<:Number} = G3Bivector{T}(T(x), T(y), T(z)) | |
| G3Spinor{T}(s::Number, x::Number, y::Number, z::Number) where {T<:Number} = G3Spinor{T}(T(s), G3Bivector{T}(x, y, z)) | |
| # Operations | |
| import Base: +, * | |
| +(a::T, b::T) where {T<:Number} = a + b | |
| +(a::G3Vector{T}, b::G3Vector{T}) where {T<:Number} = G3Vector{T}(a.e1 + b.e1, a.e2 + b.e2, a.e3 + b.e3) | |
| +(a::G3Bivector{T}, b::G3Bivector{T}) where {T<:Number} = G3Bivector{T}(a.e23 + b.e23, a.e31 + b.e31, a.e12 + b.e12) | |
| +(a::G3Pseudoscalar{T}, b::G3Pseudoscalar{T}) where {T<:Number} = G3Pseudoscalar{T}(a.e123 + b.e123) | |
| +(a::G3Spinor{T}, b::G3Spinor{T}) where {T<:Number} = G3Spinor{T}(a.s + b.s, a.B + b.B) | |
| +(a::G3Oddspinor{T}, b::G3Oddspinor{T}) where {T<:Number} = G3Oddspinor{T}(a.v + b.v, a.P + b.P) | |
| +(a::G3Multivector{T}, b::G3Multivector{T}) where {T<:Number} = G3Multivector{T}(a.s + b.s, a.v + b.v, a.B + b.B, a.P + b.P) | |
| *(a::T, b::T) where {T<:Number} = a * b | |
| *(s::T, v::G3Vector{T}) where {T<:Number} = G3Vector{T}(s * v.e1, s * v.e2, s * v.e3) | |
| *(v::G3Vector{T}, s::T) where {T<:Number} = G3Vector{T}(s * v.e1, s * v.e2, s * v.e3) | |
| *(s::T, B::G3Bivector{T}) where {T<:Number} = G3Bivector{T}(s * B.e23, s * B.e31, s * B.e12) | |
| *(B::G3Bivector{T}, s::T) where {T<:Number} = G3Bivector{T}(s * B.e23, s * B.e31, s * B.e12) | |
| *(s::T, q::G3Spinor{T}) where {T<:Number} = G3Spinor{T}(s * q.s, s * q.B) | |
| *(q::G3Spinor{T}, s::T) where {T<:Number} = G3Spinor{T}(s * q.s, s * q.B) | |
| *(s::T, P::G3Pseudoscalar{T}) where {T<:Number} = G3Pseudoscalar{T}(s * P.e123) | |
| *(P::G3Pseudoscalar{T}, s::T) where {T<:Number} = G3Pseudoscalar{T}(s * P.e123) | |
| *(s::T, o::G3Oddspinor{T}) where {T<:Number} = G3Oddspinor{T}(s * o.v, s * o.P) | |
| *(o::G3Oddspinor{T}, s::T) where {T<:Number} = G3Oddspinor{T}(s * o.v, s * o.P) | |
| *(a::G3Vector{T}, b::G3Vector{T}) where {T<:Number} = G3Spinor{T}( | |
| a.e1*b.e1 + a.e2*b.e2 + a.e3*b.e3, | |
| G3Bivector{T}(a.e2*b.e3 - b.e2*a.e3, a.e3*b.e1 - b.e3*a.e1, a.e1*b.e2 - b.e1*a.e2) | |
| ) | |
| *(a::G3Bivector{T}, b::G3Bivector{T}) where {T<:Number} = G3Spinor{T}( | |
| -a.e23*b.e23 - a.e31*b.e31 - a.e12*b.e12, | |
| G3Bivector{T}(a.e12*b.e31 - a.e31*b.e12, a.e23*b.e12 - a.e12*b.e23, a.e31*b.e23 - a.e23*b.e31) | |
| ) | |
| *(v::G3Vector{T}, B::G3Bivector{T}) where {T<:Number} = G3Oddspinor{T}( | |
| G3Vector{T}(v.e3*B.e31 - v.e2*B.e12, v.e1*B.e12 - v.e3*B.e23, v.e2*B.e23 - v.e1*B.e31), | |
| G3Pseudoscalar{T}(v.e1*B.e23 + v.e2*B.e31 + v.e3*B.e12) | |
| ) | |
| *(B::G3Bivector{T}, v::G3Vector{T}) where {T<:Number} = G3Oddspinor{T}( | |
| G3Vector{T}(-v.e3*B.e31 + v.e2*B.e12, -v.e1*B.e12 + v.e3*B.e23, -v.e2*B.e23 + v.e1*B.e31), | |
| G3Pseudoscalar{T}(v.e1*B.e23 + v.e2*B.e31 + v.e3*B.e12) | |
| ) | |
| *(v::G3Vector{T}, P::G3Pseudoscalar{T}) where {T<:Number} = G3Bivector{T}(v.e1*P.e123, v.e2*P.e123, v.e3*P.e123) | |
| *(P::G3Pseudoscalar{T}, v::G3Vector{T}) where {T<:Number} = G3Bivector{T}(v.e1*P.e123, v.e2*P.e123, v.e3*P.e123) | |
| *(B::G3Bivector{T}, P::G3Pseudoscalar{T}) where {T<:Number} = G3Vector{T}(-B.e23*P.e123, -B.e31*P.e123, -B.e12*P.e123) | |
| *(P::G3Pseudoscalar{T}, B::G3Bivector{T}) where {T<:Number} = G3Vector{T}(-B.e23*P.e123, -B.e31*P.e123, -B.e12*P.e123) | |
| *(a::G3Spinor{T}, b::G3Spinor{T}) where {T<:Number} = let AB = a.B * b.B | |
| G3Spinor{T}(a.s*b.s + AB.s, AB.B + (a.s * b.B) + (b.s * a.B)) | |
| end | |
| *(a::G3Pseudoscalar{T}, b::G3Pseudoscalar{T}) where {T<:Number} = -a.e123 * b.e123 | |
| # Wedge Product (∧) | |
| ∧(s::T, t::T) where {T<:Number} = s * t | |
| ∧(s::T, v::G3Vector{T}) where {T<:Number} = s * v | |
| ∧(v::G3Vector{T}, s::T) where {T<:Number} = s * v | |
| ∧(a::G3Vector{T}, b::G3Vector{T}) where {T<:Number} = G3Bivector{T}(a.e2*b.e3 - b.e2*a.e3, a.e3*b.e1 - b.e3*a.e1, a.e1*b.e2 - b.e1*a.e2) | |
| ∧(v::G3Vector{T}, B::G3Bivector{T}) where {T<:Number} = G3Pseudoscalar{T}(v.e1*B.e23 + v.e2*B.e31 + v.e3*B.e12) | |
| ∧(B::G3Bivector{T}, v::G3Vector{T}) where {T<:Number} = G3Pseudoscalar{T}(v.e1*B.e23 + v.e2*B.e31 + v.e3*B.e12) | |
| # Dual and Undual Operations | |
| dual(v::G3Vector{T}) where {T<:Number} = G3Bivector{T}(v.e1, v.e2, v.e3) | |
| dual(B::G3Bivector{T}) where {T<:Number} = G3Vector{T}(-B.e23, -B.e31, -B.e12) | |
| dual(P::G3Pseudoscalar{T}) where {T<:Number} = P.e123 | |
| dual(s::T) where {T<:Number} = G3Pseudoscalar{T}(s) | |
| undual(B::G3Bivector{T}) where {T<:Number} = G3Vector{T}(B.e23, B.e31, B.e12) | |
| undual(v::G3Vector{T}) where {T<:Number} = G3Bivector{T}(-v.e1, -v.e2, -v.e3) | |
| undual(s::T) where {T<:Number} = G3Pseudoscalar{T}(s) | |
| undual(P::G3Pseudoscalar{T}) where {T<:Number} = P.e123 | |
| # Regressive Product (∨) | |
| ∨(a, b) = dual(undual(a) ∧ undual(b)) | |
| # Utilities | |
| function Base.show(io::IO, v::G3Vector{T}) where {T<:Number} | |
| print(io, "$(v.e1)e₁ + $(v.e2)e₂ + $(v.e3)e₃") | |
| end | |
| function Base.show(io::IO, B::G3Bivector{T}) where {T<:Number} | |
| print(io, "$(B.e23)e₂₃ + $(B.e31)e₃₁ + $(B.e12)e₁₂") | |
| end | |
| function Base.show(io::IO, q::G3Spinor{T}) where {T<:Number} | |
| print(io, "$(q.s) + $(q.B)") | |
| end | |
| function Base.show(io::IO, P::G3Pseudoscalar{T}) where {T<:Number} | |
| print(io, "$(P.e123)e₁₂₃") | |
| end | |
| function Base.show(io::IO, o::G3Oddspinor{T}) where {T<:Number} | |
| print(io, "$(o.v) + $(o.P)") | |
| end | |
| function Base.show(io::IO, M::G3Multivector{T}) where {T<:Number} | |
| print(io, "$(M.s) + $(M.v) + $(M.B) + $(M.P)") | |
| end | |
| function Base.show(io::IO, ::G3Empty) | |
| print(io, "∅") | |
| end | |
| # Norm Squared Functions | |
| norm_sqr(s::T) where {T<:Number} = s * s | |
| norm_sqr(v::G3Vector{T}) where {T<:Number} = v.e1*v.e1 + v.e2*v.e2 + v.e3*v.e3 | |
| norm_sqr(B::G3Bivector{T}) where {T<:Number} = B.e23*B.e23 + B.e31*B.e31 + B.e12*B.e12 | |
| norm_sqr(P::G3Pseudoscalar{T}) where {T<:Number} = P.e123 * P.e123 | |
| norm_sqr(q::G3Spinor{T}) where {T<:Number} = q.s*q.s + norm_sqr(q.B) | |
| norm_sqr(o::G3Oddspinor{T}) where {T<:Number} = norm_sqr(o.v) + norm_sqr(o.P) | |
| norm_sqr(M::G3Multivector{T}) where {T<:Number} = M.s*M.s + norm_sqr(M.v) + norm_sqr(M.B) + norm_sqr(M.P) | |
| norm_sqr_study(S::G3Multivector{T}) where {T<:Number} = S.s*S.s + S.P.e123*S.P.e123 | |
| # Norm Functions | |
| norm_study(S::G3Multivector{T}) where {T<:Number} = sqrt(norm_sqr_study(S)) | |
| norm(x) = sqrt(norm_sqr(x)) | |
| # Normalization | |
| normalize(x) = x * (1.0 / norm(x)) | |
| # Inverse Functions | |
| inv(s::T) where {T<:Number} = 1.0 / s | |
| inv(v::G3Vector{T}) where {T<:Number} = v * (1.0 / norm_sqr(v)) | |
| inv(B::G3Bivector{T}) where {T<:Number} = B * (-1.0 / norm_sqr(B)) | |
| inv(P::G3Pseudoscalar{T}) where {T<:Number} = G3Pseudoscalar{T}(-1.0 / P.e123) | |
| inv(q::G3Spinor{T}) where {T<:Number} = conj(q) * (1.0 / norm_sqr(q)) | |
| inv(o::G3Oddspinor{T}) where {T<:Number} = conj(o) * (1.0 / norm_sqr(o)) | |
| study_conj(S::G3Multivector{T}) where {T<:Number} = G3Multivector{T}(S.s, zero(G3Vector{T}), zero(G3Bivector{T}), -S.P) | |
| inv_study(S::G3Multivector{T}) where {T<:Number} = study_conj(S) * (1.0 / (S * study_conj(S)).s) | |
| inv(M::G3Multivector{T}) where {T<:Number} = error("Inverse for general multivectors is not yet implemented.") | |
| inv(b::G3Biparavector{T}) where {T<:Number} = inv(to_multivector(b)) | |
| # Division | |
| divide(x, y) = x * inv(y) | |
| # Metric-Related Functions | |
| ## Right Complement | |
| rc(s::T) where {T<:Number} = G3Pseudoscalar{T}(s) | |
| rc(v::G3Vector{T}) where {T<:Number} = G3Bivector{T}(v.e1, v.e2, v.e3) | |
| rc(B::G3Bivector{T}) where {T<:Number} = G3Vector{T}(B.e23, B.e31, B.e12) | |
| rc(P::G3Pseudoscalar{T}) where {T<:Number} = P.e123 | |
| rc(q::G3Spinor{T}) where {T<:Number} = G3Oddspinor{T}(rc(q.B), rc(q.s)) | |
| rc(o::G3Oddspinor{T}) where {T<:Number} = G3Spinor{T}(rc(o.P), rc(o.v)) | |
| rc(M::G3Multivector{T}) where {T<:Number} = G3Multivector{T}(rc(M.P), rc(M.B), rc(M.v), rc(M.s)) | |
| ## Aliases | |
| const lc = rc | |
| const star = rc | |
| ## Regressive Product | |
| vee(a, b) = lc(wedge(rc(a), rc(b))) | |
| ## Dot Products | |
| dot(x, y) = vee(x, star(y)) | |
| rdot(x, y) = vee(x, star(y)) | |
| ldot(x, y) = vee(star(x), y) | |
| ## Left Contraction (Simplified) | |
| lcontract(a, b) = error("Full left contraction is not yet implemented.") | |
| # Transcendental Functions | |
| ## Exponential Functions | |
| exp(v::G3Vector{T}) where {T<:Number} = G3Paravector{T}(cosh(norm(v)), normalize(v) * sinh(norm(v))) | |
| exp(B::G3Bivector{T}) where {T<:Number} = G3Spinor{T}(cos(norm(B)), normalize(B) * sin(norm(B))) | |
| exp(q::G3Spinor{T}) where {T<:Number} = exp(q.s) * exp(q.B) | |
| exp(p::G3Paravector{T}) where {T<:Number} = G3Paravector{T}(exp(p.s) * exp(p.v).s, exp(p.s) * exp(p.v).v) | |
| exp(P::G3Pseudoscalar{T}) where {T<:Number} = G3Multivector{T}(cos(P.e123), zero(G3Vector{T}), zero(G3Bivector{T}), G3Pseudoscalar{T}(sin(P.e123))) | |
| exp(o::G3Oddspinor{T}) where {T<:Number} = to_multivector(exp(o.v)) * exp(o.P) | |
| exp(M::G3Multivector{T}) where {T<:Number} = error("Exponential for general multivectors is not yet implemented.") | |
| ## Square Root Functions | |
| sqrt(S::G3Multivector{T}) where {T<:Number} = begin | |
| c = sqrt(0.5 * (S.s + norm_study(S))) | |
| G3Multivector{T}(c, zero(G3Vector{T}), zero(G3Bivector{T}), (0.5 / c) * S.P) | |
| end | |
| sqrt(q::G3Spinor{T}) where {T<:Number} = begin | |
| n = norm_sqr(q) | |
| if abs(n - 1.0) > 1e-4 | |
| n = sqrt(n) | |
| q = q * (1.0 / n) | |
| s_sign = q.s < 0 ? -1.0 : 1.0 | |
| q = G3Spinor{T}(q.s + s_sign, q.B) | |
| sqrt(n) * normalize(q) | |
| else | |
| s_sign = q.s < 0 ? -1.0 : 1.0 | |
| q = G3Spinor{T}(q.s + s_sign, q.B) | |
| normalize(q) | |
| end | |
| end | |
| sqrt(B::G3Bivector{T}) where {T<:Number} = sqrt(G3Spinor{T}(0.0, B)) | |
| sqrt(P::G3Pseudoscalar{T}) where {T<:Number} = sqrt(G3Multivector{T}(0.0, zero(G3Vector{T}), zero(G3Bivector{T}), P)) | |
| ## Logarithm Functions | |
| log(q::G3Spinor{T}) where {T<:Number} = begin | |
| qn = norm_sqr(q) | |
| if abs(qn - 1.0) > 1e-4 | |
| qn = sqrt(qn) | |
| q = q * (1.0 / qn) | |
| log(qn) + normalize(q.B) * acos(q.s) | |
| else | |
| zero(T) + normalize(q.B) * acos(q.s) | |
| end | |
| end | |
| log(B::G3Bivector{T}) where {T<:Number} = log(G3Spinor{T}(0.0, B)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment