Editing
Module:Complex Number/Calculate
Jump to navigation
Jump to search
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
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 = {{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
Summary:
Please note that all contributions to wiki may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
Wiki:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Template used on this page:
Template:Name="$END",elements=0
(
edit
)
Navigation menu
Personal tools
Not logged in
Talk
Contributions
Create account
Log in
Namespaces
Page
Discussion
English
Views
Read
Edit
View history
More
Search
Navigation
Main page
Recent changes
Random page
Help about MediaWiki
Tools
What links here
Related changes
Special pages
Page information