模組: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)
- 例如:
模板
[编辑]使用{{複變運算}}
- 語法:
{{複變運算|運算式|number class=Module:Complex Number/CayleyDickson.cdmath=要套用凯莱-迪克森结构函數庫模組路徑和名稱}}
- 例如:
{{複變運算|(2+3*ele(2)+ele(4))*(4+5*ele(3)+ele(4))|number class=Module:Complex Number/CayleyDickson.cdmath=Module:Complex Number/Octonion.omath}}
- →「7+15*ele(1)+12*ele(2)+10*ele(3)+6*ele(4)+3*ele(6)-5*ele(7)」
- 例如:
{{複變運算|sqrt(2+3*ele(2)+ele(4))|number class=Module:Complex Number/CayleyDickson.cdmath=Module:Complex Number/Octonion.omath}}
- →「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
--無法套娃的[[凯莱-迪克森结构]]
function p.get_cdmath(_data, is_bicomplex)
local q = {}
q.cdmath={
_scopeflag=_data,
_bicomplex=is_bicomplex,
abs=function(z)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(z)
local A_len, B_len = q.cdmath.mathlib.abs(A), q.cdmath.mathlib.abs(B)
return math.sqrt( A_len * A_len + B_len * B_len )
end,
floor=function(z)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(z)
return q.cdmath.checkMathform(q.cdmath.mathlib.floor(A), q.cdmath.mathlib.floor(B), z)
end,
ceil=function(z)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(z)
return q.cdmath.checkMathform(q.cdmath.mathlib.ceil(A), q.cdmath.mathlib.ceil(B), z)
end,
div=function(left,z)
return left*q.cdmath.inverse(z)
end,
round=function(op1,op2,op3)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(op1)
local o2, _2 = q.cdmath.readCayleyDicksonNumberCDpart(op2)
local o3, _3 = q.cdmath.readCayleyDicksonNumberCDpart(op3)
return q.cdmath.checkMathform(q.cdmath.mathlib.round(A,o2,o3), q.cdmath.mathlib.round(B,o2,o3), op1,op2,op3)
end,
re=function(z)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(z)
return q.cdmath.mathlib.re(A)
end,
im=function(z)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(z)
return q.cdmath.mathlib.im(A)
end,
conjugate=function(z)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(z)
if q.cdmath._bicomplex then return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(A, -B), z) end
return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(q.cdmath.mathlib.conjugate(A), -B), z)
end,
inverse=function(z)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(z)
local A_up, B_up = q.cdmath.mathlib.conjugate(A), -B
if q.cdmath._bicomplex then A_up = A end
local A_len, B_len = q.cdmath.mathlib.abs(A), q.cdmath.mathlib.abs(B)
local div_down = ( A_len * A_len + B_len * B_len )
return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(A_up / div_down, B_up / div_down), z)
end,
tovector=function(z)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(z)
local _A, _B = q.cdmath.toSnumber(tostring(A)), q.cdmath.toSnumber(tostring(B))
return {unpack(q.cdmath.mathlib.tovector(A or 0) or {}), unpack(q.cdmath.mathlib.tovector(B or 0) or {})}
end,
trunc=function(op1,op2)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(op1)
local o2, _2 = q.cdmath.readCayleyDicksonNumberCDpart(op2)
return q.cdmath.checkMathform(q.cdmath.mathlib.trunc(A,o2), q.cdmath.mathlib.trunc(B,o2), op1,op2)
end,
sqrt=function(z)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(z)
local s_zero = q.cdmath.toSnumber("0")
if A == s_zero then
return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(q.cdmath.mathlib.sqrt(A), q.cdmath.toSnumber("0")), z)
end
return q.cdmath.checkMathform(q.cdmath.pow(z, 0.5), z)
end,
root=function(_z,_n,_num)
local z = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(_z))
local n = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(_n or 2))
local num = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(_num or 1))
local s_i = q.cdmath.toSnumber("i")
if num == q.cdmath.one or num == q.cdmath.zero or num == nil or s_i == nil then
return q.cdmath.pow(z, q.cdmath.inverse(n))
end
local sgn_data = q.cdmath.sgn(q.cdmath.nonRealPart(z))
if q.cdmath.abs(q.cdmath.nonRealPart(z))<1e-14 then sgn_data=q.cdmath.getCayleyDicksonNumber(s_i, q.cdmath.toSnumber("0")) end
local result = q.cdmath.pow(q.cdmath.abs(z), q.cdmath.inverse(n)) * q.cdmath.exp(sgn_data * (q.cdmath.arg(z) + (num-1)*(2*math.pi) ) * q.cdmath.inverse(n))
result:clean()
return result
end,
sin=function(z)
local u = q.cdmath.nonRealPart(z)
return ( math.cosh(q.cdmath.abs(u)) * math.sin(q.cdmath.re(z)) ) + ( q.cdmath.sgn(u) * math.sinh(q.cdmath.abs(u)) * math.cos(q.cdmath.re(z)) )
end,
cos=function(z)
local u = q.cdmath.nonRealPart(z)
return ( math.cosh(q.cdmath.abs(u)) * math.cos(q.cdmath.re(z)) ) - ( q.cdmath.sgn(u) * math.sinh(q.cdmath.abs(u)) * math.sin(q.cdmath.re(z)) )
end,
tan=function(z)
local theta = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(z))
return q.cdmath.sin(theta) * q.cdmath.inverse( q.cdmath.cos(theta) )
end,
cot=function(z)
local theta = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(z))
return q.cdmath.cos(theta) * q.cdmath.inverse( q.cdmath.sin(theta) )
end,
asin=function(z)
local v = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(z))
local u = q.cdmath.nonRealPart(z)
local sgnu = q.cdmath.sgn(u);
if q.cdmath.abs(sgnu) < 1e-12 then sgnu = sgnu + q.cdmath.ele(1) end
return -sgnu * q.cdmath.asinh( v * sgnu )
end,
acos=function(z)
local v = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(z))
local u = q.cdmath.nonRealPart(z)
local sgnu = q.cdmath.sgn(u);
if q.cdmath.abs(sgnu) < 1e-12 then sgnu = sgnu + q.cdmath.ele(1) end
return -sgnu * q.cdmath.acosh( v )
end,
atan=function(z)
local v = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(z))
local u = q.cdmath.nonRealPart(z)
local sgnu = q.cdmath.sgn(u);
if q.cdmath.abs(sgnu) < 1e-12 then sgnu = sgnu + q.cdmath.ele(1) end
return -sgnu * q.cdmath.atanh( v * sgnu )
end,
acot=function(z)
local v = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(z))
local u = q.cdmath.nonRealPart(z)
local sgnu = q.cdmath.sgn(u);
if q.cdmath.abs(sgnu) < 1e-12 then sgnu = sgnu + q.cdmath.ele(1) end
return sgnu * q.cdmath.acoth( v * sgnu )
end,
sinh=function(z)
local u = q.cdmath.nonRealPart(z)
return ( math.cos(q.cdmath.abs(u)) * math.sinh(q.cdmath.re(z)) ) + ( q.cdmath.sgn(u) * math.sin(q.cdmath.abs(u)) * math.cosh(q.cdmath.re(z)) )
end,
cosh=function(z)
local u = q.cdmath.nonRealPart(z)
return ( math.cos(q.cdmath.abs(u)) * math.cosh(q.cdmath.re(z)) ) + ( q.cdmath.sgn(u) * math.sin(q.cdmath.abs(u)) * math.sinh(q.cdmath.re(z)) )
end,
tanh=function(z)
local theta = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(z))
return q.cdmath.sinh(theta) * q.cdmath.inverse( q.cdmath.cosh(theta) )
end,
coth=function(z)
local theta = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(z))
return q.cdmath.cosh(theta) * q.cdmath.inverse( q.cdmath.sinh(theta) )
end,
asinh=function(z)
local _one = q.cdmath.getCayleyDicksonNumber("1", "0")
local u = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(z))
return q.cdmath.checkMathform(q.cdmath.elog( u + q.cdmath.sqrt( u * u + _one ) ), z)
end,
acosh=function(z)
local _one = q.cdmath.getCayleyDicksonNumber("1", "0")
local u = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(z))
return q.cdmath.checkMathform(q.cdmath.elog( u + q.cdmath.sqrt( u + _one ) * q.cdmath.sqrt( u - _one ) ),z)
end,
atanh=function(z)
local _one = q.cdmath.getCayleyDicksonNumber("1", "0")
local u = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(z))
return q.cdmath.checkMathform(( q.cdmath.elog( _one + u ) - q.cdmath.elog( _one - u ) ) / 2, z)
end,
acoth=function(z)
local _one = q.cdmath.getCayleyDicksonNumber("1", "0")
local u = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(z))
return q.cdmath.checkMathform(( q.cdmath.elog( _one + q.cdmath.inverse(u) ) - q.cdmath.elog( _one - q.cdmath.inverse(u) ) ) / 2, z)
end,
dot = function (op1, op2)
local nonL1, valL1 = q.cdmath.readCayleyDicksonNumberCDpart(op1)
local nonL2, valL2 = q.cdmath.readCayleyDicksonNumberCDpart(op2)
return q.cdmath.mathlib.dot(nonL1, nonL2) + q.cdmath.mathlib.dot(valL1, valL2)
end,
scalarPart=function(z)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(z)
return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber(tostring(q.cdmath.mathlib.re(A))), q.cdmath.toSnumber("0")), z)
end,
vectorPart=function(z)
return q.cdmath.nonRealPart(z)
end,
nonRealPart=function(z)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(z)
return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(q.cdmath.mathlib.nonRealPart(A), B), z)
end,
sgn=function(z)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(z)
local A_len, B_len = q.cdmath.mathlib.abs(A), q.cdmath.mathlib.abs(B)
local length = math.sqrt( A_len * A_len + B_len * B_len )
if length <= 0 then return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber("0"),q.cdmath.toSnumber("0")), z) end
return q.cdmath.checkMathform(z / length, z)
end,
arg=function(z) --TODO: verify
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(z)
local A_len, B_len = q.cdmath.mathlib.abs(A), q.cdmath.mathlib.abs(B)
local length = math.sqrt( A_len * A_len + B_len * B_len )
return math.acos( q.cdmath.mathlib.re(A) / length )
end,
cis=function(z)
local u = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(z))
return q.cdmath.cos(u) + q.cdmath.ele(1) * q.cdmath.sin(u)
end,
exp=function(z) --Cayley-Dickson construction
local u = q.cdmath.nonRealPart(z)
return q.cdmath.checkMathform(( (q.cdmath.sgn(u) * math.sin(q.cdmath.abs(u))) + math.cos(q.cdmath.abs(u))) * math.exp(q.cdmath.re(z)), z)
end,
elog=function(z) --Cayley-Dickson construction
local u = q.cdmath.nonRealPart(z)
return q.cdmath.checkMathform(q.cdmath.sgn(u)*q.cdmath.arg(z)+math.log(q.cdmath.abs(z)), z)
end,
log=function(z,basez)
if basez~=nil then return q.cdmath.checkMathform(q.cdmath.elog(basez) * q.cdmath.inverse(q.cdmath.elog(z)), z) end
return q.cdmath.elog(z)
end,
pow=function(op1,op2)
local _zero = q.cdmath.getCayleyDicksonNumber("0", "0")
local a = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(op1))
local z = q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(op2))
a:clean();z:clean();
if a.B == _zero and z.B == _zero then
return q.cdmath.checkMathform(q.cdmath.getOctonionNumberQ(q.cdmath.mathlib.pow(a.A, z.A), q.cdmath.toSnumber("0")), op1, op2)
end
return q.cdmath.checkMathform(q.cdmath.exp(z * q.cdmath.elog(a)):clean(), op1, op2)
end,
ele=function(id)
local _zero = q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber("0"), q.cdmath.toSnumber("0"))
local eles = (q.cdmath.elements or {})
local id_msg = tonumber(tostring(id)) or 0
return q.cdmath.checkMathform(eles[id_msg+1]or _zero, id)
end,
readCayleyDicksonNumberCDpart = function(z)
if type(z) == type(function()end) then return end
if type(z) == type(true) then return q.cdmath.toSnumber(z and '1' or '0'), q.cdmath.toSnumber("0") end
local dim = tonumber(({tostring((type(z)==type({}))and z.numberType or ''):gsub("%-onion","")})[1])
if type(z) == type({}) then --if already be complex number, don't run string find.
if z.numberType == "complex" or z.numberType == "dualnumber" then
if q.cdmath.elementCount >= 2 then
return q.cdmath.toSnumber(tostring(z)), q.cdmath.toSnumber("0")
else
return q.cdmath.toSnumber(tostring(q.cdmath.mathlib.re(z))), q.cdmath.toSnumber(tostring(q.cdmath.mathlib.im(z)))
end
elseif z.numberType == "quaternion" then
if q.cdmath.elementCount >= 4 then
return q.cdmath.toSnumber(tostring(z)), q.cdmath.toSnumber("0")
elseif q.cdmath.elementCount >= 2 then
return q.cdmath.toSnumber(tostring(z.real or 0)..'+'..tostring(z.imag or 0)..'i'), q.cdmath.toSnumber(tostring(z.jpart or 0)..'+'..tostring(z.kpart or 0)..'i')
else
error("Can not divide into 2 parts.")
end
elseif z.numberType == "dualcomplex" then
if q.cdmath.elementCount >= 4 then
return q.cdmath.toSnumber(tostring(z)), q.cdmath.toSnumber("0")
elseif q.cdmath.elementCount >= 2 then
return q.cdmath.toSnumber(tostring((z.non_epsilon or {}).real or 0)..'+'..tostring((z.non_epsilon or {}).epsilon or 0)..'ε'), q.cdmath.toSnumber(tostring((z.epsilon or {}).real or 0)..'+'..tostring((z.epsilon or {}).epsilon or 0)..'ε')
else
error("Can not divide into 2 parts.")
end
elseif z.numberType == "octonion" then
if q.cdmath.elementCount >= 8 then
return q.cdmath.toSnumber(tostring(z)), q.cdmath.toSnumber("0")
elseif q.cdmath.elementCount >= 4 then
return z.nonL, z.valL
elseif q.cdmath.elementCount >= 2 then
return q.cdmath.toSnumber(tostring(z.nonL.real or 0)..'+'..tostring(z.nonL.imag or 0)..'i'), q.cdmath.toSnumber(tostring(z.nonL.jpart or 0)..'+'..tostring(z.nonL.kpart or 0)..'i')
else
error("Can not divide into 2 parts.")
end
elseif dim~=nil then
if q.cdmath.elementCount > dim then
return q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber(tostring(str)), q.cdmath.toSnumber("0"))
elseif q.cdmath.elementCount == dim then
return z.A, z.B
elseif q.cdmath.elementCount < dim then
return unpack(q.cdmath.mathlib.halfNumberParts(z))
else
error(q.cdmath.elementCount .. " " .. tostring(dim) .. " " .. tostring((type(z)==type({}))and z.numberType or '') .." Not support number system.")
end
else
--return q.cdmath.toCayleyDicksonNumber(tostring(z))
error(q.cdmath.elementCount .. " " .. tostring(dim) .. " " .. tostring((type(z)==type({}))and z.numberType or '') .." Not support number system.")
end
elseif type(z) == type(0) then
return q.cdmath.toSnumber(tostring(z)), q.cdmath.toSnumber("0")
elseif type(z) == type(true) then
return q.cdmath.toSnumber(z and '1' or '0'), q.cdmath.toSnumber("0")
end
end,
random=function(op1, op2)
if type(op1)==type(nil) and type(op2)==type(nil) then return q.cdmath.getCayleyDicksonNumber(q.cdmath.mathlib.random(), q.cdmath.toSnumber("0")) end
local op1_a, op1_b = q.cdmath.readCayleyDicksonNumberCDpart(op1)
if type(op2)==type(nil) then return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(q.cdmath.mathlib.random(op1_a), q.cdmath.mathlib.random(op1_b)), op1) end
local op2_a, op2_b = q.cdmath.readCayleyDicksonNumberCDpart(op2)
return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(q.cdmath.mathlib.random(op1_a, op2_a), q.cdmath.mathlib.random(op1_b, op2_b)), op1, op2)
end,
isReal=function(z) return q.cdmath.abs(q.cdmath.nonRealPart(z)) < 1e-14 end,
CayleyDicksonNumberMeta = {
__add = function (op1, op2)
local op1_a, op1_b = q.cdmath.readCayleyDicksonNumberCDpart(op1)
local op2_a, op2_b = q.cdmath.readCayleyDicksonNumberCDpart(op2)
return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(op1_a + op2_a, op1_b + op2_b), op1, op2)
end,
__sub = function (op1, op2)
local op1_a, op1_b = q.cdmath.readCayleyDicksonNumberCDpart(op1)
local op2_a, op2_b = q.cdmath.readCayleyDicksonNumberCDpart(op2)
return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(op1_a - op2_a, op1_b - op2_b), op1, op2)
end,
__mul = function (op1, op2)
local _a, _b = q.cdmath.readCayleyDicksonNumberCDpart(op1)
local _c, _d = q.cdmath.readCayleyDicksonNumberCDpart(op2)
local r_nonL = _a*_c - q.cdmath.mathlib.conjugate(_d)*_b
local r_valL = _d*_a + _b*q.cdmath.mathlib.conjugate(_c)
if q.cdmath._bicomplex then
r_nonL = _a * _c - _b * _d
r_valL = _a * _d + _b * _c
end
return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(r_nonL, r_valL), op1, op2)
end,
__div = function (op1, op2)
local op_div = q.cdmath.inverse(op2)
local _a, _b = q.cdmath.readCayleyDicksonNumberCDpart(op1)
local _c, _d = q.cdmath.readCayleyDicksonNumberCDpart(op_div)
local r_nonL = _a*_c - q.cdmath.mathlib.conjugate(_d)*_b
local r_valL = _d*_a + _b*q.cdmath.mathlib.conjugate(_c)
if q.cdmath._bicomplex then
r_nonL = _a * _c - _b * _d
r_valL = _a * _d + _b * _c
end
return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(r_nonL, r_valL), op1, op2)
end,
__mod = function (op1, op2)
local x = q.cdmath.readComplexNumber(op1)
local y = q.cdmath.readComplexNumber(op2)
return q.cdmath.checkMathform(x - y * qmath.floor(x / y), op1, op2)
end,
__unm = function (this)
return q.cdmath.checkMathform(q.cdmath.getCayleyDicksonNumber(-this.A, -this.B), this)
end,
__eq = function (op1, op2)
return op1.A == op2.A and op1.B == op2.B
end,
__tostring = function (this)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(this)
local strA = tostring(A)
local strB = tostring(B)
if strA == "nan" or strA == "-nan" then return strA end
if strB == "nan" or strB == "-nan" then return strB end
if strA == "0" and strB == "0" then return "0" end
local body = ''
local eles = (q.cdmath.elements or {})
for i=1,#eles do
--q.cdmath.readCayleyDicksonNumberCDpart(eles[i])
local val = tonumber(q.cdmath.dot(this,eles[i]))or 0
if math.abs(val)>1e-14 then
local val_str = ''
local is_one = (math.abs(math.abs(val)-1)<1e-14)
local has_num = false
if val>0 then
if body~=''then val_str = val_str ..'+'end
val_str = val_str..(is_one and''or tostring(val))
has_num = true
elseif val<0 then
val_str = val_str..(is_one and'-'or tostring(val))
has_num = true
end
if has_num then
if i==1 then
body = body..val_str..(is_one and'1'or'')
else
if this.mathform then
body = body..val_str..' e_{'..tostring(i-1)..'}'
elseif this.htmlform then
body = body..val_str..(is_one and''or' ')..' e<sub>'..tostring(i-1)..'</sub>'
else
body = body..val_str..(is_one and''or'*')..'ele('..tostring(i-1)..')'
end
end
end
end
end
if body=='' then body = 0 end
--return mw.dumpObject(this)
return body
end,
},
checkMathform=function(result,...)
local parms = {...}
local flag = false
for i=1,#parms do flag = flag or ((type(parms[i])==type({}))and parms[i].mathform or false)end
if type(result)==type({})then result.mathform = result.mathform or flag end
return result
end,
mathlib=cmath,
toSnumber=cmath.constructor,
mathform = function(this)this.mathform=true return this end,
htmlform = function(this)this.htmlform=true return this end,
toCayleyDicksonNumber = function(str)
--load if already a number
local dim = tonumber(({tostring((type(str)==type({}))and str.numberType or ''):gsub("%-onion","")})[1])
if type(str) == type({}) then --if already be complex number, don't run string find.
if str.numberType == "complex" or str.numberType == "dualnumber" then
if q.cdmath.elementCount >= 2 then
return q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber(tostring(str)), q.cdmath.toSnumber("0"))
else
return q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber(tostring(q.cdmath.mathlib.re(str))), q.cdmath.toSnumber(tostring(q.cdmath.mathlib.im(str))))
end
elseif str.numberType == "quaternion" then
if q.cdmath.elementCount >= 4 then
return q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber(tostring(str)), q.cdmath.toSnumber("0"))
elseif q.cdmath.elementCount >= 2 then
return q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber(tostring(str.real or 0)..'+'..tostring(str.imag or 0)..'i'), q.cdmath.toSnumber(tostring(str.jpart or 0)..'+'..tostring(str.kpart or 0)..'i'))
end
elseif str.numberType == "dualcomplex" then
if q.cdmath.elementCount >= 4 then
return q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber(tostring(str)), q.cdmath.toSnumber("0"))
elseif q.cdmath.elementCount >= 2 then
return q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber(tostring((str.non_epsilon or {}).real or 0)..'+'..tostring((str.non_epsilon or {}).epsilon or 0)..'ε'), q.cdmath.toSnumber(tostring((str.epsilon or {}).real or 0)..'+'..tostring((str.epsilon or {}).epsilon or 0)..'ε'))
end
elseif str.numberType == "octonion" then
if q.cdmath.elementCount >= 8 then
return q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber(tostring(str)), q.cdmath.toSnumber("0"))
elseif q.cdmath.elementCount >= 4 then
return q.cdmath.getCayleyDicksonNumber(str.nonL, str.valL)
elseif q.cdmath.elementCount >= 2 then
return q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber(tostring(str.nonL.real or 0)..'+'..tostring(str.nonL.imag or 0)..'i'), q.cdmath.toSnumber(tostring(str.nonL.jpart or 0)..'+'..tostring(str.nonL.kpart or 0)..'i'))
end
elseif dim~=nil then
if q.cdmath.elementCount > dim then
return q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber(tostring(str)), q.cdmath.toSnumber("0"))
elseif q.cdmath.elementCount == dim then
return q.cdmath.getCayleyDicksonNumber(str.A, str.B)
end
else
end
elseif type(str) == type(0) then
return q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber(tostring(str)), q.cdmath.toSnumber("0"))
elseif type(str) == type(true) then
return q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber(str and '1' or '0'), q.cdmath.toSnumber("0"))
end
--try to parse into substring
local tmp_num = q.cdmath.toSnumber(tostring(str))
if tmp_num ~= nil then
return q.cdmath.getCayleyDicksonNumber(tmp_num, q.cdmath.toSnumber("0"))
end
--parse full string
local chk_str = tostring(str)
local got_list = {}
local ismath = false
if mw.ustring.find(chk_str,"%(")then
got_list = mw.text.split(mw.ustring.gsub(chk_str,"([%+%-])",",%1"),",")
for i=1,#got_list do
got_list[i] = mw.ustring.gsub(got_list[i],"ele","*"):gsub("%*+","*"):gsub("[%(%)]","")
end
elseif mw.ustring.find(chk_str,"%{")then
got_list = mw.text.split(mw.ustring.gsub(chk_str,"([%+%-])",",%1"),",")
for i=1,#got_list do
got_list[i] = mw.ustring.gsub(got_list[i],"^e"," e"):gsub("e","*"):gsub(" +","*"):gsub("%*+","*"):gsub("[_%{%}]","")
end
ismath = true
end
if #got_list > 0 then
local eles = (q.cdmath.elements or {})
local result_number = q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber("0"), q.cdmath.toSnumber("0"))
local _zero = q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber("0"), q.cdmath.toSnumber("0"))
local _one = q.cdmath.getCayleyDicksonNumber(q.cdmath.toSnumber("1"), q.cdmath.toSnumber("0"))
for i=1,#got_list do
if mw.text.trim(got_list[i])~='' then
local check_ele = mw.text.split(got_list[i],"%*+")
local real_coeff = tonumber(check_ele[1])or (tonumber( (tostring(check_ele[1])~='')and(tostring(check_ele[1])..'1')or check_ele[1] ) or 1)
local real_eleid = tonumber(check_ele[2])or 0
local this_ele = eles[real_eleid+1]or _zero
result_number = result_number + this_ele*real_coeff
end
end
result_number.mathform = ismath
return result_number
end
return q.cdmath.getCayleyDicksonNumber(q.cdmath.readCayleyDicksonNumberCDpart(str))
end,
getCayleyDicksonNumber = function(a,b)
local CayleyDicksonNumber = {}
setmetatable(CayleyDicksonNumber,q.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 = q.cdmath.toSnumber(a)
CayleyDicksonNumber.B = q.cdmath.toSnumber(b)
if not CayleyDicksonNumber.A then CayleyDicksonNumber.A = q.cdmath.toSnumber("0") end
if not CayleyDicksonNumber.B then CayleyDicksonNumber.B = q.cdmath.toSnumber("0") end
CayleyDicksonNumber.numberType = q.cdmath.globalNumberType
return CayleyDicksonNumber
end,
halfNumberParts = function(num)
local A, B = q.cdmath.readCayleyDicksonNumberCDpart(num)
return {A, B}
end,
init = function(math_lib)
return q.cdmath._init(math_lib)
end,
_init = function(math_lib)
if type(math_lib)==type({})then
q.cdmath.mathlib = math_lib.init()
q.cdmath.toSnumber = q.cdmath.mathlib.constructor
end
local _zero = q.cdmath.toSnumber("0")
q.cdmath.elements = {}
local unit_list = q.cdmath.mathlib.elements or{}
q.cdmath.elementCount = (#unit_list)*2
q.cdmath.globalNumberType = tostring(q.cdmath.elementCount).."-onion"
for i=1,q.cdmath.elementCount do q.cdmath.elements[i] = {} end
for i=1,#unit_list do
q.cdmath.elements[i] = q.cdmath.getCayleyDicksonNumber(unit_list[i], "0")
end
for i=1,#unit_list do
q.cdmath.elements[i+#unit_list] = q.cdmath.getCayleyDicksonNumber("0", unit_list[i])
end
q.cdmath.pi = q.cdmath.getCayleyDicksonNumber(q.cdmath.mathlib.pi, _zero)
q.cdmath["π"] = q.cdmath.getCayleyDicksonNumber(q.cdmath.mathlib.pi, _zero)
q.cdmath["°"] = q.cdmath.getCayleyDicksonNumber(q.cdmath.mathlib.pi/180, _zero)
q.cdmath.e = q.cdmath.getCayleyDicksonNumber(math.exp(1), _zero)
q.cdmath.nan = q.cdmath.getCayleyDicksonNumber(tonumber("nan"), tonumber("nan"))
q.cdmath.zero = q.cdmath.getCayleyDicksonNumber("0", _zero)
q.cdmath.one = q.cdmath.getCayleyDicksonNumber("1", _zero)
q.cdmath[-1] = q.cdmath.getCayleyDicksonNumber("-1", _zero)
q.cdmath[0],q.cdmath[1] = q.cdmath.zero,q.cdmath.one
q.cdmath.numberType = comp_lib._numberType
q.cdmath.constructor = q.cdmath.toCayleyDicksonNumber
return q.cdmath
end
}
return q
end
p.cdmath = p.get_cdmath(0, false).cdmath
p.bcdmath = p.get_cdmath(0, true).cdmath
function p.checkModuleClass(cls)
local class = ((type(cls)==type({}))and( ((cls.args or {})[1]) or cls[1] or '')or( (type(cls)==type("string")) and cls or ''))or''
if mw.ustring.sub(class,1,7):upper()=="MODULE:" then
local data = mw.ustring.sub(class, 8, -1)
local func = mw.ustring.find(data,"%.")
local modu = mw.ustring.sub(data, 1, func -1)
func = mw.ustring.sub(data, func + 1, -1)
return mw.text.trim(modu), mw.text.trim(func)
end
return ''
end
--不能套娃
p.cdmathOctonion={
init = function()
local omath=require("Module:Complex_Number/Octonion").omath.init()
p.cdmathOctonion=mw.clone(p.get_cdmath(1).cdmath).init(omath)
return p.cdmathOctonion._init(omath)
end
}
p.cdmathSedenion={
init = function()
local sdmath=p.sdmath.init()
p.cdmathSedenion=mw.clone(p.get_cdmath(1).cdmath).init(sdmath)
return p.cdmathSedenion._init(sdmath)
end
}
p.cdmathQuaternion={
init = function()
local qmath=comp_lib.qmath.init()
p.cdmathQuaternion=mw.clone(p.get_cdmath(1).cdmath).init(qmath)
return p.cdmathQuaternion._init(qmath)
end
}
p.sdmath={
abs=function(z)
local A, B = p.sdmath.readSedenionNumberCDpart(z)
local A_len, B_len = p.sdmath.mathlib.abs(A), p.sdmath.mathlib.abs(B)
return math.sqrt( A_len * A_len + B_len * B_len )
end,
floor=function(z)
local A, B = p.sdmath.readSedenionNumberCDpart(z)
return p.sdmath.checkMathform(p.sdmath.mathlib.floor(A), p.sdmath.mathlib.floor(B), z)
end,
ceil=function(z)
local A, B = p.sdmath.readSedenionNumberCDpart(z)
return p.sdmath.checkMathform(p.sdmath.mathlib.ceil(A), p.sdmath.mathlib.ceil(B), z)
end,
div=function(left,z)
return left*p.sdmath.inverse(z)
end,
round=function(op1,op2,op3)
local A, B = p.sdmath.readSedenionNumberCDpart(op1)
local o2, _2 = p.sdmath.readSedenionNumberCDpart(op2)
local o3, _3 = p.sdmath.readSedenionNumberCDpart(op3)
return p.sdmath.checkMathform(p.sdmath.mathlib.round(A,o2,o3), p.sdmath.mathlib.round(B,o2,o3), op1,op2,op3)
end,
re=function(z)
local A, B = p.sdmath.readSedenionNumberCDpart(z)
return p.sdmath.mathlib.re(A)
end,
im=function(z)
local A, B = p.sdmath.readSedenionNumberCDpart(z)
return p.sdmath.mathlib.im(A)
end,
conjugate=function(z)
local A, B = p.sdmath.readSedenionNumberCDpart(z)
return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(p.sdmath.mathlib.conjugate(A), -B), z)
end,
inverse=function(z)
local A, B = p.sdmath.readSedenionNumberCDpart(z)
local A_up, B_up = p.sdmath.mathlib.conjugate(A), -B
local A_len, B_len = p.sdmath.mathlib.abs(A), p.sdmath.mathlib.abs(B)
local div_down = ( A_len * A_len + B_len * B_len )
return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(A_up / div_down, B_up / div_down), z)
end,
tovector=function(z)
local A, B = p.sdmath.readSedenionNumberCDpart(z)
local _A, _B = p.sdmath.toSubNumber(tostring(A)), p.sdmath.toSubNumber(tostring(B))
return {unpack(p.sdmath.mathlib.tovector(A or 0) or {}), unpack(p.sdmath.mathlib.tovector(B or 0) or {})}
end,
trunc=function(op1,op2)
local A, B = p.sdmath.readSedenionNumberCDpart(op1)
local o2, _2 = p.sdmath.readSedenionNumberCDpart(op2)
return p.sdmath.checkMathform(p.sdmath.mathlib.trunc(A,o2), p.sdmath.mathlib.trunc(B,o2), op1,op2)
end,
sqrt=function(z)
local A, B = p.sdmath.readSedenionNumberCDpart(z)
local s_zero = p.sdmath.toSubNumber("0")
if A == s_zero then
return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(p.sdmath.mathlib.sqrt(A), p.sdmath.toSubNumber("0")), z)
end
return p.sdmath.checkMathform(p.sdmath.pow(z, 0.5), z)
end,
root=function(_z,_n,_num)
local z = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(_z))
local n = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(_n or p.sdmath.toSubNumber("2")))
local num = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(_num or p.sdmath.toSubNumber("1")))
local s_i = p.sdmath.toSubNumber("i")
if num == p.sdmath.one or num == p.sdmath.zero or num == nil or s_i == nil then
return p.sdmath.pow(z, p.sdmath.inverse(n))
end
local sgn_data = p.sdmath.sgn(p.sdmath.nonRealPart(z))
if p.sdmath.abs(p.sdmath.nonRealPart(z))<1e-14 then sgn_data=p.sdmath.getSedenionNumber(s_i, p.sdmath.toSubNumber("0")) end
local ex = p.sdmath.pow(p.sdmath.getSedenionNumber(p.sdmath.toSubNumber(p.sdmath.abs(z)), p.sdmath.toSubNumber("0")), p.sdmath.inverse(n))
local cr = sgn_data * (p.sdmath.getSedenionNumber(p.sdmath.toSubNumber(p.sdmath.arg(z)), p.sdmath.toSubNumber("0"))+
(num-p.sdmath.getSedenionNumber(p.sdmath.toSubNumber("1"), p.sdmath.toSubNumber("0")))*
p.sdmath.getSedenionNumber(p.sdmath.toSubNumber(2*math.pi), p.sdmath.toSubNumber("0")) ) * p.sdmath.inverse(n)
local result = ex * p.sdmath.pow(cr)
result:clean()
return result
end,
sin=function(z)
local u = p.sdmath.nonRealPart(z)
return ( math.cosh(p.sdmath.abs(u)) * math.sin(p.sdmath.re(z)) ) + ( p.sdmath.sgn(u) * math.sinh(p.sdmath.abs(u)) * math.cos(p.sdmath.re(z)) )
end,
cos=function(z)
local u = p.sdmath.nonRealPart(z)
return ( math.cosh(p.sdmath.abs(u)) * math.cos(p.sdmath.re(z)) ) - ( p.sdmath.sgn(u) * math.sinh(p.sdmath.abs(u)) * math.sin(p.sdmath.re(z)) )
end,
tan=function(z)
local theta = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(z))
return p.sdmath.sin(theta) * p.sdmath.inverse( p.sdmath.cos(theta) )
end,
cot=function(z)
local theta = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(z))
return p.sdmath.cos(theta) * p.sdmath.inverse( p.sdmath.sin(theta) )
end,
asin=function(z)
local v = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(z))
local u = p.sdmath.nonRealPart(z)
local sgnu = p.sdmath.sgn(u);
if p.sdmath.abs(sgnu) < 1e-12 then sgnu = sgnu + p.sdmath.ele(1) end
return -sgnu * p.sdmath.asinh( v * sgnu )
end,
acos=function(z)
local v = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(z))
local u = p.sdmath.nonRealPart(z)
local sgnu = p.sdmath.sgn(u);
if p.sdmath.abs(sgnu) < 1e-12 then sgnu = sgnu + p.sdmath.ele(1) end
return -sgnu * p.sdmath.acosh( v )
end,
atan=function(z)
local v = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(z))
local u = p.sdmath.nonRealPart(z)
local sgnu = p.sdmath.sgn(u);
if p.sdmath.abs(sgnu) < 1e-12 then sgnu = sgnu + p.sdmath.ele(1) end
return -sgnu * p.sdmath.atanh( v * sgnu )
end,
acot=function(z)
local v = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(z))
local u = p.sdmath.nonRealPart(z)
local sgnu = p.sdmath.sgn(u);
if p.sdmath.abs(sgnu) < 1e-12 then sgnu = sgnu + p.sdmath.ele(1) end
return sgnu * p.sdmath.acoth( v * sgnu )
end,
sinh=function(z)
local u = p.sdmath.nonRealPart(z)
return ( math.cos(p.sdmath.abs(u)) * math.sinh(p.sdmath.re(z)) ) + ( p.sdmath.sgn(u) * math.sin(p.sdmath.abs(u)) * math.cosh(p.sdmath.re(z)) )
end,
cosh=function(z)
local u = p.sdmath.nonRealPart(z)
return ( math.cos(p.sdmath.abs(u)) * math.cosh(p.sdmath.re(z)) ) + ( p.sdmath.sgn(u) * math.sin(p.sdmath.abs(u)) * math.sinh(p.sdmath.re(z)) )
end,
tanh=function(z)
local theta = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(z))
return p.sdmath.sinh(theta) * p.sdmath.inverse( p.sdmath.cosh(theta) )
end,
coth=function(z)
local theta = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(z))
return p.sdmath.cosh(theta) * p.sdmath.inverse( p.sdmath.sinh(theta) )
end,
asinh=function(z)
local _one = p.sdmath.getSedenionNumber("1", "0")
local u = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(z))
return p.sdmath.checkMathform(p.sdmath.elog( u + p.sdmath.sqrt( u * u + _one ) ), z)
end,
acosh=function(z)
local _one = p.sdmath.getSedenionNumber("1", "0")
local u = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(z))
return p.sdmath.checkMathform(p.sdmath.elog( u + p.sdmath.sqrt( u + _one ) * p.sdmath.sqrt( u - _one ) ),z)
end,
atanh=function(z)
local _one = p.sdmath.getSedenionNumber("1", "0")
local u = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(z))
return p.sdmath.checkMathform(( p.sdmath.elog( _one + u ) - p.sdmath.elog( _one - u ) ) / 2, z)
end,
acoth=function(z)
local _one = p.sdmath.getSedenionNumber("1", "0")
local u = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(z))
return p.sdmath.checkMathform(( p.sdmath.elog( _one + p.sdmath.inverse(u) ) - p.sdmath.elog( _one - p.sdmath.inverse(u) ) ) / 2, z)
end,
dot = function (op1, op2)
local nonL1, valL1 = p.sdmath.readSedenionNumberCDpart(op1)
local nonL2, valL2 = p.sdmath.readSedenionNumberCDpart(op2)
return p.sdmath.mathlib.dot(nonL1, nonL2) + p.sdmath.mathlib.dot(valL1, valL2)
end,
scalarPart=function(z)
local A, B = p.sdmath.readSedenionNumberCDpart(z)
return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(p.sdmath.toSubNumber(tostring(p.sdmath.mathlib.re(A))), p.sdmath.toSubNumber("0")), z)
end,
vectorPart=function(z)
return p.sdmath.nonRealPart(z)
end,
nonRealPart=function(z)
local A, B = p.sdmath.readSedenionNumberCDpart(z)
return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(p.sdmath.mathlib.nonRealPart(A), B), z)
end,
sgn=function(z)
local A, B = p.sdmath.readSedenionNumberCDpart(z)
local A_len, B_len = p.sdmath.mathlib.abs(A), p.sdmath.mathlib.abs(B)
local length = math.sqrt( A_len * A_len + B_len * B_len )
if length <= 0 then return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(p.sdmath.toSubNumber("0"),p.sdmath.toSubNumber("0")), z) end
return p.sdmath.checkMathform(z / length, z)
end,
arg=function(z) --TODO: verify
local A, B = p.sdmath.readSedenionNumberCDpart(z)
local A_len, B_len = p.sdmath.mathlib.abs(A), p.sdmath.mathlib.abs(B)
local length = math.sqrt( A_len * A_len + B_len * B_len )
return math.acos( p.sdmath.mathlib.re(A) / length )
end,
cis=function(z)
local u = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(z))
return p.sdmath.cos(u) + p.sdmath.ele(1) * p.sdmath.sin(u)
end,
exp=function(z) --Cayley-Dickson construction
local u = p.sdmath.nonRealPart(z)
return p.sdmath.checkMathform(( (p.sdmath.sgn(u) * math.sin(p.sdmath.abs(u))) + math.cos(p.sdmath.abs(u))) * math.exp(p.sdmath.re(z)), z)
end,
elog=function(z) --Cayley-Dickson construction
local u = p.sdmath.nonRealPart(z)
return p.sdmath.checkMathform(p.sdmath.sgn(u)*p.sdmath.arg(z)+math.log(p.sdmath.abs(z)), z)
end,
log=function(z,basez)
if basez~=nil then return p.sdmath.checkMathform(p.sdmath.elog(basez) * p.sdmath.inverse(p.sdmath.elog(z)), z) end
return p.sdmath.elog(z)
end,
pow=function(op1,op2)
local _zero = p.sdmath.getSedenionNumber("0", "0")
local a = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(op1))
local z = p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(op2))
a:clean();z:clean();
if a.B == _zero and z.B == _zero then
return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(p.sdmath.mathlib.pow(a.A, z.A), p.sdmath.toSubNumber("0")), op1, op2)
end
return p.sdmath.checkMathform(p.sdmath.exp(z * p.sdmath.elog(a)):clean(), op1, op2)
end,
ele=function(id)
local _zero = p.sdmath.getSedenionNumber(p.sdmath.toSubNumber("0"), p.sdmath.toSubNumber("0"))
local eles = (p.sdmath.elements or {})
local id_msg = tonumber(tostring(id)) or 0
return p.sdmath.checkMathform(eles[id_msg+1]or _zero, id)
end,
readSedenionNumberCDpart = function(z)
if type(z) == type(function()end) then return end
if type(z) == type(true) then return p.sdmath.toSubNumber(z and '1' or '0'), p.sdmath.toSubNumber("0") end
local dim = tonumber(({tostring((type(z)==type({}))and z.numberType or ''):gsub("%-onion","")})[1])
if type(z) == type({}) then --if already be complex number, don't run string find.
if z.numberType == "complex" then
return p.sdmath.toSubNumber(tostring(z)), p.sdmath.toSubNumber("0")
elseif z.numberType == "quaternion" then
return p.sdmath.toSubNumber(tostring(z)), p.sdmath.toSubNumber("0")
elseif z.numberType == "octonion" then
return p.sdmath.toSubNumber(tostring(z)), p.sdmath.toSubNumber("0")
elseif z.numberType == "sedenion" then
return z.A, z.B
end
elseif type(z) == type(0) then
return p.sdmath.toSubNumber(tostring(z)), p.sdmath.toSubNumber("0")
elseif type(z) == type(true) then
return p.sdmath.toSubNumber(z and '1' or '0'), p.sdmath.toSubNumber("0")
end
end,
random=function(op1, op2)
if type(op1)==type(nil) and type(op2)==type(nil) then return p.sdmath.getSedenionNumber(p.sdmath.mathlib.random(), p.sdmath.toSubNumber("0")) end
local op1_a, op1_b = p.sdmath.readSedenionNumberCDpart(op1)
if type(op2)==type(nil) then return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(p.sdmath.mathlib.random(op1_a), p.sdmath.mathlib.random(op1_b)), op1) end
local op2_a, op2_b = p.sdmath.readSedenionNumberCDpart(op2)
return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(p.sdmath.mathlib.random(op1_a, op2_a), p.sdmath.mathlib.random(op1_b, op2_b)), op1, op2)
end,
isReal=function(z) return p.sdmath.abs(p.sdmath.nonRealPart(z)) < 1e-14 end,
SedenionNumberMeta = {
__add = function (op1, op2)
local op1_a, op1_b = p.sdmath.readSedenionNumberCDpart(op1)
local op2_a, op2_b = p.sdmath.readSedenionNumberCDpart(op2)
return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(op1_a + op2_a, op1_b + op2_b), op1, op2)
end,
__sub = function (op1, op2)
local op1_a, op1_b = p.sdmath.readSedenionNumberCDpart(op1)
local op2_a, op2_b = p.sdmath.readSedenionNumberCDpart(op2)
return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(op1_a - op2_a, op1_b - op2_b), op1, op2)
end,
__mul = function (op1, op2)
local _a, _b = p.sdmath.readSedenionNumberCDpart(op1)
local _c, _d = p.sdmath.readSedenionNumberCDpart(op2)
local r_nonL = _a*_c - p.sdmath.mathlib.conjugate(_d)*_b
local r_valL = _d*_a + _b*p.sdmath.mathlib.conjugate(_c)
return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(r_nonL, r_valL), op1, op2)
end,
__div = function (op1, op2)
local op_div = p.sdmath.inverse(op2)
local _a, _b = p.sdmath.readSedenionNumberCDpart(op1)
local _c, _d = p.sdmath.readSedenionNumberCDpart(op_div)
local r_nonL = _a*_c - p.sdmath.mathlib.conjugate(_d)*_b
local r_valL = _d*_a + _b*p.sdmath.mathlib.conjugate(_c)
return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(r_nonL, r_valL), op1, op2)
end,
__mod = function (op1, op2)
local x = p.sdmath.readComplexNumber(op1)
local y = p.sdmath.readComplexNumber(op2)
return p.sdmath.checkMathform(x - y * qmath.floor(x / y), op1, op2)
end,
__unm = function (this)
return p.sdmath.checkMathform(p.sdmath.getSedenionNumber(-this.A, -this.B), this)
end,
__eq = function (op1, op2)
return op1.A == op2.A and op1.B == op2.B
end,
__tostring = function (this)
local A, B = p.sdmath.readSedenionNumberCDpart(this)
local strA = tostring(A)
local strB = tostring(B)
if strA == "nan" or strA == "-nan" then return strA end
if strB == "nan" or strB == "-nan" then return strB end
if strA == "0" and strB == "0" then return "0" end
local body = ''
local eles = (p.sdmath.elements or {})
for i=1,#eles do
--p.sdmath.readSedenionNumberCDpart(eles[i])
local val = tonumber(p.sdmath.dot(this,eles[i]))or 0
if math.abs(val)>1e-14 then
local val_str = ''
local is_one = (math.abs(math.abs(val)-1)<1e-14)
local has_num = false
if val>0 then
if body~=''then val_str = val_str ..'+'end
val_str = val_str..(is_one and''or tostring(val))
has_num = true
elseif val<0 then
val_str = val_str..(is_one and'-'or tostring(val))
has_num = true
end
if has_num then
if i==1 then
body = body..val_str..(is_one and'1'or'')
else
if this.mathform then
body = body..val_str..' e_{'..tostring(i-1)..'}'
elseif this.htmlform then
body = body..val_str..(is_one and''or' ')..' e<sub>'..tostring(i-1)..'</sub>'
else
body = body..val_str..(is_one and''or'*')..'ele('..tostring(i-1)..')'
end
end
end
end
end
if body=='' then body = 0 end
--return mw.dumpObject(this)
return body
end,
},
checkMathform=function(result,...)
local parms = {...}
local flag = false
for i=1,#parms do flag = flag or ((type(parms[i])==type({}))and parms[i].mathform or false)end
if type(result)==type({})then result.mathform = result.mathform or flag end
return result
end,
mathlib=cmath,
toSubNumber=cmath.constructor,
mathform = function(this)this.mathform=true return this end,
htmlform = function(this)this.htmlform=true return this end,
toSedenionNumber = function(str)
--load if already a number
local dim = tonumber(({tostring((type(str)==type({}))and str.numberType or ''):gsub("%-onion","")})[1])
if type(str) == type({}) then --if already be complex number, don't run string find.
if str.numberType == "complex" then
return p.sdmath.getSedenionNumber(p.sdmath.toSubNumber(tostring(str)), p.sdmath.toSubNumber("0"))
elseif str.numberType == "quaternion" then
return p.sdmath.getSedenionNumber(p.sdmath.toSubNumber(tostring(str)), p.sdmath.toSubNumber("0"))
elseif str.numberType == "octonion" then
return p.sdmath.getSedenionNumber(p.sdmath.toSubNumber(tostring(str)), p.sdmath.toSubNumber("0"))
elseif str.numberType == "sedenion" then
return p.sdmath.getSedenionNumber(str.A, str.B)
end
elseif type(str) == type(0) then
return p.sdmath.getSedenionNumber(p.sdmath.toSubNumber(tostring(str)), p.sdmath.toSubNumber("0"))
elseif type(str) == type(true) then
return p.sdmath.getSedenionNumber(p.sdmath.toSubNumber(str and '1' or '0'), p.sdmath.toSubNumber("0"))
end
--try to parse into substring
local tmp_num = p.sdmath.toSubNumber(tostring(str))
if tmp_num ~= nil then
return p.sdmath.getSedenionNumber(tmp_num, p.sdmath.toSubNumber("0"))
end
--parse full string
local chk_str = tostring(str)
local got_list = {}
local ismath = false
if mw.ustring.find(chk_str,"%(")then
got_list = mw.text.split(mw.ustring.gsub(chk_str,"([%+%-])",",%1"),",")
for i=1,#got_list do
got_list[i] = mw.ustring.gsub(got_list[i],"ele","*"):gsub("%*+","*"):gsub("[%(%)]","")
end
elseif mw.ustring.find(chk_str,"%{")then
got_list = mw.text.split(mw.ustring.gsub(chk_str,"([%+%-])",",%1"),",")
for i=1,#got_list do
got_list[i] = mw.ustring.gsub(got_list[i],"^e"," e"):gsub("e","*"):gsub(" +","*"):gsub("%*+","*"):gsub("[_%{%}]","")
end
ismath = true
end
if #got_list > 0 then
local eles = (p.sdmath.elements or {})
local result_number = p.sdmath.getSedenionNumber(p.sdmath.toSubNumber("0"), p.sdmath.toSubNumber("0"))
local _zero = p.sdmath.getSedenionNumber(p.sdmath.toSubNumber("0"), p.sdmath.toSubNumber("0"))
local _one = p.sdmath.getSedenionNumber(p.sdmath.toSubNumber("1"), p.sdmath.toSubNumber("0"))
for i=1,#got_list do
if mw.text.trim(got_list[i])~='' then
local check_ele = mw.text.split(got_list[i],"%*+")
local real_coeff = tonumber(check_ele[1])or (tonumber( (tostring(check_ele[1])~='')and(tostring(check_ele[1])..'1')or check_ele[1] ) or 1)
local real_eleid = tonumber(check_ele[2])or 0
local this_ele = eles[real_eleid+1]or _zero
result_number = result_number + this_ele*real_coeff
end
end
result_number.mathform = ismath
return result_number
end
return p.sdmath.getSedenionNumber(p.sdmath.readSedenionNumberCDpart(str))
end,
getSedenionNumber = function(a,b)
local SedenionNumber = {}
setmetatable(SedenionNumber,p.sdmath.SedenionNumberMeta)
function SedenionNumber: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 SedenionNumber:clean()
xpcall(function()
self.A:clean()
self.B:clean()
end,function()end)
return self
end
SedenionNumber.A = p.sdmath.toSubNumber(a)
SedenionNumber.B = p.sdmath.toSubNumber(b)
if not SedenionNumber.A then SedenionNumber.A = p.sdmath.toSubNumber("0") end
if not SedenionNumber.B then SedenionNumber.B = p.sdmath.toSubNumber("0") end
SedenionNumber.numberType = "sedenion"
return SedenionNumber
end,
halfNumberParts = function(num)
local A, B = p.sdmath.readSedenionNumberCDpart(num)
return {A, B}
end,
init = function()
local omath=require("Module:Complex_Number/Octonion").omath.init()
p.sdmath.mathlib = omath
p.sdmath.toSubNumber = omath.constructor
local _zero = p.sdmath.toSubNumber("0")
p.sdmath.elements = {}
local unit_list = p.sdmath.mathlib.elements or{}
p.sdmath.elementCount = (#unit_list)*2
for i=1,p.sdmath.elementCount do p.sdmath.elements[i] = {} end
for i=1,#unit_list do
p.sdmath.elements[i] = p.sdmath.getSedenionNumber(unit_list[i], "0")
end
for i=1,#unit_list do
p.sdmath.elements[i+#unit_list] = p.sdmath.getSedenionNumber("0", unit_list[i])
end
p.sdmath.pi = p.sdmath.getSedenionNumber(p.sdmath.mathlib.pi, _zero)
p.sdmath["π"] = p.sdmath.getSedenionNumber(p.sdmath.mathlib.pi, _zero)
p.sdmath["°"] = p.sdmath.getSedenionNumber(p.sdmath.mathlib.pi/180, _zero)
p.sdmath.e = p.sdmath.getSedenionNumber(math.exp(1), _zero)
p.sdmath.nan = p.sdmath.getSedenionNumber(tonumber("nan"), tonumber("nan"))
p.sdmath.zero = p.sdmath.getSedenionNumber("0", _zero)
p.sdmath.one = p.sdmath.getSedenionNumber("1", _zero)
p.sdmath[-1] = p.sdmath.getSedenionNumber("-1", _zero)
p.sdmath[0],p.sdmath[1] = p.sdmath.zero,p.sdmath.one
p.sdmath.numberType = comp_lib._numberType
p.sdmath.constructor = p.sdmath.toSedenionNumber
return p.sdmath
end
}
new_meta = getmetatable( p ) or {}
new_meta.__index = function (this, func_name)
if mw.ustring.find(func_name, "=") then
local eqs, eqe = mw.ustring.find(func_name, "=")
local check_func_name = mw.ustring.sub(func_name,1, (eqs or 0)-1)
local check_r = mw.ustring.find(check_func_name, "=")
if not check_r then
local tocall_obj = p[check_func_name]
if type(tocall_obj) == type({}) then
local math_class = mw.ustring.sub(func_name,(eqe or 0)+1, -1)
if type(tocall_obj._init) ~= nil then
local mymath = cmath
local mytomath = cmath.constructor
if mw.ustring.sub(math_class,1,7):upper()=="MODULE:" then
local module_name, math_lib_name = p.checkModuleClass(math_class)
xpcall(function()
local load_module = require("Module:"..module_name)
if load_module ~= nil then
local load_math_lib = load_module[math_lib_name]
if load_module ~= nil then
local func_type = type(function()end)
local my_math_lib = (type(load_math_lib.init) == func_type) and load_math_lib.init() or load_math_lib
if type(my_math_lib.constructor) == func_type then
math_class = "mymath"
mymath = my_math_lib
mytomath = my_math_lib.constructor
end
end
end
end,function()end)
end
tocall_obj.init=function()
return tocall_obj._init(mymath)
end
end
return tocall_obj
end
end
end
return nil
end
setmetatable(p, new_meta)
return p