模組:Complex Number/CayleyDickson
外观

本模組為基於Module:Complex Number的凯莱-迪克森结构運算系統,可將Module:Complex Number系列函數庫的任一數學庫套用凯莱-迪克森结构形成新的數學庫,並能提供其他模組呼叫使用。而若要直接在模板或條目中使用可透過Module:Complex Number/Calculate或{{複變運算}}來完成。
模組內容
本模組有5套數學資料結構的定義以及對應的數學運算庫:
- .cdmathQuaternion
- 已將四元數套用凯莱-迪克森结构形成的代數結構之數學資料結構及運算的系統,可當八元數使用。
- .cdmathOctonion
- 已將八元數套用凯莱-迪克森结构形成的代數結構之數學資料結構及運算的系統,可當十六元數使用。
- .cdmathSedenion
- 已將十六元數套用凯莱-迪克森结构形成的代數結構之數學資料結構及運算的系統,可當三十二元數使用。
- .sdmath
- 十六元數的數學資料結構及運算的系統
使用方法
LUA
- 初始化數學庫
- 一般方法:
local 自訂函數庫名稱 = require("Module:Complex Number/CayleyDickson").函數庫名稱.init()
- 例如初始化十六元數數學庫:
local sdmath = require("Module:Complex Number/CayleyDickson").sdmath.init()
- 例如初始化十六元數數學庫:
- 套用凯莱-迪克森结构並初始化數學庫:
- 直接載入已套用凯莱-迪克森结构的數學庫並初始化:
local 自訂函數庫名稱 = require("Module:Complex Number/CayleyDickson")['cdmath=要套用凯莱-迪克森结构的數學庫的模組路徑和名稱'].init()
- 例如初始化將八元數(Module:Complex Number/Octonion)套用凯莱-迪克森结构所形成的十六元數數學庫:
local sdomath = require("Module:Complex Number/CayleyDickson")['cdmath=Module:Complex_Number/Octonion.omath'].init()
- 其中數學庫的模組路徑和名稱格式為
Module:模組名稱.數學庫名稱
- 例如初始化將八元數(Module:Complex Number/Octonion)套用凯莱-迪克森结构所形成的十六元數數學庫:
- 一般方法:
- 初始化指定數學結構的數字
local 變數名稱 = 自訂函數庫名稱.constructor("描述數字的字串,單位元素用ele(n)表示")
- 例如:
local num1 = sdomath.constructor("2+3*ele(2)+ele(4)")
- 例如:
- 執行運算
- 例如:
local sdomath = require("Module:Complex Number/CayleyDickson")['cdmath=Module:Complex_Number/Octonion.omath'].init() local num1 = sdomath.constructor("2+3*ele(2)+ele(4)") local num2 = sdomath.constructor("4+5*ele(3)+ele(4)") print(num1 * num2)
- 輸出:7+15*ele(1)+12*ele(2)+10*ele(3)+6*ele(4)+3*ele(6)-5*ele(7)
- 或者使用函數庫內容:
local sdomath = require("Module:Complex Number/CayleyDickson")['cdmath=Module:Complex_Number/Octonion.omath'].init() local num1 = sdomath.constructor("2+3*ele(2)+ele(4)") print(sdomath.sqrt(num1))
- 輸出:1.6943519980768+0.88529420197369*ele(2)+0.29509806732456*ele(4)
- 例如:
模板
使用{{複變運算}}
使用{{計算結果}}
參見
local p = {}
local comp_lib = require("Module:Complex_Number")
local cmath = comp_lib.cmath.init()
function p._isNaN(x)
return (not (x==x)) and (x~=x)
end
p.cdmath={
abs=function(z)
local A, B = p.cdmath.readCayleyDicksonNumberCDpart(z)
local A_len, B_len = p.cdmath.mathlib.abs(A), p.cdmath.mathlib.abs(B)
return math.sqrt( A_len * A_len + B_len * B_len )
end,
conjugate=function(z)
local A, B = p.cdmath.readCayleyDicksonNumberCDpart(z)
return p.cdmath.getCayleyDicksonNumber(p.cdmath.mathlib.conjugate(A), -B)
end,
re=function(z)
local A, B = p.cdmath.readCayleyDicksonNumberCDpart(z)
return p.cdmath.mathlib.re(A)
end,
im=function(z)
local A, B = p.cdmath.readCayleyDicksonNumberCDpart(z)
return p.cdmath.mathlib.im(A)
end,
inverse=function(z)
local A, B = p.cdmath.readCayleyDicksonNumberCDpart(z)
local A_up, B_up = p.cdmath.mathlib.conjugate(A), -B
local A_len, B_len = p.cdmath.mathlib.abs(A), p.cdmath.mathlib.abs(B)
local div_down = ( A_len * A_len + B_len * B_len )
return p.cdmath.getCayleyDicksonNumber(A_up / div_down, B_up / div_down)
end,
sqrt=function(z)
local A, B = p.cdmath.readCayleyDicksonNumberCDpart(z)
local s_zero = p.cdmath.toSnumber("0")
if A == s_zero then
return p.omath.getOctonionNumberQ(p.cdmath.mathlib.sqrt(A), p.cdmath.toSnumber("0"))
end
return p.cdmath.pow(z, 0.5)
end,
asinh=function(z)
local _one = p.cdmath.getCayleyDicksonNumber("1", "0")
local u = p.cdmath.getCayleyDicksonNumber(p.cdmath.readCayleyDicksonNumberCDpart(z))
return p.cdmath.elog( u + p.cdmath.sqrt( u * u + _one ) )
end,
acosh=function(z)
local _one = p.cdmath.getCayleyDicksonNumber("1", "0")
local u = p.cdmath.getCayleyDicksonNumber(p.cdmath.readCayleyDicksonNumberCDpart(z))
return p.cdmath.elog( u + p.cdmath.sqrt( u + _one ) * p.cdmath.sqrt( u - _one ) )
end,
atanh=function(z)
local _one = p.cdmath.getCayleyDicksonNumber("1", "0")
local u = p.cdmath.getCayleyDicksonNumber(p.cdmath.readCayleyDicksonNumberCDpart(z))
return ( p.cdmath.elog( _one + u ) - p.cdmath.elog( _one - u ) ) / 2
end,
acoth=function(z)
local _one = p.cdmath.getCayleyDicksonNumber("1", "0")
local u = p.cdmath.getCayleyDicksonNumber(p.cdmath.readCayleyDicksonNumberCDpart(z))
return ( p.cdmath.elog( _one + p.cdmath.inverse(u) ) - p.cdmath.elog( _one - p.cdmath.inverse(u) ) ) / 2
end,
dot = function (op1, op2)
local nonL1, valL1 = p.cdmath.readCayleyDicksonNumberCDpart(op1)
local nonL2, valL2 = p.cdmath.readCayleyDicksonNumberCDpart(op2)
return p.cdmath.mathlib.dot(nonL1, nonL2) + p.cdmath.mathlib.dot(valL1, valL2)
end,
scalarPart=function(z)
local A, B = p.cdmath.readCayleyDicksonNumberCDpart(z)
return p.cdmath.getCayleyDicksonNumber(p.cdmath.toSnumber(tostring(p.cdmath.mathlib.re(A))), p.cdmath.toSnumber("0"))
end,
vectorPart=function(z)
return p.cdmath.nonRealPart(z)
end,
nonRealPart=function(z)
local A, B = p.cdmath.readCayleyDicksonNumberCDpart(z)
return p.cdmath.getCayleyDicksonNumber(p.cdmath.mathlib.nonRealPart(A), B)
end,
sgn=function(z)
local A, B = p.cdmath.readCayleyDicksonNumberCDpart(z)
local A_len, B_len = p.cdmath.mathlib.abs(A), p.cdmath.mathlib.abs(B)
local length = math.sqrt( A_len * A_len + B_len * B_len )
if length <= 0 then return p.cdmath.getCayleyDicksonNumber(p.cdmath.toSnumber("0"),p.cdmath.toSnumber("0")) end
return z / length
end,
arg=function(z) --TODO: verify
local A, B = p.cdmath.readCayleyDicksonNumberCDpart(z)
local A_len, B_len = p.cdmath.mathlib.abs(A), p.cdmath.mathlib.abs(B)
local length = math.sqrt( A_len * A_len + B_len * B_len )
return math.acos( p.cdmath.mathlib.re(A) / length )
end,
exp=function(z) --Cayley-Dickson construction
local u = p.cdmath.nonRealPart(z)
return ( (p.cdmath.sgn(u) * math.sin(p.cdmath.abs(u))) + math.cos(p.cdmath.abs(u))) * math.exp(p.cdmath.re(z))
end,
elog=function(z) --Cayley-Dickson construction
local u = p.cdmath.nonRealPart(z)
mw.log(p.cdmath.arg(z))
return p.cdmath.sgn(u)*p.cdmath.arg(z)+math.log(p.cdmath.abs(z))
end,
log=function(z,basez)
if basez~=nil then return p.cdmath.elog(basez) * p.cdmath.inverse(p.cdmath.elog(z)) end
return p.cdmath.elog(z)
end,
pow=function(op1,op2)
local _zero = p.cdmath.getCayleyDicksonNumber("0", "0")
local a = p.cdmath.getCayleyDicksonNumber(p.cdmath.readCayleyDicksonNumberCDpart(op1))
local z = p.cdmath.getCayleyDicksonNumber(p.cdmath.readCayleyDicksonNumberCDpart(op2))
a:clean();z:clean();
if a.B == _zero and z.B == _zero then
return p.cdmath.getOctonionNumberQ(p.cdmath.mathlib.pow(a.A, z.A), p.cdmath.toSnumber("0"))
end
return p.cdmath.exp(z * p.cdmath.elog(a)):clean()
end,
readCayleyDicksonNumberCDpart = function(z)
if type(z) == type({}) then --if already be complex number, don't run string find.
if z.numberType == "complex" then
if p.cdmath.elementCount() >= 2 then
return p.cdmath.toSnumber(z), p.cdmath.toSnumber("0")
else
return p.cdmath.toSnumber(tostring(p.cdmath.mathlib.re(z))), p.cdmath.toSnumber(tostring(p.cdmath.mathlib.im(z)))
end
elseif z.numberType == "quaternion" then
if p.cdmath.elementCount() >= 4 then
return p.cdmath.toSnumber(z), p.cdmath.toSnumber("0")
else
error("Can not divide into 2 parts.")
end
elseif z.numberType == "octonion" then
if p.cdmath.elementCount() >= 8 then
return p.cdmath.toSnumber(z), p.cdmath.toSnumber("0")
else
return z.nonL, z.valL
end
elseif z.numberType == tostring(p.cdmath.elementCount()).."-onion" then
return z.A, z.B
else
error("Not support number system.")
end
elseif type(z) == type(0) then
return p.cdmath.toSnumber(tostring(z)), p.cdmath.toSnumber("0")
end
end,
CayleyDicksonNumberMeta = {
__add = function (op1, op2)
local op1_a, op1_b = p.cdmath.readCayleyDicksonNumberCDpart(op1)
local op2_a, op2_b = p.cdmath.readCayleyDicksonNumberCDpart(op2)
return p.cdmath.getCayleyDicksonNumber(op1_a + op2_a, op1_b + op2_b)
end,
__sub = function (op1, op2)
local op1_a, op1_b = p.cdmath.readCayleyDicksonNumberCDpart(op1)
local op2_a, op2_b = p.cdmath.readCayleyDicksonNumberCDpart(op2)
return p.cdmath.getCayleyDicksonNumber(op1_a - op2_a, op1_b - op2_b)
end,
__mul = function (op1, op2)
local _a, _b = p.cdmath.readCayleyDicksonNumberCDpart(op1)
local _c, _d = p.cdmath.readCayleyDicksonNumberCDpart(op2)
local r_nonL = _a*_c - p.cdmath.mathlib.conjugate(_d)*_b
local r_valL = _d*_a + _b*p.cdmath.mathlib.conjugate(_c)
return p.cdmath.getCayleyDicksonNumber(r_nonL, r_valL)
end,
__div = function (op1, op2)
local op_div = p.cdmath.inverse(op2)
local _a, _b = p.cdmath.readCayleyDicksonNumberCDpart(op1)
local _c, _d = p.cdmath.readCayleyDicksonNumberCDpart(op_div)
local r_nonL = _a*_c - p.cdmath.mathlib.conjugate(_d)*_b
local r_valL = _d*_a + _b*p.cdmath.mathlib.conjugate(_c)
return p.cdmath.getCayleyDicksonNumber(r_nonL, r_valL)
end,
__mod = function (op1, op2)
local x = p.cdmath.readComplexNumber(op1)
local y = p.cdmath.readComplexNumber(op2)
return x - y * qmath.floor(x / y)
end,
__unm = function (this)
return p.cdmath.getCayleyDicksonNumber(-this.A, -this.B)
end,
__eq = function (op1, op2)
return op1.A == op2.A and op1.B == op2.B
end,
},
mathlib=cmath,
toSnumber=cmath.constructor,
elementCount = function() return #(p.cdmath.elements or {}) end,
getCayleyDicksonNumber = function(a,b)
CayleyDicksonNumber = {}
setmetatable(CayleyDicksonNumber,p.cdmath.CayleyDicksonNumberMeta)
function CayleyDicksonNumber:update()
xpcall(function()
self.A:update()
self.B:update()
self.argument = 0
self.length = math.sqrt( self.A.length * self.A.length + self.B.length * self.B.length )
end,function()end)
end
function CayleyDicksonNumber:clean()
xpcall(function()
self.A:clean()
self.B:clean()
end,function()end)
return self
end
CayleyDicksonNumber.A = p.cdmath.toSnumber(a)
CayleyDicksonNumber.B = p.cdmath.toSnumber(b)
CayleyDicksonNumber.numberType = tostring(p.cdmath.elementCount()).."-onion"
return CayleyDicksonNumber
end,
init = function(math_lib)
if type(math_lib)==type({})then
p.cdmath.mathlib = math_lib.init()
p.cdmath.toSnumber = p.cdmath.mathlib.constructor
end
--p.omath.pi = p.cdmath.mathlib.pi
--p.omath["π"] = p.omath.getOctonionNumber(math.pi, 0, 0, 0, 0, 0, 0, 0)
--p.omath["°"] = p.omath.getOctonionNumber(math.pi/180, 0, 0, 0, 0, 0, 0, 0)
--p.omath.e = p.omath.getOctonionNumber(math.exp(1), 0, 0, 0, 0, 0, 0, 0)
--p.omath.nan = p.omath.getOctonionNumber(tonumber("nan"), tonumber("nan"), tonumber("nan"), tonumber("nan"), tonumber("nan"), tonumber("nan"), tonumber("nan"), tonumber("nan"))
--p.omath.zero = p.omath.getOctonionNumber(0, 0, 0, 0, 0, 0, 0, 0)
--p.omath.one = p.omath.getOctonionNumber(1, 0, 0, 0, 0, 0, 0, 0)
--p.omath[-1] = p.omath.getOctonionNumber(-1, 0, 0, 0, 0, 0, 0, 0)
-- p.omath[0],p.omath[1] = p.omath.zero,p.omath.one
p.cdmath.numberType = comp_lib._numberType
p.cdmath.elements = {}
for i=1,#(p.cdmath.mathlib.elements or{}) do p.cdmath.elements[#(p.cdmath.elements)+1] = p.cdmath.getCayleyDicksonNumber(p.cdmath.mathlib.elements[i],"0")end
for i=1,#(p.cdmath.mathlib.elements or{}) do p.cdmath.elements[#(p.cdmath.elements)+1] = p.cdmath.getCayleyDicksonNumber("0",p.cdmath.mathlib.elements[i])end
--p.cdmath.constructor = p.omath.toCDNumber
return p.cdmath
end
}
return p