模組:Complex Number/Calculate/Operators

local p={}
local noop_func = function()end
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
function p.fill_function(in_ftable, final_scope)
	for k,v in pairs(in_ftable) do 
		if type(v) ~= type(noop_func) then final_scope['*$'..k]=in_ftable[k]final_scope[k]=function(...)return final_scope['*$'..k]:func(...)end end 
	end
	return final_scope
end
function p.fill_scope(final_scope, math_lib, number_Constructer, debug_flag, calc_func)
	for k,v in pairs(final_scope) do if mw.ustring.sub(k,1,2)=="*$" then final_scope[k].local_scopes = final_scope end end
	final_scope['^$math_lib']=math_lib
	final_scope['^$number_Constructer']=number_Constructer
	final_scope['^$debug_flag']=debug_flag
	final_scope['^$calc_func']=calc_func
	return final_scope
end
function p.function_preload(input_str_o,in_ftable, math_lib, number_Constructer, debug_flag, nocalc_func, just_fix)
	local input_str = mw.ustring.gsub(input_str_o,'⇽','←') 
	if mw.ustring.find(input_str,"↦") then else return input_str end
	local func = noop_func
	local old_str = input_str
	local outer_old_str = input_str
	if just_fix == true or type(math_lib.toTagMath)==type(func) then
		repeat
			outer_old_str = input_str
			repeat
				old_str = input_str
				local repl_named = type(math_lib.toTagMath)==type(func)and(function(name,vars,contxs,tail)
					local func_contx = mw.ustring.format("%s⇐((%s)⇰(%s))", name,mw.ustring.gsub(vars,',',mw.ustring.char(0x201A)),mw.ustring.gsub(contxs,';+','∷'):gsub(',+','█'))
					if mw.text.trim(tail or '')=='(' then 
						func_contx = '(' .. func_contx .. ')⇽' .. tail
					elseif mw.text.trim(tail or '')~='' then 
						func_contx = func_contx .. '∷'
					end
					return func_contx
				end) or "%1⇐((%2)⇰(%3))∷"
				input_str = mw.ustring.gsub(input_str,"(%a+)%s*:([%a%s,]+)↦([^↦:]-);(%s*[%(,]?)", repl_named)
			until input_str == old_str
			local repl_unnamed =type(math_lib.toTagMath)==type(func)and(function(vars,contxs)
				return mw.ustring.format("((%s)⇰(%s))⇽",mw.ustring.gsub(vars,',',mw.ustring.char(0x201A)),
					mw.ustring.gsub(contxs,';','∷'):gsub(',','█')
				)
			end) or "((%1)⇰(%2))⇽"
			input_str = mw.ustring.gsub(input_str,":([%a%s,]+)↦([^↦:]-);",repl_unnamed)
		until input_str == outer_old_str
		input_str = mw.ustring.gsub(input_str,"⇰","↦")
		input_str = mw.ustring.gsub(input_str,"∷",";")
		input_str = mw.ustring.gsub(input_str,"█",",")
		input_str = mw.ustring.gsub(input_str,"⇐",":")
		input_str = mw.ustring.gsub(input_str,mw.ustring.char(0x201A),',')
		input_str = mw.text.trim(input_str,"\t\r\n\f ⇽")
		input_str = mw.ustring.gsub(input_str,"⇽(%s*[,;%)])","%1")
		return input_str
	end
	local ftable = type(in_ftable) ~= type({"table"}) and {} or in_ftable
	local function make_fobj(par,inner)
		local n_par = mw.text.trim(mw.ustring.gsub(par,'[%s,;:]+', ','),"\t\r\n\f ,")
		local make_obj = {par=mw.text.split(n_par,','),inner=inner}
		make_obj.postfix = nocalc_func(inner, math_lib, number_Constructer, debug_flag)
		function make_obj:func(...)
			local make_args = {...}
			local back_up_scope = {}
			for i=1,#self.par do if make_args[i] then 
				back_up_scope[self.par[i]] = self.local_scopes[self.par[i]]
				self.local_scopes[self.par[i]] = make_args[i]
			end end
			if self.local_scopes['^$debug_flag'] == true then mw.log("call "..self.functionName) end
			local result = self.local_scopes['^$calc_func'](
				self.postfix, 
				self.local_scopes, 
				self.local_scopes['^$math_lib'], 
				self.local_scopes['^$number_Constructer'], 
				self.local_scopes['^$debug_flag']
			)
			for i=1,#self.par do if make_args[i] then 
				self.local_scopes[self.par[i]] = back_up_scope[self.par[i]]
			end end
			if mw.ustring.find(tostring(result),',') then 
				result = tostring(result)
				local tail_data = mw.text.split(result,',')
				for i=#tail_data,1,-1 do result = mw.text.trim(tail_data[i])if result ~= '' then break end end
			end
			if self.local_scopes['^$debug_flag'] == true then mw.log(self.functionName.." return "..tostring(result)) end
			return result
		end
		return make_obj
	end
	local function func_repl(par,inner)
		ftable[#ftable + 1] = make_fobj(par,inner)
		ftable[#ftable].functionName = '#'..#ftable
		local func_index = numberToAZ(#ftable)
		ftable['function'..func_index] = ftable[#ftable]
		return ' function'..func_index..' '
	end
	local function func_repl_n(name,par,inner)
		ftable[name] = make_fobj(par,inner)
		ftable[name].functionName = name
		return ' '..name..' '
	end
	repeat
		outer_old_str = input_str
		repeat
			old_str = input_str
			input_str = mw.ustring.gsub(input_str,"(%a+)%s*:([%a%s,]+)↦([^↦:]-);",func_repl_n)
		until input_str == old_str
		input_str = mw.ustring.gsub(input_str,":([%a%s,]+)↦([^↦:]-);",func_repl)
	until input_str == outer_old_str
	return input_str, ftable
end

p.symbol_table = {
		['+'] = { propetry="op", multp = true, count = 2, 
			name="加法",title="加法",example="7 + 3",description="計算兩數之和",
			priority=9, ppriority=9, calc=function(a,b,c,d)return d(a)+d(b) end},
		["+ "] = { propetry="op", count = 1, 
			name="正號",title="正數",example="+7",description="表達一正數",
			priority=14, ppriority=14, calc=function(a,c,d)return d(a) end},
		['-'] = { propetry="op", multp = true, count = 2, 
			name="減法",title="減法",example="7 - 3",description="計算兩數之差",
			priority=9, ppriority=9, calc=function(a,b,c,d)return d(a)-d(b) end},
		["- "] = { propetry="op", count = 1, 
			name="負號",title="负数",example="-7",description="計算一數的相反數",
			priority=14, ppriority=14, calc=function(a,c,d)return -d(a) end},
		['−'] = { propetry="op", multp = true, count = 2, 
			name="減法",title="減法",example="7 − 3",description="計算兩數之差",
			priority=9, ppriority=9, calc=function(a,b,c,d)return d(a)-d(b) end},
		["− "] = { propetry="op", count = 1, 
			name="負號",title="负数",example="−7",description="計算一數的相反數",
			priority=14, ppriority=14, calc=function(a,c,d)return -d(a) end},
		['*'] = { propetry="op", multp = true, count = 2, 
			name="乘法",title="乘法",example="7 * 3",description="計算兩數之乘積",
			priority=10, ppriority=10, calc=function(a,b,c,d)return d(a)*d(b) end},
		["* "] = { propetry="op", count = 1, 
			name="共軛複數",title="共轭复数",example="*(7+3i)",description="計算一數的共軛複數",
			priority=14, ppriority=14, calc=function(a,c,d) if type(c.conjugate)==type(noop_func) then return c.conjugate(d(a))else return d(a)end end},
		['×'] = { propetry="op", multp = true, count = 2, 
			name="乘法",title="乘法",example="7 × 3",description="計算兩數之乘積",
			priority=10, ppriority=10, calc=function(a,b,c,d)return d(a)*d(b) end},
		--隱藏符號的乘法
		['⋅'] = { propetry="op", count = 2, 
			name="係數",title="系数",example="2⋅π",description="表達一數的係數",
			priority=10, ppriority=10, calc=function(a,b,c,d)if type(c.mathtimes)==type(noop_func) then return c.mathtimes(d(a),d(b)) end return d(a)*d(b)end},
		--處理單位的內部符號
		['˙'] = { propetry="op", private=true, multp = true, count = 2, priority=10, ppriority=10, calc=function(a,b,c,d)if type(c.mathtimes)==type(noop_func) then return c.mathtimes(d(a),d(b)) end return d(a)*d(b)end},["˙ "] = { propetry="op", private=true, count = 1, priority=14, ppriority=14, calc=function(a,c,d) return d(a) end},
		--優先序處理的內部符號
		['MINOP'] = { propetry="op", private=true, multp = true, count = 2, priority=-999, ppriority=-999 },
		['MAXOP'] = { propetry="op", private=true, multp = true, count = 2, priority=999, ppriority=999 },
		['/'] = { propetry="op", count = 2, 
			name="除法",title="除法",example="7 / 3",description="計算兩數相除之商",
			priority=10, ppriority=10, calc=function(a,b,c,d)return d(a)/d(b) end},
		['÷'] = { propetry="op", count = 2, 
			name="除法",title="除法",example="7 ÷ 3",description="計算兩數相除之商",
			priority=10, ppriority=10, calc=function(a,b,c,d)return d(a)/d(b) end},
		['%'] = { propetry="op", count = 2, 
			name="取餘數",title="带余除法",example="7 % 3",description="計算兩數相除之餘數",
			priority=10, ppriority=10, calc=function(a,b,c,d)return d(a)%d(b) end},
		['≃'] = { propetry="op", count = 2, 
			name="数值修约",title="数值修约",example="7.3 ≃ 1",description="計算將一數数值修约至指定位數",
			priority=8, ppriority=8, calc=function(a,b,c,d)return c.round(d(a),d(b)) end},
		['^'] = { propetry="op", count = 2, 
			name="冪",title="冪",example="7 ^ 3",description="計算兩數之冪運算",
			priority=12, ppriority=11, calc=function(a,b,c,d)return c.pow(d(a),d(b)) end},
		[','] = { propetry="op", count = 2, 
			name="數組",title="数组",example="7, 3",description="產生數組供多元函數使用",
			priority=1, ppriority=1, calc=function(c,...) if type(c.mathcomma)==type(noop_func) then return c.mathcomma(...) end error("此處不支援此種運算")end },
		['='] = { propetry="op", count = 2, 
			name="邏輯相等",title="相等",example="7 = 3",description="兩數是否相等",
			priority=3, ppriority=3, calc=function(a,b,c,d)return type(c.matheq)==type(noop_func)and c.matheq(d(a),d(b))or d( (c.abs(d(a)-d(b)) < 1e-14) and 1 or 0)end},
		['≠'] = { propetry="op", count = 2, 
			name="邏輯不相等",title="不等",example="7 ≠ 3",description="兩數是否不相等",
			priority=3, ppriority=3, calc=function(a,b,c,d)return type(c.mathneq)==type(noop_func)and c.mathneq(d(a),d(b))or d( (c.abs(d(a)-d(b)) > 1e-14)and 1 or 0)end},
		['←'] = { propetry="op", count = 2, 
			name="數值指派",title="變數",example="x ← 7;x",description="給予變數數值",
			priority=7, ppriority=7, calc=function(a,b,c,d)return type(c.mathdef)==type(noop_func)and c.mathdef(d(a),d(b))or b end},
		['⟵'] = { propetry="op", count = 1, 
			name="返回值",title="Return語句",example="⟵7;8",description="返回數值",
			priority=2, ppriority=2, calc=function(a,c,d)return type(c.mathreturn)==type(noop_func)and c.mathreturn(d(a))or a end},
		--處理函數的內部符號
		['⇽'] = { propetry="op", private=true, count = 2, priority=12, ppriority=12, calc=function(a,b,c,d)return type(c.mathset)==type(noop_func)and c.mathset(d(a),d(b))or b end},
		['↦'] = { propetry="op", count = 2, 
			name="函數映射",title="函數",example=":x,y↦x^2+y^2;(5,2)",description="給予函數定義",
			priority=12, ppriority=12, calc=function(a,b,c,d)if type(c.mathmapsto)==type(noop_func) then return c.mathmapsto(d(a),d(b)) end error("此處不支援此種運算子")end},
		[':'] = { propetry="op", count = 2, 
			name="構成函數",example="f:x↦x^2;(5)",description="冒號(<code>:</code>)為定義函<span></span>數時區隔函<span></span>數的名稱與函<span></span>數的主體,而冒號(<code>:</code>)與分號(<code>;</code>)的區間構成一個函<span></span>數的定義。在冒號左邊的內容為函<span></span>數的名稱,在冒號右邊的內容為函<span></span>數的內容。若函<span></span>數沒有名稱也需要輸寫冒號。",
			priority=7, ppriority=7, calc=function(a,b,c,d)if type(c.mathfuncdef)==type(noop_func) then return c.mathfuncdef(d(a),d(b)) end error("函數語法錯誤")end},
		[';'] = { propetry="op", count = 2, 
			name="運算式分隔",title="分號",example="7 ; 3",description="分隔兩運算式,結果將取最後一個分號後的結果",
			priority=1, ppriority=1, calc=function(a,b,c,d)return type(c.mathsemicolon)==type(noop_func)and c.mathsemicolon(d(a),d(b))or b end},
		['>'] = { propetry="op", count = 2, 
			name="邏輯大於",title="不等號",example="7 > 3",description="比較兩數大小",
			priority=6, ppriority=6, calc=function(a,b,c,d)
			if type(c.mathgt)==type(noop_func) then return c.mathgt(d(a),d(b)) end
			if c.abs(c.nonRealPart(d(a))) > 1e-14 or c.abs(c.nonRealPart(d(b))) > 1e-14 then return 0 end
			return d(c.re(d(a))>c.re(d(b))and 1 or 0)
		end},
		['<'] = { propetry="op", count = 2, 
			name="邏輯小於",title="不等號",example="7 < 3",description="比較兩數大小",
			priority=6, ppriority=6, calc=function(a,b,c,d)
			if type(c.mathlt)==type(noop_func) then return c.mathlt(d(a),d(b)) end
			if c.abs(c.nonRealPart(d(a))) > 1e-14 or c.abs(c.nonRealPart(d(b))) > 1e-14 then return 0 end
			return d(c.re(d(a))<c.re(d(b))and 1 or 0)
		end},
		['≥'] = { propetry="op", count = 2, 
			name="邏輯大於等於",title="不等號",example="7 ≥ 3",description="比較兩數大小",
			priority=6, ppriority=6, calc=function(a,b,c,d)
			if type(c.mathgteq)==type(noop_func) then return c.mathgteq(d(a),d(b)) end
			if c.abs(c.nonRealPart(d(a))) > 1e-14 or c.abs(c.nonRealPart(d(b))) > 1e-14 then return 0 end
			return d(c.re(d(a))>=c.re(d(b))and 1 or 0)
		end},
		['≤'] = { propetry="op", count = 2, 
			name="邏輯小於等於",title="不等號",example="7 ≤ 3",description="比較兩數大小",
			priority=6, ppriority=6, calc=function(a,b,c,d)
			if type(c.mathlteq)==type(noop_func) then return c.mathlteq(d(a),d(b)) end
			if c.abs(c.nonRealPart(d(a))) > 1e-14 or c.abs(c.nonRealPart(d(b))) > 1e-14 then return 0 end
			return d(c.re(d(a))<=c.re(d(b))and 1 or 0)
		end},
		['&'] = { propetry="op", count = 2, 
			name="邏輯且",title="逻辑与",example="(1=1) & (1=2)",description="兩邏輯是否皆為真",
			priority=5, ppriority=5, calc=function(a,b,c,d)
			if type(c.mathand)==type(noop_func) then return c.mathand(d(a),d(b)) end
			return d(((c.abs(d(a)) > 1e-14) and (c.abs(d(b)) > 1e-14))and 1 or 0)
		end},
		['∧'] = { propetry="op", count = 2, 
			name="邏輯且",title="逻辑与",example="(1=1) & (1=2)",description="兩邏輯是否皆為真",
			priority=5, ppriority=5, calc=function(a,b,c,d)
			if type(c.mathand)==type(noop_func) then return c.mathand(d(a),d(b)) end
			return d(((c.abs(d(a)) > 1e-14) and (c.abs(d(b)) > 1e-14))and 1 or 0)
		end},
		['↑'] = { propetry="op", count = 2, 
			name="邏輯與非",title="谢费尔竖线",example="(1=1) ↑ (1=2)",description="兩邏輯是否不全為真",
			priority=5, ppriority=5, calc=function(a,b,c,d)
			if type(c.mathnand)==type(noop_func) then return c.mathnand(d(a),d(b)) end
			return d((not((c.abs(d(a)) > 1e-14) and (c.abs(d(b)) > 1e-14)))and 1 or 0)
		end},
		['|'] = { propetry="op", count = 2, 
			name="邏輯或",title="逻辑或",example="(1=1) | (1=2)",description="兩邏輯是否有一者為真",
			priority=4, ppriority=4, calc=function(a,b,c,d)
			if type(c.mathor)==type(noop_func) then return c.mathor(d(a),d(b)) end
			return d(((c.abs(d(a)) > 1e-14) or (c.abs(d(b)) > 1e-14))and 1 or 0)
		end},
		['∨'] = { propetry="op", count = 2, 
			name="邏輯或",title="逻辑或",example="(1=1) | (1=2)",description="兩邏輯是否有一者為真",
			priority=4, ppriority=4, calc=function(a,b,c,d)
			if type(c.mathor)==type(noop_func) then return c.mathor(d(a),d(b)) end
			return d(((c.abs(d(a)) > 1e-14) or (c.abs(d(b)) > 1e-14))and 1 or 0)
		end},
		['↓'] = { propetry="op", count = 2, 
			name="邏輯或非",title="逻辑或非",example="(1=1) ↓ (1=2)",description="兩邏輯是否全為假",
			priority=4, ppriority=4, calc=function(a,b,c,d)
			if type(c.mathnor)==type(noop_func) then return c.mathnor(d(a),d(b)) end
			return d((not((c.abs(d(a)) > 1e-14) or (c.abs(d(b)) > 1e-14)))and 1 or 0)
		end},
		['⊕'] = { propetry="op", count = 2, 
			name="邏輯異或",title="逻辑异或",example="(1=1) ⊕ (1=2)",description="兩邏輯是否相異",
			priority=4, ppriority=4, calc=function(a,b,c,d)
			if type(c.mathxor)==type(noop_func) then return c.mathxor(d(a),d(b)) end
			return d(( ((c.abs(d(a)) > 1e-14) or (c.abs(d(b)) > 1e-14)) and (not((c.abs(d(a)) > 1e-14) and (c.abs(d(b)) > 1e-14))) )and 1 or 0)
		end},
		['⇔'] = { propetry="op", count = 2, 
			name="邏輯若且唯若",title="当且仅当",example="(1=1) ⇔ (1=2)",description="兩邏輯是否相同",
			priority=4, ppriority=4, calc=function(a,b,c,d)
			if type(c.mathxnor)==type(noop_func) then return c.mathxnor(d(a),d(b)) end
			return d(((c.abs(d(a)) > 1e-14) == (c.abs(d(b)) > 1e-14))and 1 or 0)
		end},
		['~'] = { propetry="op", multp = true, count = 2, 
			name="邏輯非",title="逻辑非",example="~(1=2)",description="邏輯否定",
			priority=13, ppriority=13, calc=function(a,b,c,d)
			if type(c.mathnot)==type(noop_func) then return c.mathnot(d(b)) end
			return d((not(c.abs(d(b)) > 1e-14))and 1 or 0)
		end},
		['~ '] = { propetry="op", count = 1, 
			name="邏輯非",title="逻辑非",example="~(1=2)",description="邏輯否定",
			priority=13, ppriority=13, calc=function(a,c,d)
			if type(c.mathnot)==type(noop_func) then return c.mathnot(d(a)) end
			return d((not(c.abs(d(a)) > 1e-14))and 1 or 0)
		end},
}
return p