Module:Complex Number/Calculate: Difference between revisions
1>A2569875 (+連續等號功能) |
m (1 revision imported) |
(No difference)
|
Latest revision as of 12:17, 23 April 2025
local p = {} local getArgs = require('Module:Arguments').getArgs local ext_mathlib = require("Module:Complex Number/Functions")._init local comp_number = nil local TrackingCategory = require('Module:TrackingCategory') local Operators = require('Module:Complex_Number/Calculate/Operators') local strip_marker_temp, strip_marker_temp_len = {}, 0 local noop_func = function()end p.use_other_module = false p.symbol_table=Operators.symbol_table --======== public tools ======== function p._remove_strip_marker(str)return mw.text.decode(mw.text.unstrip(str)) end function p._load_strip_marker(str)return mw.ustring.gsub(mw.text.decode(mw.text.unstripNoWiki(str)),"\127'\"`UNIQ.-QINU`\"'\127",function(strip) strip_marker_temp_len = strip_marker_temp_len + 1 local idx_az = numberToAZ(strip_marker_temp_len) strip_marker_temp[idx_az] = strip return ' UNQ' .. idx_az .. ' ' end)end function p._function_preprocessing(input_str,math_lib, number_Constructer, debug_flag, jsut_load) local input_fo, ftable = Operators.function_preload(input_str,{},math_lib, number_Constructer, debug_flag, p.nocalc, jsut_load) if type(ftable)~=type({"table"})then return input_fo, {} end local final_scope=Operators.fill_function(ftable,{}) final_scope=Operators.fill_scope(final_scope, math_lib, number_Constructer, debug_flag, p.calc_by_postfix) return input_fo, final_scope end function p._re_math_output(unmathstr) return tostring(p._preCalculate({tostring(unmathstr):gsub('%*','⋅'),class="mathtag"})) end function p._adj_math_output(unmathstr) return mw.text.trim(mw.ustring.gsub(" "..unmathstr.." ","ω","\\omega "):gsub("ε","\\varepsilon ") :gsub("([^%a])inf([^%a])","%1\\infty %2"):gsub("([^%a])nan([^%a])","%1\\mathrm{NaN}%2") :gsub("([%+%-]?)(%d*%.?%d+)e([%+%-]?%d+)","%1%2\\times 10^{%3}")) end function p._randomseed()math.randomseed(math.floor(os.time() * os.clock()))end
function p._getNumString(input_string, exp_flag) local str, shift_digits = p.scientific2number(mw.ustring.upper(input_string), exp_flag) local int_digits, float_digits = {}, {} if mw.ustring.find(input_string, "[;:]") then str = mw.ustring.gsub(str, "[^;:,%d%.]", "") local pre_digits = mw.text.split(str, "[,:]") local doing_int = true for i=1,#pre_digits do if doing_int then local find_point = mw.ustring.find(pre_digits[i], "[;%.]") if find_point then doing_int = false int_digits[#int_digits + 1] = tonumber( ({mw.ustring.gsub(mw.ustring.sub(pre_digits[i], 1, find_point-1), "[;%.]", "")})[1] ) or 0 float_digits[#float_digits + 1] = tonumber( ({mw.ustring.gsub(mw.ustring.sub(pre_digits[i], find_point+1, -1), "[;%.]", "")})[1] ) or 0 else int_digits[#int_digits + 1] = tonumber( ({mw.ustring.gsub(pre_digits[i], "[;%.]", "")})[1] ) or 0 end else float_digits[#float_digits + 1] = tonumber( ({mw.ustring.gsub(pre_digits[i], "[;%.]", "")})[1] ) or 0 end end if #int_digits == 0 then int_digits[1] = 0 end if #float_digits == 0 then float_digits[1] = 0 end else str = mw.ustring.gsub(str, "[^%.%d%a]", "") local point_pos = mw.ustring.find(str, "%.") local int_str, float_str = ((point_pos or 2) <= 1) and "0" or mw.ustring.sub(str, 1, (point_pos or 0)-1), point_pos and mw.ustring.sub(str, point_pos+1, -1) or float_str = mw.ustring.gsub(float_str, "%.", "") local char_0 = mw.ustring.codepoint('0') local char_A = mw.ustring.codepoint('A') local char_Z = mw.ustring.codepoint('Z') local int_strlen, float_strlen = mw.ustring.len(int_str), mw.ustring.len(float_str) for i=1,int_strlen do local code_point = mw.ustring.codepoint(mw.ustring.sub(int_str,i,i)) if code_point < char_A and code_point >= char_0 then code_point = code_point - char_0 elseif code_point <= char_Z then code_point = code_point - char_A + 10 end int_digits[i] = code_point end for i=1,float_strlen do local code_point = mw.ustring.codepoint(mw.ustring.sub(float_str,i,i)) if code_point < char_A and code_point >= char_0 then code_point = code_point - char_0 elseif code_point <= char_Z then code_point = code_point - char_A + 10 end float_digits[i] = code_point end end return int_digits, float_digits end
--======== local tools ======== local function numberToAZ(num) local body = local s = tostring(math.floor(tonumber(num))) for i = 1, mw.ustring.len(s) do local char_id = tonumber(mw.ustring.sub(s, i, i)) + 65 char_id = char_id + ((char_id >= 73) and 3 or 0) body = body .. mw.ustring.char(char_id) end return body end local function _subst_strip(str) local UNIQ mw.ustring.gsub(str, "UNQ(%a+)$", function(num) UNIQ = UNIQ or num end) return strip_marker_temp[UNIQ or -1] or str end local function _subst_error_strip(str) local UNIQ mw.ustring.gsub(str, "UNQ(%a+)$", function(num) UNIQ = UNIQ or num end) return mw.ustring.gsub(strip_marker_temp[UNIQ or -1] or str, "\127'\"`UNIQ%-%-(%a+).-QINU`\"'\127", "<%1></%1>") end local function stringToTable(s) --字串轉陣列 local t, i = {}, 1 while i <= mw.ustring.len(s) do if mw.ustring.sub(s, i, i) ~= ' ' then local j, k = mw.ustring.find(s,"[%d%a]+",i) if (j or (i+1)) > i then t[#t + 1] = mw.ustring.sub(s, i, i) else t[#t + 1] = mw.ustring.sub(s, j, k) i = k end end i = i + 1 end return t end local function print_sk(sk,sp) local body, sp_checker = , mw.text.trim(sp or ) for i = 1,#sk do local checker = ((type(sk[i]) == type({})) and sk[i].name or nil) or sk[i] if type(checker) == type({}) then local cats = "" for cati=1,#checker do if cats ~= "" then cats = cats .. ',' end cats = cats .. tostring(checker[cati])end checker = cats end if mw.text.trim( (type(checker)==type(noop_func))and "function" or checker ) ~= sp_checker then if body ~= then body = body .. (sp or ' ') end if type(sk[i]) == type({}) and sk[i].name then if sk[i].name == "$END" then body = body .. '$' else body = body .. sk[i].name end else if tostring(sk[i]) == 'table' and sk[i].assign=="assign" then body = body .. (tostring(sk[i][1])=="$END" and "${字串結尾}" or _subst_error_strip(tostring(sk[i][1]))) else body = body .. _subst_error_strip(tostring(sk[i])) end end end end return body end --======== template tools ======== 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 function p.scientific2number(input_str, exp_flag) local inputstr = input_str if type(input_str) == type({"table"}) then inputstr = (input_str.args or {})[1] or input_str[1] or elseif type(input_str) ~= type("string") then inputstr = tostring(input_str) end local input_numstr = mw.text.trim(inputstr) local numstr, flag = input_numstr local exp_num = 0 local sign_str = mw.ustring.sub(numstr,1,1) if not (sign_str=='+' or sign_str=='-' or sign_str=='−') then sign_str= else numstr = mw.ustring.sub(numstr,2,-1) end numstr, flag = mw.ustring.gsub(numstr, "^%s*([%d%.]+)%s*[Ee]%s*([+-−]"..(exp_flag and or '-').."%d+)%s*$", function(number_name, dig_str) local digits = mw.ustring.gsub(dig_str, "%+", "") digits = mw.ustring.gsub(digits, "[-−]+", "-") exp_num = tonumber(digits) or 0 return number_name end) numstr = numstr ..'.' if flag <= 0 then return input_numstr end numstr = mw.ustring.gsub(numstr, "[^%d%.]", "") local pti, ptat = 0, (({mw.ustring.find(numstr, "%.")})[1]or 2)-1 numstr = mw.ustring.gsub(numstr, "%.", "") local numlen = mw.ustring.len(numstr) if ptat + exp_num > 0 then if numlen < ptat + exp_num then numstr = numstr .. string.rep( '0', ptat + exp_num - numlen ) elseif numlen > ptat + exp_num then numstr = mw.ustring.sub(numstr, 1, ptat + exp_num)..'.'..mw.ustring.sub(numstr, ptat + exp_num+1, -1) end elseif ptat + exp_num <= 0 then numstr = '0.' .. ((ptat + exp_num==0) and or string.rep( '0', - ptat - exp_num )) .. numstr end return sign_str .. numstr end --======== main ======== function p._preCalculate(frame, error_func)
local args local can_math = false local should_math = false if frame == mw.getCurrentFrame() then -- We're being called via #invoke. The args are passed through to the module -- from the template page, so use the args that were passed into the template. args = getArgs(frame) --frame.args local yesno = require('Module:Yesno') can_math = yesno(args['use math'] or args['use_math']) should_math = yesno(args['should math'] or args['should_math']) else -- We're being called from another module or from the debug console, so assume -- the args are passed in directly. args = frame end local yesno = require('Module:Yesno') if yesno(args.useOtherModule or 'no') == true then p.use_other_module = true end
if comp_number == nil then comp_number = require("Module:Complex Number") end
local cmath, qmath, bmath = comp_number.cmath.init(), comp_number.qmath.init(), comp_number.bmath.init() local mathtag = p.tagmath.init()
local math_class = args['class']or if mw.text.trim(math_class) == then math_class = "cmath" end local mymath = cmath local mytomath = cmath.toComplexNumber 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(noop_func) 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,noop_func) end
local input_math_lib = ( {
cmath = cmath, qmath = qmath, bmath = bmath, mathtag = mathtag, mymath = mymath } ) [ math_class ] local input_to_number = (( { cmath = cmath.toComplexNumber, qmath = qmath.toQuaternionNumber, bmath = bmath.toBoolean, mathtag = mathtag.toTagMath, mymath = mytomath } ) [ math_class ] ) return p.calc(p._load_strip_marker(args[1] or args['1'] or ), input_math_lib , input_to_number, nil, nil, error_func ), can_math, should_math, input_math_lib, input_to_number, args end function p.templateCalculate(frame)
p._randomseed()
local body, can_math, should_math, input_math_lib, input_to_number, args = p._preCalculate(frame) if type(body) == type("string") then if body:find("function") then body = body:gsub("function([A-Z]+)",function(func_id) local result = func_id:gsub("[A-Z]",function(char_it) local char_id = char_it:byte(1,1) local num_id = char_id - 65 return tostring(num_id - ((num_id>=10) and 3 or 0)) end) return "function"..result end) end end if should_math or can_math then local yesno = require('Module:Yesno') if args.class ~= "mathtag" and yesno(args['show math'] or args['shw_math']) then body = p._re_math_output(body) end body = p._adj_math_output(tostring(body)) end if can_math then body = frame:callParserFunction{name = "#tag:math", args = {tostring(body)}} end return body end function p.calculate(frame)
p._randomseed()
local body, can_math, should_math = p._preCalculate(frame) if should_math or can_math then body = p._adj_math_output(tostring(body)) end if can_math then body = frame:callParserFunction{name = "#tag:math", args = {tostring(body)}} end return body end
function p.toPostfix(frame)--單純印出字串,不運算
local args if frame == mw.getCurrentFrame() then -- We're being called via #invoke. The args are passed through to the module -- from the template page, so use the args that were passed into the template. args = getArgs(frame, { trim = false,
removeBlanks = false
}) --frame.args else -- We're being called from another module or from the debug console, so assume -- the args are passed in directly. args = frame end
local format = mw.text.decode(args.format or"{{{1}}} "); format = mw.ustring.gsub(format, "%{%{%{.-%}%}%}", "%%s" ); local it = mw.ustring.find(format, "%%s", 1) format = mw.ustring.gsub(format, "\\n", "\n") local expr_geter = p._function_preprocessing(p._load_strip_marker(args[1] or args['1'] or ),{}, nil, nil, true) local result, body = p.infixToPostfix( expr_geter ), for i, result_str in pairs( result ) do if type(result_str)==type({}) and mw.text.trim(result_str.name) ~= '|' and result_str.propetry ~= "func start" then body = body .. mw.ustring.gsub(format, "%%s", _subst_strip(mw.text.trim(tostring(result_str.name)))) elseif type(result_str)==type("string") then body = body .. mw.ustring.gsub(format, "%%s", _subst_strip(mw.text.trim(tostring(result_str)))) end end return body end
function p.toPrefix(frame)--單純印出字串,不運算
local args if frame == mw.getCurrentFrame() then -- We're being called via #invoke. The args are passed through to the module -- from the template page, so use the args that were passed into the template. args = getArgs(frame, { trim = false,
removeBlanks = false
}) --frame.args else -- We're being called from another module or from the debug console, so assume -- the args are passed in directly. args = frame end
local format = mw.text.decode(args.format or"{{{1}}} "); format = mw.ustring.gsub(format, "%{%{%{.-%}%}%}", "%%s" ); local it = mw.ustring.find(format, "%%s", 1) format = mw.ustring.gsub(format, "\\n", "\n") local expr_geter = p._function_preprocessing(p._load_strip_marker(args[1] or args['1'] or ),{}, nil, nil, true) local postfix, body = p.infixToPostfix( expr_geter ), local pre_stack = {} local cmt_str = "" local cmt_count = 0 local function _item_tostring(item)return _subst_strip((type(item)==type({"table"}))and(item.name or tostring(item))or tostring(item))end local function tail_process() if cmt_str ~= "" then local oper_out_format = (cmt_count==2) and "%s , %s" or ((cmt_count==1) and "%s %s" or "%s (, %s)") pre_stack[#pre_stack<=0 and 1 or #pre_stack] = mw.ustring.format(oper_out_format, _item_tostring(pre_stack[#pre_stack]and(pre_stack[#pre_stack]..' ')or), _item_tostring(cmt_str) ) cmt_str = "" else local new_top = for i=1,#pre_stack do if new_top ~= then new_top = new_top .. ' ' end new_top = new_top .. _item_tostring(pre_stack[i]) end for i=#pre_stack,1,-1 do pre_stack[i] = nil end pre_stack[1] = new_top end end for i = 1,#postfix do local it = postfix[i] local opdata = (it.propetry == "operator") and p.symbol_table[it.name] or {count=0} if it.name == "," then --case 逗號 if cmt_str == "" then if #pre_stack >= 2 then cmt_str = mw.ustring.format("%s %s", _item_tostring(pre_stack[#pre_stack-1]), _item_tostring(pre_stack[#pre_stack])) cmt_count = 2 pre_stack[#pre_stack] = nil else cmt_str = _item_tostring(pre_stack[#pre_stack]or ' ') cmt_count = mw.test.trim(cmt_str)== and 0 or 1 end else local new_cmt = (pre_stack[#pre_stack]and(' '.._item_tostring(pre_stack[#pre_stack])))or cmt_str = cmt_str .. new_cmt cmt_count = cmt_count + (mw.text.trim(new_cmt)== and 0 or 1) end pre_stack[#pre_stack] = nil elseif it.propetry == "func start" then pre_stack[#pre_stack+1] = "$function_start\127" elseif it.propetry == "func" then local par_count = 0 local find_func_head = #pre_stack while not mw.ustring.find(_item_tostring(pre_stack[find_func_head]),"%$function_start\127") do if find_func_head < 1 then par_count = 0 break end par_count = par_count + 1 find_func_head = find_func_head - 1 end local par_data = _item_tostring(pre_stack[find_func_head]or'$function_start\127') find_func_head = find_func_head <= 0 and #pre_stack or find_func_head local mark_start, mark_end = mw.ustring.find(par_data,"%$function_start\127") par_data = mw.text.split(mark_start and par_data or "$function_start\127","%$function_start\127") local tail_data = if cmt_str ~= "" then tail_data = mw.ustring.format("%s %s",_item_tostring(par_data[2]),_item_tostring(cmt_str)) par_count = par_count + cmt_count end local par_it = find_func_head+1 while par_it <= #pre_stack do tail_data = mw.ustring.format("%s %s",tail_data,_item_tostring(pre_stack[par_it])) par_it = par_it + 1 end tail_data = mw.ustring.format((par_count==2) and "%s %s" or "(%s %s)",_item_tostring(it),tail_data) local head_data = mw.text.trim(par_data[1]) pre_stack[find_func_head] = (head_data== and or head_data..' ')..tail_data par_it = find_func_head+1 while par_it <= #pre_stack do pre_stack[par_it]=nil end cmt_str = "" cmt_count=0 elseif opdata.count == 1 then if opdata.count == 1 or cmt_str == "" then pre_stack[#pre_stack] = mw.ustring.format("(%s %s)", _item_tostring(it),_item_tostring(pre_stack[#pre_stack]) ) else local oper_out_format = (cmt_count==2) and "%s %s" or "(%s %s)" pre_stack[(#pre_stack<=0 and 0 or #pre_stack) + 1] = mw.ustring.format(oper_out_format, _item_tostring(it),_item_tostring(cmt_str) ) end cmt_str = "" cmt_count=0 elseif opdata.count == 2 then --case 2元運算子 if #pre_stack == 1 and cmt_str ~= "" then local oper_out_format = (cmt_count==2) and "%s %s , %s" or ((cmt_count==1) and "%s %s %s" or "%s %s (, %s)") pre_stack[#pre_stack] = mw.ustring.format(oper_out_format, _item_tostring(it), _item_tostring(pre_stack[#pre_stack]), _item_tostring(cmt_str) ) cmt_str = "" cmt_count=0 else pre_stack[#pre_stack-1] = mw.ustring.format("%s %s %s", _item_tostring(it), _item_tostring(pre_stack[#pre_stack-1]), _item_tostring(pre_stack[#pre_stack]) ) pre_stack[#pre_stack] = nil end elseif it.propetry == "operator" then elseif it.name == "$END" then --case 結尾 tail_process() else--otherwise pre_stack[#pre_stack+1] = it end end tail_process()
local result = mw.text.trim(_item_tostring(pre_stack[1]) or _item_tostring(pre_stack[0])) if mw.ustring.sub(result,1,1) == '(' and mw.ustring.sub(result,-1,-1) == ')' then result = mw.ustring.sub(result,2,-2) end result = mw.text.split(mw.ustring.gsub(result,'%s+',' '),'%s+') for i, result_str in pairs( result ) do if mw.text.trim(result_str) ~= '|' then body = body .. mw.ustring.gsub(format, "%%s", result_str) end end body = mw.ustring.gsub(body,"⇽","←") return body end
--mw.log(p.calc("45*5+(1+5-9+((12-5)+5i+(9)/4)*sqrt(-6))*-8",require("Module:Complex Number").cmath.init(),require("Module:Complex Number").cmath.init().toComplexNumber,true,true,function(msg)mw.log("錯誤! "..msg)end)) -- 346.97959 - 181.262241 i --mw.log(p.calc("45*5+(1+5-9+((12-5)+5+(9)/4)*sin(-6))*-8",nil,nil,true,true,function(msg)mw.log("錯誤! "..msg)end)) -- 217.146633205 --mw.log(p.calc("(i*j*k)",require("Module:Complex Number").qmath.init(),require("Module:Complex Number").qmath.init().toQuaternionNumber,true,true,function(msg)mw.log("錯誤! "..msg)end)) -- (-1) function p.calc(input_str, math_lib, number_Constructer, debug_flag, should_use_other_module, error_func) if comp_number == nil then comp_number = require("Module:Complex Number") end if should_use_other_module ~= nil then p.use_other_module = not (not should_use_other_module) end math = comp_number.math.init() local mathlib, numberConstructer = math_lib or math, number_Constructer or tonumber local adj_input_str = input_str if math_lib and math_lib.is_bool_lib == true then adj_input_str = mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(' ' .. input_str .. ' ',"%s+and%s+"," * "),"[&∧]","*"),"%s+or%s+"," + "),"∨","+"),"%s+not%s+"," - "),"¬","-") end local pre_expr, pre_scope = p._function_preprocessing(adj_input_str, math_lib, number_Constructer, debug_flag) local postfix = p.infixToPostfix(pre_expr, debug_flag) if pre_scope then postfix.scope = pre_scope end return p.calc_by_postfix(postfix, {}, math_lib, number_Constructer, debug_flag, error_func) end
function p.nocalc(input_str, math_lib, number_Constructer, debug_flag) if comp_number == nil then comp_number = require("Module:Complex Number") end math = comp_number.math.init() local mathlib, numberConstructer = math_lib or math, number_Constructer or tonumber local adj_input_str = input_str if math_lib and math_lib.is_bool_lib == true then adj_input_str = mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(' ' .. input_str .. ' ',"%s+and%s+"," * "),"[&∧]","*"),"%s+or%s+"," + "),"∨","+"),"%s+not%s+"," - "),"¬","-") end return p.infixToPostfix(adj_input_str, debug_flag) end
local returnMeta = { __tostring = function (this) return tostring(this.value) end } local keep_string = {object=true, ['string']=true, frameArg=true} local without_load = {object=true, ['string']=true, symbols=true} function p.calc_by_postfix(postfix, scope, math_lib, number_Constructer, debug_flag, _error_func) local error_func = error if type(_error_func)==type(noop_func) then error_func = _error_func end if comp_number == nil then comp_number = require("Module:Complex Number") end math = comp_number.math.init() local mathlib, numberConstructer = math_lib or math, number_Constructer or tonumber local local_scope = {} local call_stack = {{}} local calc_stack = {} local dbg_func, do_dbg = mw.log, true if debug_flag ~= true then dbg_func, do_dbg = noop_func,false end
if type(postfix.scope) == type({}) then for pk, pv in pairs(postfix.scope) do scope[pk] = scope[pk] or postfix.scope[pk]end end
if postfix.is_error == true then error_func("計算失敗:"..postfix.error_message, 2) end
for i = 1,#postfix do local it = postfix[i] if it.propetry == "func start" then call_stack[#call_stack + 1] = {} elseif it.propetry == "operator" then local opdata = p.symbol_table[it.name] local to_ass local if_return = false xpcall(function() if it.name == ',' then if calc_stack[#calc_stack-1] ~= ',' and calc_stack[#calc_stack] ~= ',' and #(call_stack[#call_stack]) > 0 then call_stack[#call_stack+1]={} end if calc_stack[#calc_stack-1] == ',' and calc_stack[#calc_stack] == ',' then local call_stack_top_left,call_stack_top_right = {},{} for ij = 1, #(call_stack[#call_stack-1]) do call_stack_top_left[#call_stack_top_left + 1] = (call_stack[#call_stack-1])[ij] end for ij = 1, #(call_stack[#call_stack]) do call_stack_top_right[#call_stack_top_right + 1] = (call_stack[#call_stack])[ij] end local cma_result_left,cma_result_right = p.symbol_table[','].calc( mathlib, unpack( call_stack_top_left ) ), p.symbol_table[','].calc( mathlib, unpack( call_stack_top_right ) ) call_stack[#call_stack] = nil call_stack[#call_stack] = nil local call_stack_count = #call_stack for queue_it = call_stack_count,1,-1 do call_stack[queue_it+1]=call_stack[queue_it]end call_stack[1] = { cma_result_left, cma_result_right } else if calc_stack[#calc_stack-1] ~= ',' then local call_stack_count = #(call_stack[#call_stack]) for queue_it = call_stack_count,1,-1 do (call_stack[#call_stack])[queue_it+1]=(call_stack[#call_stack])[queue_it]end (call_stack[#call_stack])[1] = calc_stack[#calc_stack-1] --(call_stack[#call_stack])[#(call_stack[#call_stack]) + 1] = calc_stack[#calc_stack-1] end if calc_stack[#calc_stack] ~= ',' then (call_stack[#call_stack])[#(call_stack[#call_stack]) + 1] = calc_stack[#calc_stack] end end calc_stack[#calc_stack] = nil; calc_stack[#calc_stack] = ',' elseif opdata.count == 1 then if calc_stack[#calc_stack] == ',' and #call_stack > 0 then local call_stack_top = {} for ij = 1, #(call_stack[#call_stack]) do call_stack_top[#call_stack_top + 1] = (call_stack[#call_stack])[ij] end local cma_result = p.symbol_table[','].calc( mathlib, unpack( call_stack_top ) ) calc_stack[#calc_stack] = opdata.calc(cma_result,mathlib,numberConstructer) call_stack[#call_stack] = calc_stack[#calc_stack] elseif it.name == '⟵' and type(mathlib.mathdef) ~= type(noop_func) then calc_stack = { { ['return'] = true, value=opdata.calc(calc_stack[#calc_stack],mathlib,numberConstructer) } } setmetatable(calc_stack[1],returnMeta) if_return = true else if ((type(calc_stack[#calc_stack]) == type({})) and calc_stack[#calc_stack] or {}).assign == "assign" then local get_data = (local_scope or {})[calc_stack[#calc_stack][1]] if get_data then calc_stack[#calc_stack] = local_scope[calc_stack[#calc_stack][1]] error_func("計算失敗:未知的變數 \"" .. _subst_error_strip(tostring(calc_stack[#calc_stack][1])) .. "\" ",2) end end calc_stack[#calc_stack] = opdata.calc(calc_stack[#calc_stack],mathlib,numberConstructer) end else if it.name ~= '←' then if ((type(calc_stack[#calc_stack]) == type({})) and calc_stack[#calc_stack] or {}).assign == "assign" then local get_data = (local_scope or {})[calc_stack[#calc_stack][1]] if get_data then calc_stack[#calc_stack] = local_scope[calc_stack[#calc_stack][1]] else local try_scope_obj = calc_stack[#calc_stack][1] local try_scope_name = tostring(try_scope_obj) local try_scope = mathlib[try_scope_name] if type(try_scope_obj) == type({}) and try_scope_obj.isObject then try_scope = try_scope_obj.value or try_scope end if try_scope==nil then try_scope = scope[try_scope_name] end if try_scope==nil then try_scope = _G[try_scope_name] end if try_scope==nil and mathlib.noncalculate ~= true and mathlib.ext_loaded ~= true then mathlib = ext_mathlib(mathlib, numberConstructer) try_scope = mathlib[try_scope_name] if use_ext_mathlib ~= true then use_ext_mathlib = true end end if try_scope~=nil then if type(try_scope)==type(noop_func) then calc_stack[#calc_stack] = try_scope_name else calc_stack[#calc_stack] = try_scope end else error_func("計算失敗:未知的變數 \"" .. _subst_error_strip(tostring(calc_stack[#calc_stack][1])) .. "\" " ,2) end end end if ((type(calc_stack[#calc_stack - 1]) == type({})) and calc_stack[#calc_stack - 1] or {}).assign == "assign" then local get_data = (local_scope or {})[calc_stack[#calc_stack - 1][1]] if get_data then calc_stack[#calc_stack - 1] = local_scope[calc_stack[#calc_stack - 1][1]] else local try_scope_obj = calc_stack[#calc_stack - 1][1] local try_scope_name = tostring(try_scope_obj) local try_scope = mathlib[try_scope_name] if type(try_scope_obj) == type({}) and try_scope_obj.isObject then try_scope = try_scope_obj.value or try_scope end if try_scope==nil then try_scope = scope[try_scope_name] end if try_scope==nil then try_scope = _G[try_scope_name] end if try_scope==nil and mathlib.noncalculate ~= true and mathlib.ext_loaded ~= true then mathlib = ext_mathlib(mathlib, numberConstructer) try_scope = mathlib[try_scope_name] if use_ext_mathlib ~= true then use_ext_mathlib = true end end if try_scope~=nil then calc_stack[#calc_stack - 1] = try_scope else error_func("計算失敗:未知的變數 \"" .. _subst_error_strip(tostring(calc_stack[#calc_stack - 1][1])) .. "\" ",2) end end end else if ((type(calc_stack[#calc_stack]) == type({})) and calc_stack[#calc_stack] or {}).assign == "assign" then local get_data = (local_scope or {})[calc_stack[#calc_stack][1]] if get_data then calc_stack[#calc_stack] = local_scope[calc_stack[#calc_stack][1]] else get_data = (scope or {})[calc_stack[#calc_stack][1]] or _G[calc_stack[#calc_stack][1]] or mathlib[calc_stack[#calc_stack][1]] if type(get_data) == type(noop_func) then calc_stack[#calc_stack] = get_data else error_func("計算失敗:未知的變數 \"" .. _subst_error_strip(tostring(calc_stack[#calc_stack][1])) .. "\" ",2) end end end to_ass = calc_stack[#calc_stack - 1] end if (calc_stack[#calc_stack] == ',' or calc_stack[#calc_stack-1] == ',') and #call_stack > 0 then
local cma_result_left,cma_result_right if calc_stack[#calc_stack-1] == ',' and calc_stack[#calc_stack] == ',' then local call_stack_top_left,call_stack_top_right = {},{} for ij = 1, #(call_stack[#call_stack-1]) do call_stack_top_left[#call_stack_top_left + 1] = (call_stack[#call_stack-1])[ij] end for ij = 1, #(call_stack[#call_stack]) do call_stack_top_right[#call_stack_top_right + 1] = (call_stack[#call_stack])[ij] end cma_result_left,cma_result_right = p.symbol_table[','].calc( mathlib, unpack( call_stack_top_left ) ), p.symbol_table[','].calc( mathlib, unpack( call_stack_top_right ) ) calc_stack[#calc_stack - 1] = opdata.calc(cma_result_left ,cma_result_right, mathlib,numberConstructer) call_stack[#call_stack] = nil call_stack[#call_stack] = nil local call_stack_count = #call_stack for queue_it = call_stack_count,1,-1 do call_stack[queue_it+1]=call_stack[queue_it]end call_stack[1] = calc_stack[#calc_stack - 1] else cma_result_left,cma_result_right = calc_stack[#calc_stack - 1]or 0, calc_stack[#calc_stack]or 0 local call_stack_top = {} for ij = 1, #(call_stack[#call_stack]) do call_stack_top[#call_stack_top + 1] = (call_stack[#call_stack])[ij] end local cma_result = p.symbol_table[','].calc( mathlib, unpack( call_stack_top ) ) if calc_stack[#calc_stack-1] == ',' then cma_result_left = cma_result elseif calc_stack[#calc_stack] == ',' then cma_result_right = cma_result end calc_stack[#calc_stack - 1] = opdata.calc(cma_result_left ,cma_result_right, mathlib,numberConstructer) call_stack[#call_stack] = nil local call_stack_count = #call_stack for queue_it = call_stack_count,1,-1 do call_stack[queue_it+1]=call_stack[queue_it]end call_stack[1] = calc_stack[#calc_stack - 1] end else calc_stack[#calc_stack - 1] = opdata.calc(calc_stack[#calc_stack - 1]or 0 ,calc_stack[#calc_stack]or 0,mathlib,numberConstructer) end calc_stack[#calc_stack] = nil end end, function(message) error_func("計算失敗:套用運算子 \"" .. _subst_error_strip(mw.text.trim(it.name)) .. "\" 發生錯誤 \"" .. message .. "\" ",2) end) xpcall(function() (calc_stack[#calc_stack]):clean() end,function(_)end) if it.name == '←' and type(mathlib.mathdef) ~= type(noop_func)then local cantass = "計算失敗:套用運算子 \"" .. _subst_error_strip(mw.text.trim(it.name)) .. "\" 發生錯誤:無法將 \"".. tostring(to_ass[1] or to_ass) .."\" 的值設定為 \"" .. tostring(calc_stack[#calc_stack] ) .. "\" " local check_num = numberConstructer(to_ass[1] or to_ass) if check_num then error_func(cantass,2) elseif local_scope then local_scope[to_ass[1]] = calc_stack[#calc_stack] else error_func(cantass,2)end end if do_dbg == true then dbg_func(it.name, '\t', print_sk(calc_stack,', ') ) end if if_return then break end elseif it.propetry == "func" then local calfunc, functype = mathlib[it.name], type(noop_func) if type(calfunc) ~= functype and type((scope or {})[it.name]) == functype then calfunc = scope[it.name] end if type(calfunc) ~= functype and type(_G[it.name]) == functype then calfunc = _G[it.name] end if type(calfunc) ~= functype and mathlib.noncalculate ~= true and mathlib.ext_loaded ~= true then mathlib = ext_mathlib(mathlib, numberConstructer) calfunc = mathlib[it.name] if use_ext_mathlib ~= true and type(calfunc) == functype then use_ext_mathlib = true end end if type(calfunc) ~= functype and type((local_scope or {})[it.name]) == functype then calfunc = local_scope[it.name] end local is_other_module = false if type(calfunc) ~= functype and p.use_other_module == true then local check_func = mw.text.split(it.name,"AtModule") if #check_func > 1 then xpcall(function() local load_module = require( "Module:" .. check_func[2]) calfunc = load_module[check_func[1]] is_other_module = true end, function(message) error_func("計算失敗:執行函數 \"" .. "Module:" .. check_func[2] .. '#' .. check_func[1] .. "\" 發生錯誤 \"" .. message .. "\" ",2) end) end end local callstr = it.name local ifreturn = false if type(calfunc) == functype then xpcall(function() local call_stack_top = {} for j = 1, #(call_stack[#call_stack]) do if ((type((call_stack[#call_stack])[j] ) == type({})) and (call_stack[#call_stack])[j] or {}).assign == "assign" then local get_data = (local_scope or {})[(call_stack[#call_stack])[j][1]] if get_data then (call_stack[#call_stack])[j] = local_scope[(call_stack[#call_stack])[j][1]] else local try_scope_obj = (call_stack[#call_stack])[j][1] local try_scope_name = tostring(try_scope_obj) local try_scope = mathlib[try_scope_name] if without_load[callstr] then try_scope = try_scope_obj end if type(try_scope_obj) == type({}) and try_scope_obj.isObject then try_scope = try_scope_obj.value or try_scope end if try_scope==nil then try_scope = scope[try_scope_name] end if try_scope==nil then try_scope = _G[try_scope_name] end if try_scope==nil and mathlib.noncalculate ~= true and mathlib.ext_loaded ~= true then mathlib = ext_mathlib(mathlib, numberConstructer) try_scope = mathlib[try_scope_name] if use_ext_mathlib ~= true then use_ext_mathlib = true end end if try_scope~=nil then (call_stack[#call_stack])[j] = try_scope else error_func("計算失敗:未知的變數 \"" .. _subst_error_strip(tostring((call_stack[#call_stack])[j][1])) .. "\" ",2) end end end call_stack_top[#call_stack_top + 1] = (call_stack[#call_stack])[j] end if call_stack_top == ',' or call_stack_top == or call_stack_top == nil then call_stack_top[#call_stack_top + 1] = calc_stack[#calc_stack] end if #call_stack_top > 0 then if do_dbg == true then callstr = callstr .. '(' .. print_sk(call_stack_top,',') .. ')' end local wrap_call_stack_top = call_stack_top if is_other_module then wrap_call_stack_top = {} for k,v in pairs(call_stack_top) do wrap_call_stack_top[k] = tostring(v) end end local calc_result = calfunc( unpack( wrap_call_stack_top ) ) if type(calc_result) == type({}) and calc_result['return'] then calc_result = calc_result.value if type(mathlib.mathdef) ~= type(noop_func) then calc_stack = {calc_result} ifreturn = true end end if type(calc_result) == type() and (not keep_string[callstr]) then calc_result = numberConstructer(calc_result) or calc_result end calc_stack[#calc_stack] = calc_result else if ((type(calc_stack[#calc_stack]) == type({})) and calc_stack[#calc_stack] or {}).assign == "assign" then local get_data = (local_scope or {})[calc_stack[#calc_stack][1]] if get_data then calc_stack[#calc_stack] = local_scope[calc_stack[#calc_stack][1]] else local try_scope_obj = calc_stack[#calc_stack][1] local try_scope_name = tostring(try_scope_obj) local try_scope = mathlib[try_scope_name] if without_load[callstr] then try_scope = try_scope_obj end if type(try_scope_obj) == type({}) and try_scope_obj.isObject then try_scope = try_scope_obj.value or try_scope end if try_scope==nil then try_scope = scope[try_scope_name] end if try_scope==nil then try_scope = _G[try_scope_name] end if try_scope==nil and mathlib.noncalculate ~= true and mathlib.ext_loaded ~= true then mathlib = ext_mathlib(mathlib, numberConstructer) try_scope = mathlib[try_scope_name] if use_ext_mathlib ~= true then use_ext_mathlib = true end end if try_scope~=nil then calc_stack[#calc_stack] = try_scope else error_func("計算失敗:未知的變數 \"" .. _subst_error_strip(tostring(calc_stack[#calc_stack][1])) .. "\" ",2) end end end local wrap_call_stack_top = calc_stack[#calc_stack] if is_other_module then wrap_call_stack_top = tostring(wrap_call_stack_top) end local calc_result = calfunc( wrap_call_stack_top ) if type(calc_result) == type({}) and calc_result['return'] then calc_result = calc_result.value if type(mathlib.mathdef) ~= type(noop_func) then calc_stack = {calc_result} ifreturn = true end end if type(calc_result) == type() and (not keep_string[callstr]) then calc_result = numberConstructer(calc_result) or calc_result end calc_stack[#calc_stack] = calc_result end call_stack[#call_stack] = nil end, function(message) error_func("計算失敗:執行函數 \"" .. _subst_error_strip(it.name) .. "\" 發生錯誤 \"" .. message .. "\" ",2) end) else if it.name == '(' then error_func("計算失敗:未封閉的括號",2) end error_func("計算失敗:無法執行函數 \"" .. _subst_error_strip(it.name) .. "\" ",2) end xpcall(function() (calc_stack[#calc_stack]):clean() end,function(_)end) if do_dbg == true then dbg_func(callstr, '\t', print_sk(calc_stack,', ') ) end if ifreturn then break end else local get_data = numberConstructer(it.name) if get_data == nil then get_data = numberConstructer((scope or {})[it.name]) or numberConstructer(_G[it.name]) or numberConstructer(mathlib[it.name]) or numberConstructer(it.name) end if get_data == nil then get_data={it.name,assign="assign"}end calc_stack[#calc_stack + 1] = get_data xpcall(function() (calc_stack[#calc_stack]):clean() end,function(_)end) if do_dbg == true then dbg_func(it.name, '\t', print_sk(calc_stack,', ') ) end end end if #calc_stack == 1 then local checker = calc_stack[#calc_stack] if ((type(calc_stack[#calc_stack]) == type({})) and calc_stack[#calc_stack] or {}).assign == "assign" then checker = tostring(calc_stack[#calc_stack][1]) end if checker == ',' then for call_i=#call_stack,1,-1 do for call_j=1,#(call_stack[call_i]) do if ((type(call_stack[call_i][call_j]) == type({})) and call_stack[call_i][call_j] or {}).assign == "assign" then local get_data = (local_scope or {})[call_stack[call_i][call_j][1]] if get_data then call_stack[call_i][call_j] = local_scope[call_stack[call_i][call_j][1]] else call_stack[call_i][call_j] = tostring(call_stack[call_i][call_j][1]) end end if checker == ',' then checker = else checker = checker..', ' end checker = checker .. tostring(call_stack[call_i][call_j]) end end end return checker elseif #calc_stack > 1 then local check_number_data = print_sk(calc_stack,', ') if mw.text.trim(check_number_data) == then error_func("計算失敗:缺少運算子和運算數,無法運算",2) elseif not mw.ustring.find(check_number_data,',') then --"缺少運算子且只有一個運算數" 那就返回運算數,不視為錯誤 --error_func("計算失敗:預期為二元運算,但缺少運算子且只有一個運算數 \"".. check_number_data .."\",無法運算",2) return numberConstructer(check_number_data) else error_func("計算失敗:缺少運算子,數字 [" .. check_number_data .. "] 無法運算",2) end end return numberConstructer(0) end
function p.infixToPostfix(input_str, debug_flag) local str, index, num_list = input_str, 0, {}; local dbg_func, do_dbg = mw.log, true if debug_flag ~= true then dbg_func, do_dbg = noop_func,false end local flag_logging = {} local flag_logging_list = { logic_func = "replace logic operators...", round_and_return = "replace round and return operators...", equal_operator = "replace equal operators...", scientific = "replace scientific symbols...", imaginary_unit = "replace imaginary units..." } if mw.ustring.find(str,"[xXnN]?[aAoOnN][nNrRoO][dDtTrR]?([^%a%(])") then str = mw.ustring.gsub(str,"([%A])[aA][nN][dD]([^%a%(])","%1 & %2") str = mw.ustring.gsub(str,"([%A])[nN][aA][nN][dD]([^%a%(])","%1 ↑ %2")
str = mw.ustring.gsub(str,"([%A])[oO][rR]([^%a%(])","%1 | %2") str = mw.ustring.gsub(str,"([%A])[nN][oO][rR]([^%a%(])","%1 ↓ %2")
str = mw.ustring.gsub(str,"([%A])[xX][oO][rR]([^%a%(])","%1 ⊕ %2") str = mw.ustring.gsub(str,"([%A])[xX][nN][oO][rR]([^%a%(])","%1 ⇔ %2")
str = mw.ustring.gsub(str,"([%A])[nN][oO][tT]([^%a%(])","%1 ~ %2") str = mw.ustring.gsub(str,"^not([^%a%(])","~ %1") flag_logging.logic_func = true end if mw.ustring.find(str,"[rR][oOeE][uUtT][nNuU][dDrR][nN]?([^%a%(])") then str = mw.ustring.gsub(str,"([%A])[rR][oO][uU][nN][dD]([^%a%(])","%1 ≃ %2") str = mw.ustring.gsub(str,"([%A])[rR][eE][tT][uU][rR][nN]([^%a%(])","%1 ⟵ %2") str = mw.ustring.gsub(str,"^%s*[rR][eE][tT][uU][rR][nN]([^%a%(])","⟵ %1") flag_logging.round_and_return = true end local feq1,feq2,fsci,fsi,fsj,fsk,fpi,fpj,fpk = 0,0,0,0,0,0,0,0,0 str, feq1 = mw.ustring.gsub(str,"([><=!~@])=",function(str) return ({['>']='≥',['<']='≤',['~']='≠',['!']='≠',['=']='=',['@']='←'})[str] end) str, feq2 = mw.ustring.gsub(str,"([%a%d]+)%s*([%+%-−%*×⋅/÷%%%^&↑%|↓⊕⇔])=", "%1 ← %1 %2 ") str, fsci = mw.ustring.gsub(str,"([%+%-]?)(%d*%.?%d+)e([%+%-]?%d+)([ijk]?)",function(n_sign,n_num,n_pow,ijk) return n_sign.."("..n_num.."*10^("..n_pow.."))"..((ijk~=nil and ijk~=)and(' ˙ '..ijk) or) end)
if mw.ustring.find(str,"[ijk]") then str, fsi = mw.ustring.gsub(str,"(%a)i","%1I") str, fsj = mw.ustring.gsub(str,"(%a)j","%1J") str, fsk = mw.ustring.gsub(str,"(%a)k","%1K") str, fpi = mw.ustring.gsub(str,"i(%a)","I%1") str, fpj = mw.ustring.gsub(str,"j(%a)","J%1") str, fpk = mw.ustring.gsub(str,"k(%a)","K%1") end local result = mw.ustring.gsub(str,"%d*%.?%d*%s*[ijk]?", function(b) if b ~= nil and mw.text.trim(b) ~= then index = index + 1 num_list[#num_list + 1] = b return ' ' .. tostring(index) end return end ); if ((fpi or 0)+(fsi or 0)) ~= 0 then result = mw.ustring.gsub(result,"I","i") end if ((fpj or 0)+(fsj or 0)) ~= 0 then result = mw.ustring.gsub(result,"J","j") end if ((fpk or 0)+(fsk or 0)) ~= 0 then result = mw.ustring.gsub(result,"K","k") end -------------------------------------------------------- if do_dbg then if ((feq1 or 0)+(feq2 or 0)) ~= 0 then flag_logging.equal_operator = true end if (fsci or 0) ~= 0 then flag_logging.scientific = true end if ((fpi or 0)+(fsi or 0)+(fpj or 0)+(fsj or 0)+(fpk or 0)+(fsk or 0)) ~= 0 then flag_logging.imaginary_unit = true end for flag_name,flag in pairs(flag_logging)do if flag == true and flag_logging_list[flag_name] then dbg_func(flag_logging_list[flag_name])end end end -------------------------------------------------------- local str2, index, azid, func_list = result, 0, , {}; local result = mw.ustring.gsub(str2,"[π°]", function(b) if b ~= nil and mw.text.trim(b) ~= then num_list[#num_list + 1] = b return ' ˙ ' .. tostring(#num_list) .. ' ' end end ); result = mw.ustring.gsub(result,"%a[%a%d]*%s*%(?", function(b) if b ~= nil and mw.text.trim(b) ~= then if mw.ustring.find(b,"%(") then local func_name = mw.ustring.match(b,"%a[%a%d]*") if func_name ~= nil and mw.text.trim(func_name) ~= then index, azid = index + 1, numberToAZ(index) func_list[azid] = func_name return ' ' .. azid .. ' ' end else num_list[#num_list + 1] = b return ' ' .. tostring(#num_list) .. ' ' end end return end ); for i=1,#num_list do num_list[i] = mw.ustring.gsub(num_list[i],"%s+",) end if do_dbg then dbg_func(mw.ustring.format('result string is "%s"', result)) end local mid_expr = stringToTable(result) mid_expr[#mid_expr + 1] = "$END" local stack, postfix = Template:Name="$END",elements=0, {} for i = 1,#mid_expr do local it = mid_expr[i] if it == "$END" then while #stack > 0 and stack[#stack].name ~= "$END" do local psymbol_tablestackstacknamecount,_fl = -1 _fl,psymbol_tablestackstacknamecount = xpcall(function()return p.symbol_table[stack[#stack].name].count end,noop_func) if (stack[#stack] or {elements=0}).elements < (psymbol_tablestackstacknamecount or -1) then local error_message = p.symbol_table[stack[#stack].name].name.."運算子需要"..p.symbol_table[stack[#stack].name].count.."個運算數,但只找到"..stack[#stack].elements.."個運算數" if do_dbg == true then dbg_func("== \""..stack[#stack].name.."\" "..error_message) end return {is_error=true, error_message=error_message} end postfix[#postfix + 1] = {name=stack[#stack].name, propetry=stack[#stack].propetry} stack[#stack] = nil --pop if stack[#stack] then stack[#stack].elements = (stack[#stack].elements or 0) + 1 end end if do_dbg == true then dbg_func("結束",'\t', print_sk(postfix,' ') ,'\t',print_sk(stack)) end elseif mw.ustring.match(it,"[%a%(]") then stack[#stack + 1] = {name=it,elements=0,propetry='func'} if do_dbg == true then dbg_func(it, "括號開始",'\t', print_sk(postfix,' ') ,'\t',print_sk(stack)) end if func_list[it] ~= nil then postfix[#postfix + 1] = {name=' ', propetry="func start"} end elseif p.symbol_table[it] ~= nil and p.symbol_table[it].propetry == "op" then local op_it = p.symbol_table[it] local op_ls = p.symbol_table[mid_expr[i-1]] local flag = mw.ustring.match(mid_expr[i-1] or ,"[%a%(]") if (mid_expr[i-1] or '娜娜奇') == '娜娜奇' then flag = false end if ( op_ls or (i == 1) or flag ) and op_it.multp == true then stack[#stack + 1] = {name=it .. ' ',elements=0,propetry='operator'} else while p.symbol_table[(stack[#stack]or{name=noop_func}).name] and p.symbol_table[(stack[#stack]or{name=noop_func}).name].priority and p.symbol_table[stack[#stack].name].ppriority >= p.symbol_table[it].priority do if stack[#stack].elements < p.symbol_table[stack[#stack].name].count then local error_message = p.symbol_table[stack[#stack].name].name.."運算子需要"..p.symbol_table[stack[#stack].name].count.."個運算數,但只找到"..stack[#stack].elements.."個運算數" if do_dbg == true then dbg_func("== \""..stack[#stack].name.."\" "..error_message) end return {is_error=true, error_message=error_message} end postfix[#postfix + 1] = {name=stack[#stack].name, propetry=stack[#stack].propetry} stack[#stack] = nil --pop stack[#stack].elements = (stack[#stack].elements or 0) + 1 end stack[#stack + 1] = {name=it,elements=1, propetry='operator'} end if do_dbg == true then dbg_func(it, "運算子",'\t', print_sk(postfix,' ') ,'\t',print_sk(stack)) end elseif mw.ustring.match(it,"%d+") then postfix[#postfix + 1] = {name=num_list[tonumber(it)] or ("N" .. it), propetry="number"} stack[#stack].elements = (stack[#stack].elements or 0) + 1 if do_dbg == true then dbg_func(it, "數字",'\t', print_sk(postfix,' ') ,'\t',print_sk(stack)) end elseif it == ')' then local flag = mw.ustring.match(stack[#stack].name,"[%a%(]") while flag == nil do --遇 ) 輸出至 ( if stack[#stack].name ~= "$END" then if stack[#stack].elements < p.symbol_table[stack[#stack].name].count then local error_message = p.symbol_table[stack[#stack].name].name.."運算子需要"..p.symbol_table[stack[#stack].name].count.."個運算數,但只找到"..stack[#stack].elements.."個運算數" if do_dbg == true then dbg_func("== \""..stack[#stack].name.."\" "..error_message) end return {is_error=true, error_message=error_message} end postfix[#postfix + 1] = {name=stack[#stack].name, propetry=stack[#stack].propetry} stack[#stack] = nil --pop stack[#stack].elements = (stack[#stack].elements or 0) + 1 end flag = mw.ustring.match(stack[#stack].name,"[%a%(]") end if mw.ustring.match(stack[#stack].name,"%a") then if stack[#stack].name ~= "$END" then postfix[#postfix + 1] = {name=func_list[stack[#stack].name] or stack[#stack].name, propetry=stack[#stack].propetry} end end if stack[#stack].name == "$END" then local error_message = "未預料的反括號" if do_dbg == true then dbg_func("=="..error_message) end postfix.is_error=true postfix.error_message = error_message else stack[#stack] = nil --pop end if stack[#stack] then stack[#stack].elements = ((stack[#stack] or {}).elements or 0) + 1 end if do_dbg == true then dbg_func(it, "結束括號",'\t', print_sk(postfix,' ') ,'\t',print_sk(stack))end end end
return postfix
end
function p.ifNumeric(frame) local result, can_math, should_math, input_math_lib, input_to_number local error_count = 0 local error_flag = xpcall(function() result, can_math, should_math, input_math_lib, input_to_number = p._preCalculate(frame, function()error_count = error_count + 1 end) end,noop_func) error_flag = (not error_flag) or (error_count > 0)
local args if frame == mw.getCurrentFrame() then -- We're being called via #invoke. The args are passed through to the module -- from the template page, so use the args that were passed into the template. args = getArgs(frame) --frame.args else -- We're being called from another module or from the debug console, so assume -- the args are passed in directly. args = frame end local body = if args[2]==nil and args[3]==nil then return error_flag and or '1' end if error_flag then body = args[3] or body else body = args[2] or body end
return body end
function p.calcExpr(frame) local result, can_math, should_math, input_math_lib, input_to_number local error_count = 0 local bool_value = 0 local error_message local error_flag = xpcall(function() result, can_math, should_math, input_math_lib, input_to_number = p._preCalculate(frame, function(msg) error_message = error_message or msg error_count = error_count + 1 end) bool_value = input_math_lib.abs(result) end,noop_func) error_flag = (not error_flag) or (error_count > 0)
local args if frame == mw.getCurrentFrame() then -- We're being called via #invoke. The args are passed through to the module -- from the template page, so use the args that were passed into the template. args = getArgs(frame) --frame.args else -- We're being called from another module or from the debug console, so assume -- the args are passed in directly. args = frame end local body = if args[2]==nil and args[3]==nil then if error_message~=nil and error_flag then error(error_message, 2) end return result end if bool_value > 1e-14 and (not error_flag) then body = args[2] or body else body = args[3] or body end
return body end
function p.isReal(frame)
local args
local result, can_math, should_math, input_math_lib, input_to_number local error_count = 0 local non_real_value = 0 local error_flag = xpcall(function() result, can_math, should_math, input_math_lib, input_to_number = p._preCalculate(frame, function()error_count = error_count + 1 end) non_real_value = input_math_lib.abs(input_math_lib.nonRealPart(result)) end,noop_func) error_flag = (not error_flag) or (error_count > 0)
if frame == mw.getCurrentFrame() then -- We're being called via #invoke. The args are passed through to the module -- from the template page, so use the args that were passed into the template. args = getArgs(frame) --frame.args else -- We're being called from another module or from the debug console, so assume -- the args are passed in directly. args = frame end local body = if non_real_value > 1e-14 or error_flag then body = args[3] or body else body = args[2] or body end
return body end
--表達式輸出為<math></math>支援 p.tagmath={ matheq=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'=','=') end, mathneq=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'≠','\\neq') end, mathdef=function(op1,op2) local that, oper_id = p.tagmath.toTagMath(op2), if op2.lowoperator ~= '(' and op2.lowoperator ~= then that.value = "\\left( " .. that.value .. "\\right) "end that.lowoperator = oper_id return p.tagmath.apply_binary_operator(op1,that,'←','\\overset{\\underset{\\mathrm{def}}{}}{=}') end, mathmapsto=function(op1,op2) local that_op1, oper_id = p.tagmath.toTagMath(op1), if op1.lowoperator ~= '(' and op1.lowoperator ~= then that_op1.value = "\\left( " .. that_op1.value .. "\\right) "end that_op1.lowoperator = oper_id return p.tagmath.apply_binary_operator(that_op1,op2,'↦','\\mapsto') end, mathfuncdef=function(op1,op2) local that_op1, oper_id = p.tagmath.toTagMath(op1), that_op1.lowoperator = oper_id return p.tagmath.apply_binary_operator(that_op1,op2,':',':') end, mathset=function(op1,op2) local that_op1, oper_id, that = p.tagmath.toTagMath(op1), if op1.lowoperator ~= '(' and op1.lowoperator ~= then that_op1.value = "\\left( " .. that_op1.value .. "\\right) "end that_op1.lowoperator = oper_id that, oper_id = p.tagmath.toTagMath(op2), if op2.lowoperator ~= '(' and op2.lowoperator ~= then that.value = "\\left( " .. that.value .. "\\right) "end that.lowoperator = oper_id return p.tagmath.apply_binary_operator(that_op1,that,'⇽','\\gets') end, mathcomma=function(...) local get_all_arg = {...} if #get_all_arg == 1 then return get_all_arg[1] end if #get_all_arg == 0 then return end local merge_data = for itj=1,#get_all_arg do if merge_data ~= then merge_data = merge_data .. ' ,\\, ' end merge_data = merge_data .. tostring(get_all_arg[itj]) end local that_op1, oper_id = p.tagmath.toTagMath(merge_data), that_op1.value = "\\left( " .. that_op1.value .. "\\right) " that_op1.lowoperator = oper_id return that_op1 end, mathsemicolon=function(op1,op2) local check_empty = mw.ustring.gsub(tostring(op1),'%s',) if check_empty =="{}" or check_empty == then return op2 end return p.tagmath.apply_binary_operator(op1,op2,';',';\\,') end, mathtimes=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'⋅','\\, ') end, mathlt=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'<','<') end, mathgt=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'>','>') end, mathlteq=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'≤','\\leq') end, mathgteq=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'≥','\\geq') end, mathand=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'&','\\land') end, mathnand=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'↑','\\uparrow') end, mathor=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'|','\\lor') end, mathnor=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'↓','\\downarrow') end, mathxor=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'⊕','\\oplus') end, mathxnor=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'⇔','\\leftrightarrow') end, mathnot=function(this) local that, oper_id = p.tagmath.toTagMath(this), if this.lowoperator ~= '(' and this.lowoperator ~= then that.value = "\\left( " .. that.value .. "\\right) "end that.lowoperator = oper_id that.value = "\\lnot" .. that.value return that end, mathreturn=function(this) local that, oper_id = p.tagmath.toTagMath(this), that.lowoperator = oper_id that.value = "\\text{return}\\," .. that.value return that end, pow=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'^','^',false,true) end, div=function(op1,op2) local left, right = p.tagmath.toTagMath(op1), p.tagmath.toTagMath(op2) left.lowoperator = left.value = "\\frac{ " .. left.value .. " }{ " .. right.value .. "}" return left end, sqrt=function(op1,op2) local left = p.tagmath.toTagMath(op1) if op2 ~= nil then local right = p.tagmath.toTagMath(op2) left.value = "\\sqrt[ " .. right.value .. " ]{ " .. left.value .. "}" else left.value = "\\sqrt{ " .. left.value .. " }" end left.lowoperator = return left end, dot=function(op1,op2) return p.tagmath.apply_binary_operator(op1,op2,'*','\\cdot') end, exp=function(this) local that, oper_id = p.tagmath.toTagMath(this), that.lowoperator = oper_id that.value = " e^{ " .. that.value .. "} " return that end, log=function(op1,op2) local left, right, vals, log_symbol if op2 ~= nil then right, left = p.tagmath.toTagMath(op1), p.tagmath.toTagMath(op2) vals = "_{" .. right.value .. "}" log_symbol = "log " else left, vals = p.tagmath.toTagMath(op1), log_symbol = "ln " end if left.lowoperator ~= '(' and left.lowoperator ~= then left.value = "\\left( " .. left.value .. "\\right) "end left.lowoperator = left.value = '\\' .. log_symbol .. vals .. left.value return left end, abs=function(this) local that, oper_id = p.tagmath.toTagMath(this), that.lowoperator = oper_id that.value = "\\left\\vert " .. that.value .. "\\right\\vert " return that end, conjugate=function(this) local that, oper_id = p.tagmath.toTagMath(this), that.lowoperator = oper_id that.value = "\\overline{ " .. that.value .. " } " return that end, floor=function(this) local that, oper_id = p.tagmath.toTagMath(this), that.lowoperator = oper_id that.value = "\\left\\lfloor " .. that.value .. "\\right\\rfloor " return that end, ceil=function(this) local that, oper_id = p.tagmath.toTagMath(this), that.lowoperator = oper_id that.value = "\\left\\lceil " .. that.value .. "\\right\\rceil " return that end, binomial=function(n,k) local that, oper_id = p.tagmath.toTagMath(n), local that_k = p.tagmath.toTagMath(k) or {value=} that.lowoperator = oper_id that.value = "\\binom {" .. that.value .. "}{" .. that_k.value .. '}' return that end, min=function(...) local this_list, oper_id = {...}, local that = p.tagmath.toTagMath(this_list[1]) for i=2,#this_list do local it_item = p.tagmath.toTagMath(this_list[i]) that.value = that.value .. ', \\,' .. it_item.value end that.value = "\\left( " .. that.value .. "\\right) " that.lowoperator = oper_id that.value = "\\min {" .. that.value .. '}' return that end, factorial=function(this) local that, oper_id = p.tagmath.toTagMath(this), if this.lowoperator ~= '(' and this.lowoperator ~= then that.value = "\\left( " .. that.value .. "\\right) "end that.lowoperator = oper_id that.value = that.value .. "!" return that end, ele=function(this) local that, oper_id = p.tagmath.toTagMath(this), if this.lowoperator ~= '(' and this.lowoperator ~= then that.value = "\\left( " .. that.value .. "\\right) "end that.lowoperator = oper_id that.value = "\\,e_{" .. that.value .. "}" return that end, norm=function(n,_p) local that, oper_id = p.tagmath.toTagMath(n), local that_p = p.tagmath.toTagMath(_p) or {value=} that.lowoperator = oper_id that.value = "\\left \\|" .. that.value .. "\\right \\|" if _p then that.value = that.value .."_{" .. that_p.value .. '}' end return that end, transpose=function(this) local that, oper_id = p.tagmath.toTagMath(this), if this.lowoperator ~= '(' and this.lowoperator ~= then that.value = "\\left( " .. that.value .. "\\right) "end that.lowoperator = oper_id that.value = that.value .. "^{\\mathrm{T}}" return that end, identity=function(this) local that, oper_id = p.tagmath.toTagMath(this), that.lowoperator = oper_id that.value = "I_{" .. that.value .. "}" return that end, row=function(...) local get_all_arg = {...} if #get_all_arg == 1 then return get_all_arg[1] end if #get_all_arg == 0 then return end local merge_data = for itj=1,#get_all_arg do if merge_data ~= then merge_data = merge_data .. ' & ' end merge_data = merge_data..'{'..tostring(get_all_arg[itj])..'}' end local that_op1, oper_id = p.tagmath.toTagMath(merge_data), that_op1.lowoperator = oper_id return that_op1 end, matrix=function(...) local get_all_arg = {...} if #get_all_arg == 1 then local that_op1, oper_id = p.tagmath.toTagMath(get_all_arg[1]), that_op1.value = "\\begin{bmatrix} " .. that_op1.value .. "\\end{bmatrix} " that_op1.lowoperator = oper_id return that_op1 end if #get_all_arg == 0 then return end local merge_data = for itj=1,#get_all_arg do if merge_data ~= then merge_data = merge_data .. ' \\\\\n' end merge_data = merge_data .. tostring(get_all_arg[itj]) end local that_op1, oper_id = p.tagmath.toTagMath(merge_data), that_op1.value = "\\begin{bmatrix} " .. that_op1.value .. "\\end{bmatrix} " that_op1.lowoperator = oper_id return that_op1 end, mathform=function(inputdata) return inputdata end, cofactor=function(this, p_i, q_j) local that, oper_id = p.tagmath.toTagMath(this), '(' if (this.lowoperator ~= '(') and (this.lowoperator ~= ) then that.value = "\\left( " .. that.value .. "\\right) " end that.lowoperator = oper_id that.value = '\\mathrm{cof} ' .. that.value
if p_i~= nil and q_j~= nil then local pi_math = p.tagmath.toTagMath(p_i) local qj_math = p.tagmath.toTagMath(q_j) that.value = "\\left( " .. that.value .. "\\right) _ {{"..pi_math.value.."},\\,{"..qj_math.value.."}}" end return that end, cof=function(this, p_i, q_j)return p.tagmath.cofactor(this, p_i, q_j)end, ["if"]=function(expr, true_expr, false_expr) return p.tagmath._ifelse_func(false, expr, true_expr, false_expr) end, iff=function(expr, true_expr, false_expr) return p.tagmath._ifelse_func(true, expr, true_expr, false_expr) end, ifelse=function(...) return p.tagmath._ifelse_func(false, ...) end, ifelsef=function(...) return p.tagmath._ifelse_func(true, ...) end, _ifelse_func=function(is_func, ...) local exprlist = {...} local last_else = #exprlist % 2 == 1 local max_num = (last_else and (#exprlist - 1) or #exprlist) / 2 local that, oper_id = p.tagmath.toTagMath(), for i=1,max_num do if i > 1 then that.value = that.value .. ' \\\\ ' end local expr = p.tagmath.toTagMath(exprlist[i * 2 - 1]) local expr_true = p.tagmath.toTagMath(exprlist[i * 2]) if is_func then expr.value = expr.value:gsub("\\mapsto","") expr_true.value = expr_true.value:gsub("\\mapsto","") end that.value = that.value .. mw.ustring.format("{%s}, & \\text{if }{%s}", expr_true.value, expr.value) end if last_else then local expr_false = p.tagmath.toTagMath(exprlist[#exprlist]) if is_func then expr_false.value = expr_false.value:gsub("\\mapsto","") end that.value = that.value .. mw.ustring.format(" \\\\ {%s}, & \\text{otherwise}", expr_false.value) end that.lowoperator = oper_id that.value = mw.ustring.format("\\begin{cases} %s \\end{cases}", that.value) return that end, symbols=function(name) local symbolname = p.tagmath.toTagMath(name) local symbolresult = require('Module:Complex_Number/Functions')._symbols(mw.text.trim(symbolname.value,"%{%}\t\r\n\f ")) if symbolresult then return p.tagmath.toTagMath(symbolresult) end return p.tagmath.apply_function("symbols", name) end, object=function(obj,...) local objlist = {...} local objname = p.tagmath.toTagMath(obj) for i=1,#objlist do local to_add = p.tagmath.toTagMath(objlist[i]).value if objlist[i].lowoperator ~= '(' and objlist[i].lowoperator ~= then to_add = "\\left( " .. to_add .. "\\right) "end objname.value = objname.value .. '.' .. to_add end objname.value = "\\text{" .. objname.value .. "}" return objname end, ['string']=function(...) local strlist = {...} local str = p.tagmath.toTagMath() for i=1,#strlist do str.value = str.value .. p.tagmath.toTagMath(strlist[i]).value end str.value = "{}^\\shortparallel\\text{" .. str.value .. "}^\\shortparallel" return str end, call=function(_func, ...) local that_func = p.tagmath.toTagMath(_func) local that_args = p.tagmath.mathcomma(...) local is_inner_func = mw.ustring.find(tostring(that_func.value),"\\mapsto") if #({...}) <= 1 and type(is_inner_func) == type(nil) then that_args.value = "\\left( " .. that_args.value .. "\\right) "end if type(is_inner_func) ~= type(nil) then that_func.value = that_func.value .. ' \\gets ' end that_args.value = that_func.value..that_args.value return that_args end, diff=function(_expr, _value) local that, oper_id = p.tagmath.toTagMath(_value), 'MINOP' local that_expr = p.tagmath.toTagMath(_expr) local data_start, data_end = mw.ustring.find(tostring(that_expr.value),"\\mapsto") local var_data = mw.ustring.sub(tostring(that_expr.value),1,(data_start or 1)-1) local expr_data = mw.ustring.sub(tostring(that_expr.value),(data_end or 0)+1,-1) var_data = mw.ustring.gsub(var_data,"^%s*%{","") expr_data = mw.ustring.gsub(expr_data,"%}%s*$","") local group_flag = mw.ustring.find(expr_data,"[%+%-]") if not group_flag then expr_data = mw.ustring.gsub(expr_data,"\\right%)%s*%}%s*$","") expr_data = mw.ustring.gsub(expr_data,"^%s*%{\\left%(","") end local check_ijk = mw.ustring.find(tostring(var_data),"[ijkIJK]t") if (not data_start) or check_ijk then var_data = mw.text.trim(var_data) == and "x" or var_data var_data = mw.ustring.gsub(var_data,"([ijkIJK])t","%1") expr_data = mw.ustring.gsub(expr_data,"([ijkIJK])t","%1") end that.value = mw.ustring.format("\\left.\\frac{d\\,{%s}}{d{%s}}\\right|_{{%s}={%s}}", expr_data, var_data, var_data, that.value) that.lowoperator = oper_id return that end, integral=function(_value, _b, _expr) local that, b, oper_id = p.tagmath.toTagMath(_value), p.tagmath.toTagMath(_b), 'MINOP' local that_expr = p.tagmath.toTagMath(_expr) local data_start, data_end = mw.ustring.find(tostring(that_expr.value),"\\mapsto") local var_data = mw.ustring.sub(tostring(that_expr.value),1,(data_start or 1)-1) local expr_data = mw.ustring.sub(tostring(that_expr.value),(data_end or 0)+1,-1) var_data = mw.ustring.gsub(var_data,"^%s*%{","") expr_data = mw.ustring.gsub(expr_data,"%}%s*$","") local group_flag = mw.ustring.find(expr_data,"[%+%-]") if not group_flag then expr_data = mw.ustring.gsub(expr_data,"\\right%)%s*%}%s*$","") expr_data = mw.ustring.gsub(expr_data,"^%s*%{\\left%(","") end local check_ijk = mw.ustring.find(tostring(var_data),"[ijkIJK]t") if (not data_start) or check_ijk then var_data = mw.text.trim(var_data) == and "x" or var_data var_data = mw.ustring.gsub(var_data,"([ijkIJK])t","%1") expr_data = mw.ustring.gsub(expr_data,"([ijkIJK])t","%1") end that.value = mw.ustring.format("\\int_{%s}^{%s} %s\\,d{%s}", that.value, b.value, expr_data, var_data) that.lowoperator = oper_id return that end, ['∫']=function(_value, _b, _expr) return p.tagmath.integral(_value, _b, _expr) end, limit=function(_value, _way, _expr) local that, oper_id = p.tagmath.toTagMath(_value), 'MINOP' local check_way = mw.ustring.gsub(tostring(_way),'[\{\}%s]',) check_way = tonumber(check_way) local way_text = check_way > 1e-8 and "+" or ( check_way < -1e-8 and "-" or ) local that_expr = p.tagmath.toTagMath(_expr) local data_start, data_end = mw.ustring.find(tostring(that_expr.value),"\\mapsto") local var_data = mw.ustring.sub(tostring(that_expr.value),1,(data_start or 1)-1) local expr_data = mw.ustring.sub(tostring(that_expr.value),(data_end or 0)+1,-1) var_data = mw.ustring.gsub(var_data,"^%s*%{","") expr_data = mw.ustring.gsub(expr_data,"%}%s*$","") local group_flag = mw.ustring.find(expr_data,"[%+%-]") if not group_flag then expr_data = mw.ustring.gsub(expr_data,"\\right%)%s*%}%s*$","") expr_data = mw.ustring.gsub(expr_data,"^%s*%{\\left%(","") end local check_ijk = mw.ustring.find(tostring(var_data),"[ijkIJK]t") if (not data_start) or check_ijk then var_data = mw.text.trim(var_data) == and "x" or var_data var_data = mw.ustring.gsub(var_data,"([ijkIJK])t","%1") expr_data = mw.ustring.gsub(expr_data,"([ijkIJK])t","%1") end that.value = mw.ustring.format("\\lim_{{%s} \\to {%s}^{%s}}{%s}", var_data, that.value, way_text, expr_data) that.lowoperator = oper_id return that end, summation=function(_begin, _end, _expr) local that, oper_id = p.tagmath.toTagMath(_begin), 'MINOP' local that_begin = p.tagmath.toTagMath(_begin) local that_end = p.tagmath.toTagMath(_end) local that_expr = p.tagmath.toTagMath(_expr) local data_start, data_end = mw.ustring.find(tostring(that_expr.value),"\\mapsto") local var_data = mw.ustring.sub(tostring(that_expr.value),1,(data_start or 1)-1) local expr_data = mw.ustring.sub(tostring(that_expr.value),(data_end or 0)+1,-1) var_data = mw.ustring.gsub(var_data,"^%s*%{","") expr_data = mw.ustring.gsub(expr_data,"%}%s*$","") local group_flag = mw.ustring.find(expr_data,"[%+%-]") if not group_flag then expr_data = mw.ustring.gsub(expr_data,"\\right%)%s*%}%s*$","") expr_data = mw.ustring.gsub(expr_data,"^%s*%{\\left%(","") end local check_ijk = mw.ustring.find(tostring(var_data),"[ijkIJK]t") if (not data_start) or check_ijk then var_data = mw.text.trim(var_data) == and "i" or var_data var_data = mw.ustring.gsub(var_data,"([ijkIJK])t","%1") expr_data = mw.ustring.gsub(expr_data,"([ijkIJK])t","%1") end that.value = mw.ustring.format("\\sum_{{%s}={%s}}^{%s} {%s}", var_data, that_begin.value, that_end.value, expr_data) that.lowoperator = oper_id return that end, product=function(_begin, _end, _expr) local that, oper_id = p.tagmath.toTagMath(_begin), 'MINOP' local that_begin = p.tagmath.toTagMath(_begin) local that_end = p.tagmath.toTagMath(_end) local that_expr = p.tagmath.toTagMath(_expr) local data_start, data_end = mw.ustring.find(tostring(that_expr.value),"\\mapsto") local var_data = mw.ustring.sub(tostring(that_expr.value),1,(data_start or 1)-1) local expr_data = mw.ustring.sub(tostring(that_expr.value),(data_end or 0)+1,-1) var_data = mw.ustring.gsub(var_data,"^%s*%{","") expr_data = mw.ustring.gsub(expr_data,"%}%s*$","") local group_flag = mw.ustring.find(expr_data,"[%+%-]") if not group_flag then expr_data = mw.ustring.gsub(expr_data,"\\right%)%s*%}%s*$","") expr_data = mw.ustring.gsub(expr_data,"^%s*%{\\left%(","") end local check_ijk = mw.ustring.find(var_data,"[ijkIJK]t") if (not data_start) or check_ijk then var_data = mw.text.trim(var_data) == and "i" or var_data var_data = mw.ustring.gsub(var_data,"([ijkIJK])t","%1") expr_data = mw.ustring.gsub(expr_data,"([ijkIJK])t","%1") end that.value = mw.ustring.format("\\prod_{{%s}={%s}}^{%s} {%s}", var_data, that_begin.value, that_end.value, expr_data) that.lowoperator = oper_id return that end, divisorsigma=function(op1,op2) local left, right, vals, sigma_symbol right, left = p.tagmath.toTagMath(op1), p.tagmath.toTagMath(op2) if op2 == nil then left = p.tagmath.toTagMath("") vals = "" else vals = "_{" .. right.value .. "}" end sigma_symbol = "sigma " left.value = "\\left( " .. ((op2 == nil) and right.value or left.value) .. "\\right) " left.lowoperator = left.value = '\\' .. sigma_symbol .. vals .. left.value return left end, hide=function(this)return""end, exprs=function(...) local input_args = {...} return p.tagmath.mathcomma(unpack(input_args)) end, lastexpr=function(...) local input_args = {...} return input_args[#input_args] end, equalexpr=function(...) local get_all_arg = {...} if #get_all_arg == 1 then return get_all_arg[1] end if #get_all_arg == 0 then return end local merge_data = for itj=1,#get_all_arg do if merge_data ~= then merge_data = merge_data .. '=' end merge_data = merge_data .. tostring(get_all_arg[itj]) end local that_op1, oper_id = p.tagmath.toTagMath(merge_data), that_op1.lowoperator = oper_id return that_op1 end, inverse=function(this) local that, oper_id = p.tagmath.toTagMath(this), if this.lowoperator ~= '(' and this.lowoperator ~= then that.value = "\\left( " .. that.value .. "\\right) "end that.lowoperator = oper_id that.value = that.value .. "^{-1}" return that end, re=function(this) local that, oper_id = p.tagmath.toTagMath(this), if this.lowoperator ~= '(' and this.lowoperator ~= then that.value = "\\left( " .. that.value .. "\\right) "end that.lowoperator = oper_id that.value = "\\operatorname{Re}" .. that.value return that end, im=function(this) local that, oper_id = p.tagmath.toTagMath(this), if this.lowoperator ~= '(' and this.lowoperator ~= then that.value = "\\left( " .. that.value .. "\\right) "end that.lowoperator = oper_id that.value = "\\operatorname{Im}" .. that.value return that end, apply_function=function(func_name, ...) local para_info = {...} local this = #para_info == 1 and para_info[1] or p.tagmath.mathcomma(...) local that, oper_id = p.tagmath.toTagMath(this), '(' local math_ext_funcs={["minimum"]="\\min",["maximum"]="\\max",["sin"]="\\sin",["cos"]="\\cos",["tan"]="\\tan",["sec"]="\\sec",["csc"]="\\csc",["cot"]="\\cot", ["asin"]="\\arcsin",["acos"]="\\arccos",["atan"]="\\arctan",["asec"]="\\operatorname{arcsec}",["acsc"]="\\operatorname{arccsc}",["acot"]="\\operatorname{arccot}", ["sinh"]="\\sinh",["cosh"]="\\cosh",["tanh"]="\\tanh",["sech"]="\\operatorname{sech}",["csch"]="\\operatorname{csch}",["coth"]="\\coth", ["asinh"]="\\operatorname{arcsinh}",["acosh"]="\\operatorname{arccosh}",["atanh"]="\\operatorname{arctanh}",["asech"]="\\operatorname{arcsech}",["acsch"]="\\operatorname{arccsch}",["acoth"]="\\operatorname{arccoth}", ["scalarPartQuaternion"]="\\operatorname{Scalar}",["vectorPartQuaternion"]="\\operatorname{Vector}", ["sgn"]="\\sgn",["gamma"]="\\Gamma",["cis"]="\\operatorname{cis}",["eulerphi"]="\\varphi",["LambertW"]="W", ["gcd"]="\\gcd",["lcm"]="\\operatorname{lcm}",["round"]="\\operatorname{round}",["arg"]="\\arg",["trunc"]="\\operatorname{trunc}", ["gd"]="\\operatorname{gd}",["arcgd"]="\\operatorname{arcgd}",["cogd"]="\\operatorname{cogd}", ["diag"]="\\operatorname{diag}",["det"]="\\det",["determinant"]="\\det", ["adj"]="\\operatorname{adj}",["adjoint"]="\\operatorname{adj}" } local need_comm={["gamma"]=true,["eulerphi"]=true,["LambertW"]=true} local math_format_funcs={ ["factorial"]="%s!" } if ((#para_info == 1) and (this.lowoperator ~= '(') and (this.lowoperator ~= )) or ((#para_info == 1) and (math_ext_funcs[func_name] == nil or need_comm[func_name] == true) and (this.lowoperator == ))then that.value = "\\left( " .. that.value .. "\\right) " end
that.lowoperator = oper_id if math_format_funcs[func_name] then that.value = mw.ustring.format(math_format_funcs[func_name], that.value) else that.value = (math_ext_funcs[func_name] or func_name) .. ' ' .. that.value end return that end, apply_binary_operator = function(op1, op2, oper_id, oper_math,left_no,right_no) local left, right = p.tagmath.toTagMath(op1), p.tagmath.toTagMath(op2) if left.lowoperator ~= '(' and left.lowoperator ~= and ((p.symbol_table[left.lowoperator] and p.symbol_table[left.lowoperator].ppriority and p.symbol_table[left.lowoperator].ppriority < p.symbol_table[oper_id].priority)) then if not left_no then left.value = "\\left( " .. left.value .. "\\right) " end left.lowoperator = '(' end
if right.lowoperator ~= '(' and right.lowoperator ~= and ((p.symbol_table[right.lowoperator] and p.symbol_table[right.lowoperator].ppriority and p.symbol_table[right.lowoperator].ppriority < p.symbol_table[oper_id].priority)) then if not right_no then right.value = "\\left( " .. right.value .. "\\right) " end right.lowoperator = '(' end
local low_operator = oper_id if ((p.symbol_table[left.lowoperator] or {ppriority=0}).ppriority or 0) ~= 0 then if p.symbol_table[left.lowoperator].ppriority < p.symbol_table[low_operator].ppriority then low_operator = left.lowoperator end end if ((p.symbol_table[right.lowoperator] or {ppriority=0}).ppriority or 0) ~= 0 then if p.symbol_table[right.lowoperator].ppriority < p.symbol_table[low_operator].ppriority then low_operator = right.lowoperator end end left.lowoperator = low_operator left.value = "{ {" .. left.value .. '}' .. oper_math .. '{' .. right.value .. "} }" return left end, TagMathMeta = { __add = function (op1, op2) return p.tagmath.apply_binary_operator(op1,op2,'+','+') end, __sub = function (op1, op2) return p.tagmath.apply_binary_operator(op1,op2,'-','-') end, __mul = function (op1, op2) return p.tagmath.apply_binary_operator(op1,op2,'*',"\\times ") end, __div = function (op1, op2) return p.tagmath.apply_binary_operator(op1,op2,'/',"\\div ") end, __tostring = function (this) return this.value end, __unm = function (this) local that, oper_id = p.tagmath.toTagMath(this), "- " if this.lowoperator ~= '(' and this.lowoperator ~= then that.value = "\\left( " .. that.value .. "\\right) "end that.lowoperator = oper_id that.value = "-{ " .. that.value .. "}" return that end, __eq = function (op1, op2)return p.tagmath.tagMathString(op1).value == p.tagmath.tagMathString(op2).value end, }, toTagMath = function(tagMathString) if type(tagMathString) == type({}) and tagMathString.numberType == "latex" then return tagMathString end if type(tagMathString) == type(nil) then return nil end local math_ext_const={["pi"]="\\pi",["π"]="\\pi",["°"]="{}^{\\circ}",["inf"]="\\infty",["nan"]="\\mathrm{NaN}",["nil"]="",["null"]=""} local TagMath = {} if (type(tagMathString) == type({})) and tagMathString.value ~= nil and tagMathString.lowoperator ~= nil then TagMath = {value=tagMathString.value,lowoperator=tagMathString.lowoperator} else TagMath = {} TagMath.value = math_ext_const[tagMathString] or tagMathString TagMath.lowoperator = end setmetatable(TagMath,p.tagmath.TagMathMeta) TagMath.numberType = "latex" return TagMath end, init = function() if comp_number == nil then comp_number = require("Module:Complex Number") end p.tagmath.zero = p.tagmath.toTagMath(0) p.tagmath.one = p.tagmath.toTagMath(1) p['nil'] = p.tagmath.toTagMath("") p.tagmath.noncalculate=true p.tagmath[0],p.tagmath[1] = p.tagmath.zero,p.tagmath.one new_meta = getmetatable( p.tagmath ) or {} new_meta.__index = function (this, func_name) return function(...)return p.tagmath.apply_function(func_name, ...)end end setmetatable(p.tagmath,new_meta) p.tagmath.numberType = comp_number._numberType p.tagmath.constructor = p.tagmath.toTagMath return p.tagmath end }
return p