本页使用了标题或全文手工转换
被永久保护的模块

模組:Complex Number/Calculate

维基百科,自由的百科全书
跳到导航 跳到搜索
文档图示 模块文档[查看] [编辑] [历史] [清除缓存]

本模組定義了一些數學運算的結構與邏輯。

使用方法

項目 語法 說明 範例
數字的表達
實數
+或-實數值
科學記號
+或-實數值e+或-科學記號值
含單位的數
+或-實數值單位
含常數單位
任何數值表達式常數或單位的表達式
數字的表達可分為實數表達、科學記號和含單位的數。
  • 實數表達即一般的實數;
  • 科學記號為一實數緊接著一個e和一個整數,例如實數值e實數值則代表實數值×10實數值
  • 另一個表達方式為一個實數值緊接著一個複變單位或角度單位,例如2i表示兩倍的虛數單位。此表達式不能與科學記號一同使用。能使用的單位包括ijk°π。其餘需使用運算子來表達。
  • +2.735→2.735
  • -2735e-3→-2.735
  • 2.735i→2.735i
  • -180°-3.1415926535898
四則運算與冪運算 運算式運算符運算式 2+3*5^2→77
函數(參數1,參數2...) 调用现有函 factorial(5)→120
多組運算 運算式1;運算式2 僅會顯示最後一組運算的結果 2+3;2*3→6
變數定義 變數名稱運算式 x←5;x→5
數定義 函數名稱:參數1,參數2...函數運算式; 數的語法為以名稱起始並以冒號區隔函數名稱與定義(函數名稱可留空,但冒號不能省去),整個語法要以分號(;結尾。位於映射符號(前方為函數的變數或參數,後方為函數主體定義,即f : x f(x);。函數可以有多個變數,但僅能有單個輸出,即。同時函數語法亦不支援嵌套,即函數定義內不能包含另一個函數的定義,但可以分開定義再行組合 f:x↦x^2+1;(0);f(5) →26
運算符優先序調整 (運算式要優先計算的運算符運算式)運算符運算式
  • 2+3*5→17
  • (2+3)*5→25


運算符

語法 名稱 元數 說明 優先 範例 效果 math輸出
基礎算术
+
2
計算兩數之和
9
7 + 3
10
-
2
計算兩數之差
9
7 - 3
4
*
2
計算兩數之乘積
10
7 * 3
21
×
2
計算兩數之乘積
10
7 × 3
21
/
2
計算兩數相除之商
10
7 / 3
2.3333333333333
÷
2
計算兩數相除之商
10
7 ÷ 3
2.3333333333333
%
2
計算兩數相除之餘數
10
7 % 3
1
^
2
計算兩數之冪運算
12
7 ^ 3
343
e
2
當e左鄰一實數、右鄰一整數時,則為科學記號,以256e-3為例,其代表的結果為。要注意的是左邊的數必為單一實數、右邊的數必為整數,可為負數,且中間不能有空格。
12.3e4
123000
()
1
改變運算優先順序
2*(2+3)
10
数论
+
1
表達一正數
14
+7
7
-
1
計算一數的相反數
14
-7
-7
%
2
計算兩數相除之餘數
10
7 % 3
1
数值修约
round
2
round 的運算子模式,會將一數四捨五入到指定的位數。使用時須與前後文各間隔至少一個空格
8
π round 6
3.141593
代数
2
表達一數的係數
10
2⋅π
6.2831853071796
2
給予變數數值
7
x ← 7;x
7
2
給予函數定義
12
:x,y↦x^2+y^2;(5,2)
29
,
2
產生數組供多元函數使用
1
7, 3
7, 3
複變
*
1
計算一數的共軛複數
14
*(7+3i)
7-3i
i
1
表達純虛數
3i
3i
布尔代数
&
2
兩邏輯是否皆為真
5
(1=1) & (1=2)
0
2
兩邏輯是否不全為真
5
(1=1) ↑ (1=2)
1
|
2
兩邏輯是否有一者為真
4
(1=1) | (1=2)
1
2
兩邏輯是否全為假
4
(1=1) ↓ (1=2)
0
2
兩邏輯是否相異
4
(1=1) ⊕ (1=2)
1
2
兩邏輯是否相同
4
(1=1) ⇔ (1=2)
0
~
1
邏輯否定
13
~(1=2)
1
and
2
邏輯且的字母模式。使用時須與前後文各間隔至少一個空格
5
(1=1) and (1=2)
0
nand
2
邏輯與非的字母模式。使用時須與前後文各間隔至少一個空格
5
(1=1) nand (1=2)
1
or
2
邏輯或的字母模式。使用時須與前後文各間隔至少一個空格
4
(1=1) or (1=2)
1
nor
2
邏輯或非的字母模式。使用時須與前後文各間隔至少一個空格
4
(1=1) nor (1=2)
0
xor
2
邏輯異或的字母模式。使用時須與前後文各間隔至少一個空格
4
(1=1) xor (1=2)
1
xnor
2
邏輯若且唯若的字母模式。使用時須與前後文各間隔至少一個空格
4
(1=1) xnor (1=2)
0
not
1
邏輯非的字母模式。使用時須與前後文各間隔至少一個空格
13
not (1=2)
1
二元关系
>
2
比較兩數大小
6
7 > 3
1
<
2
比較兩數大小
6
7 < 3
0
2
比較兩數大小
6
7 ≥ 3
1
2
比較兩數大小
6
7 ≤ 3
0
=
2
兩數是否相等
3
7 = 3
0
2
兩數是否不相等
3
7 ≠ 3
1
技術性
;
2
分隔兩運算式,結果將取最後一個分號後的結果
1
7 ; 3
3
三角函
°
1
用於表示角度單位的符號。
0.05235987755983
π
1
表示圓周率。
9.4247779607694

常數

語法 名稱 別名 說明 數值 math輸出
e 自然底數 自然對數函數的底數 2.718281828459
i 虛數單位 表達純虛數 i
j 四元數單位j 表達純四元數虛數j j
k 四元數單位k 表達純四元數虛數k k
nan 非數 用於表示數學上未定義的數值,或計算發生錯誤的數值。
° 角度單位 用於表示角度單位的符號。 0.017453292519943
π 圓周率 pi 表示圓周率。 3.1415926535898
ω 艾森斯坦整数單位 表達艾森斯坦整数單位。 -0.5+0.86602540378444i

語法 名稱 參數
數量
說明 範例 效果 math輸出
基礎算术
div
2
用於在math輸出時,以分數的形式顯示
div(7,3)
2.3333333333333
dot
2
計算兩數的內積。
dot(7,3)
21
pow
2
計算兩數之冪運算
pow(7,3)
343
数论
gcd
不定
計算多個數的最大公因數。
gcd(7,21)
7
digits
1
取得整數的位數個數
digits(7321)
4
初等函
abs
1
計算一數與原點的歐幾里得距離
abs(-3)
3
log
自然對數
1
log(e)
1
log
2
log(2,16)
4
sgn
1
sgn(-7)
-1
sqrt
1
sqrt(16)
4
inverse
1
inverse(7)
0.14285714285714
exp
1
exp(π⋅i)
-1
数值修约
floor
1
floor(7.3)
7
ceil
1
ceil(7.3)
8
round
3
對一數進行四捨五入。第一參數為欲四捨五入的數字;第二參數為欲四捨五入的位數;第三參數為當數值修約底數非十進制時的底數。
round(π,6)
3.141593
trunc
2
對一數取截尾函數。第一參數為欲截尾的數字;第二參數為欲截尾的位數。
trunc(π,6)
3.141592
統計
average
不定
average(7,3,2,1)
3.25
geoaverage
不定
geoaverage(7,3,2,1)
2.5457298950218
maximum
不定
maximum(7,3,2,1)
7
minimum
不定
minimum(7,3,2,1)
1
selectlist
不定
selectlist(2,7,3,2,1)
3
代数
summation
3
計算以函數表達之數列的總和。第一參數為數列首項;第二參數為數列末項;第三參數為用以表達數列的函
summation(1,5,:x↦x^2;)
55
product
3
計算以函數表達之數列的連乘積。第一參數為數列首項;第二參數為數列末項;第三參數為用以表達數列的函
product(1,5,:it↦it;)
120
<不定>
不定
调用自行定义的函数,這些函數通常是。以f:x↦x^2;;f(5)為例,其中f:x↦x^2;定義了函,並调用了函。函數的語法為以名稱起始並以冒號區隔函數名稱與定義(函數名稱可留空,但冒號不能省去),整個語法要以分號(;)結尾。位於映射符號()前方為函數的變數或參數,後方為函數主體定義。函數可以有多個變數,但僅能有單個輸出;同時函數語法亦不支援嵌套,即函數定義內不能包含另一個函數的定義,但可以分開定義再行組合。
f:x↦x^2;,f(5)
f, 25
ele
1
取得特定代數空間(如四元數)的第n個單位元,如ele(2)即e₂=j
ele(2)
j
微積分
limit
3
計算一函數在x=x₀的極限。需注意此運算為估計,運算精度約僅有7位有效數字。第一參數為x₀;第二參數為逼近方向,1表示右極限、-1表示左極限、0表示一般的極限,此時若極限不存在則返回nan;第三參數為欲求極限的函數。
limit(0,1,:x↦div(x,x);)
1
diff
2
計算一函數在x=x₀的導數。需注意此運算為估計,運算精度約僅有7位有效數字。第一參數為欲求導數的函數x₀;第二參數為x₀。
diff(cos,div(2⋅pi,3))
-0.86602540379001
複變
re
1
re(7+3i)
7
im
1
im(7+3i)
3
nonRealPart
1
nonRealPart(7+3i+2j+k)
3i+2j+k
scalarPartQuaternion
1
scalarPartQuaternion(7+3i+2j+k)
7
vectorPartQuaternion
1
vectorPartQuaternion(7+3i+2j+k)
3i+2j+k
arg
1
計算一複數的輻角
arg(3+7i)
1.1659045405098
cis
1
cis(π)
-1
conjugate
1
conjugate(7+3i)
7-3i
技術性
hide
隱藏輸出
1
hide(7,3);5
5
<functionName>AtModule<ModulePageName>
不定
调用其他模块的函数。須注意函數名稱必須是純英文、模組名稱也必須是純英文,不能有空格或其他符號。例如若需要呼叫Module:Element中的getAtomicWeight函數,則須表示為getAtomicWeightAtModuleElement
getAtomicWeightAtModuleElement(10)
20.1797
三角函
sin
1
sin(π)
0
cos
1
cos(π)
-1
tan
1
tan(π)
0
cot
1
cot(div(π,2))
0
sec
1
sec(π)
-1
csc
1
csc(div(π,2))
1
asin
1
計算一數的反正弦值
asin(1)
1.5707963267949
acos
1
計算一數的反餘弦值
acos(1)
0
atan
1
計算一數的反正切值
atan(1)
0.78539816339745
acot
1
計算一數的反餘切值
acot(1)
0.78539816339745
asec
1
計算一數的反正割值
asec(1)
0
acsc
1
計算一數的反餘割值
acsc(1)
1.5707963267949
sinh
1
sinh(π)
11.548739357258
cosh
1
cosh(π)
11.591953275522
tanh
1
tanh(π)
0.99627207622075
coth
1
coth(π)
1.0037418731973
sech
1
sech(π)
0.086266738334054
csch
1
csch(π)
0.086589537530047
asinh
1
計算一數的雙曲反正弦值
asinh(1)
0.88137358701954
acosh
1
計算一數的雙曲反餘弦值
acosh(1)
0
atanh
1
計算一數的雙曲反正切值
atanh(0.5)
0.54930614433405
acoth
1
計算一數的雙曲反餘切值
acoth(1.5)
0.80471895621705
asech
1
計算一數的雙曲反正割值
asech(1)
0
acsch
1
計算一數的雙曲反餘割值
acsch(1)
0.88137358701954
cis
1
cis(π)
-1
gd
1
gd(e)
1.4390113159637
cogd
1
cogd(π)
0.08648169656714
local p = {}
local getArgs = require('Module:Arguments').getArgs
local ext_mathlib = require("Module:Complex Number/Functions")._init
local use_other_module = false
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 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 _remove_strip_marker(str)return mw.text.decode(mw.text.unstrip(str)) end
local function _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
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 _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
local function _adj_math_output(unmathstr)
	return mw.ustring.gsub(unmathstr,"ω","\\omega "):gsub("ε","\\varepsilon ") 
		:gsub("([%+%-]?)(%d*%.?%d+)e([%+%-]?%d+)","%1%2\\times 10^{%3}")
end

function p.calc_table(frame)
	local variable_process = require("Module:Number/data")
    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, {
        	parentFirst=true,
        	trim = false,
			removeBlanks = false
        }) --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 use_other_module = true end
    local first_number_list = {"2","3","4","5","6","7","8","9"}
    local second_number_list, first_number_show, second_number_show
    local calculate_str, calculate_title = "{{{left}}} * {{{right}}}", "×"
	if args['number list'] or args['number_list'] then first_number_list = mw.text.split(args['number list'] or args['number_list'] or '',',') end
	if args['number list2'] or args['number_list2'] then second_number_list = mw.text.split(args['number list2'] or args['number_list2'] or '',',') end
	
	if args['number list show'] or args['number_list_show'] then first_number_show = mw.text.split(args['number list show'] or args['number_list_show'] or '',',') end
	if args['number list show2'] or args['number_list_show2'] then second_number_show = mw.text.split(args['number list show2'] or args['number_list_show2'] or '',',') end
	
	if args['calculate'] then calculate_str = mw.text.trim(_remove_strip_marker(args['calculate'])) end
	if args['calculate title'] or args['calculate_title'] then calculate_title = mw.text.trim(args['calculate title'] or args['calculate_title']) end
	if second_number_list == nil or (second_number_list and (second_number_list == {} or #second_number_list == 0) ) then
		second_number_list = first_number_list
	end
	if first_number_show == nil or (first_number_show and (first_number_show == {} or #first_number_show == 0) ) then
		first_number_show = first_number_list
	end
	if second_number_show == nil or (second_number_show and (second_number_show == {} or #second_number_show == 0) ) then
		second_number_show = first_number_show
	end
	local body, buffer_str, table_str = "", '', ''
	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(function()end)
					local my_math_lib = (type(load_math_lib.init) == func_type) and load_math_lib.init() or load_math_lib
					if type(my_math_lib.constructor) == func_type then
						math_class = "mymath"
						mymath = my_math_lib
						mytomath = my_math_lib.constructor
					end
				end
			end
		end,function()end)
	end
	body = body .. "! " .. (args["main head css"] or args["main_head_css"] or '') .. " | " .. calculate_title .. ' \n'
	for j=1,#second_number_list do
		local second_it = mw.text.trim(second_number_list[j] or '')
		local second_it_show = mw.text.trim(second_number_show[j] or '')
		if second_it ~= nil then
			local second_num_math = tostring(second_it_show or second_it)
			if should_math or can_math then second_num_math = _adj_math_output(second_num_math) end
			if can_math then second_num_math = frame:callParserFunction{name = "#tag:math", args = {second_num_math}} end
			body = body .. "! " .. (args["head css"] or args["head_css"] or '') .. " | " .. second_num_math .. ' \n'
		end
	end
	body = body .. '\n'
	for i=1,#first_number_list do
		local first_it = mw.text.trim(first_number_list[i] or '')
		local first_it_show = mw.text.trim(first_number_show[i] or '')
		if first_it ~= nil then
			body = body .. "|-\n"; table_str = ''
			local first_num_math = tostring(first_it_show or first_it)
			if should_math or can_math then first_num_math = _adj_math_output(first_num_math) end
			if can_math then first_num_math = frame:callParserFunction{name = "#tag:math", args = {first_num_math}} end
			body = body .. "! " .. (args["head css"] or args["head_css"] or '') .. " | "  .. first_num_math .. " \n"
			for j=1,#second_number_list do
				local second_it = mw.text.trim(second_number_list[j] or '')
				if second_it ~= nil then
					
					buffer_str = variable_process._getFormatingStringByArgument(calculate_str, {
						left=tostring(first_it),right=tostring(second_it)
					})
					local exec_result = p.calc( buffer_str or '', ( {
						cmath = cmath,
						qmath = qmath,
						bmath = bmath,
						mathtag = mathtag,
						mymath = mymath
					} ) [ math_class ] , (( {
						cmath = cmath.toComplexNumber,
						qmath = qmath.toQuaternionNumber,
						bmath = bmath.toBoolean,
						mathtag = mathtag.toTagMath,
						mymath = mytomath
					} ) [ math_class ] ) )
					local exec_result_str = mw.text.trim(tostring(exec_result) or '')
					local exec_check = mw.text.trim((tonumber(exec_result_str) and args[tonumber(exec_result_str)]) or args[exec_result_str] or '')
					if exec_check == '' then exec_check = nil end
					table_str = table_str .. '|' .. (exec_check or args["number css"] or args["number_css"] or '') .. "| "
					if should_math or can_math then exec_result_str = _adj_math_output(exec_result_str) end
					if can_math then exec_result_str = frame:callParserFunction{name = "#tag:math", args = {exec_result_str}} end
					table_str = table_str .. mw.text.trim(exec_result_str) .. ' \n'
				end
			end
			body = body .. table_str
		end
	end
	if use_ext_mathlib == true then TrackingCategory.append('使用擴充複變函數庫的頁面') end
	return body
end
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._preCalculate(frame)
    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 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(function()end)
					local my_math_lib = (type(load_math_lib.init) == func_type) and load_math_lib.init() or load_math_lib
					if type(my_math_lib.constructor) == func_type then
						math_class = "mymath"
						mymath = my_math_lib
						mytomath = my_math_lib.constructor
					end
				end
			end
		end,function()end)
	end
    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( _load_strip_marker(args[1] or args['1'] or ''), input_math_lib , input_to_number ), 
		can_math, should_math, input_math_lib, input_to_number
end
function p.templateCalculate(frame)
	local body, can_math, should_math = 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 body = _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)
	local body, can_math, should_math = p._preCalculate(frame)
	if should_math or can_math then body = _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.functionGraph(frame)
	if comp_number == nil then comp_number = require("Module:Complex Number") end
    local cmath, qmath = comp_number.cmath.init(), comp_number.qmath.init()
	if not getArgs then getArgs = require('Module:Arguments').getArgs end
	local args = getArgs(frame, {parentFirst=true})
	local exprs = {}
	local body_args, x_start, x_end, y_min, y_max, sampling = {}, 0, 1, nil, nil, 50
	for arg_name, arg_value in pairs( args ) do
		if tonumber(arg_name) ~= nil then exprs[#exprs + 1] = _remove_strip_marker(arg_value)
		elseif  mw.ustring.lower(arg_name) == "start" then x_start = tonumber(arg_value)
		elseif  mw.ustring.lower(arg_name) == "end" then x_end = tonumber(arg_value)
		elseif  mw.ustring.lower(arg_name) == "sampling" then sampling = tonumber(arg_value)
		elseif  mw.ustring.lower(arg_name) == "min" then y_min = tonumber(arg_value)
		elseif  mw.ustring.lower(arg_name) == "max" then y_max = tonumber(arg_value)
		else body_args[arg_name] = arg_value
		end
	end
	local yesno = require('Module:Yesno')
	if yesno(args.useOtherModule or 'no') == true then use_other_module = true end
    local body = p._functionGraph(exprs,
    	x_start, x_end, sampling, y_min, y_max, body_args, ( {
		cmath = cmath,
		qmath = qmath,
	} ) [ frame.args['class'] ] , (( {
		cmath = cmath.toComplexNumber,
		qmath = qmath.toQuaternionNumber,
	} ) [ frame.args['class'] ] ) )
	body.width = 400
	body.height = 100; body.type="line"
	body.interpolate = frame.args['interpolate'] or "monotone"
	for arg_name, arg_value in pairs( body_args ) do
		body[arg_name] = arg_value
	end
	body = mw.getCurrentFrame():expandTemplate{title = "Graph:Chart", args = body}
	if use_ext_mathlib == true then TrackingCategory.append('使用擴充複變函數庫的頁面') 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 = _function_preprocessing(_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 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)))) 
		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 = _function_preprocessing(_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

function p._functionGraph(expr_arr,x_start,x_end,sampling, y_min, y_max, body_args,  math_lib, number_Constructer)
	if (yesno or require('Module:Yesno'))((body_args or {}).useOtherModule or 'no') == true then use_other_module = true 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 postfix = {}
	local check_func = {}
	local x_arr, y_arr = {}, {}
	if type(expr_arr) == type({}) then
		for i=1,#expr_arr do
			local check_parametric = mw.text.split(expr_arr[i],';')
			if #check_parametric == 1 then
				local pre_expr, pre_scope = _function_preprocessing(expr_arr[i], mathlib, numberConstructer, false)
				postfix[#postfix + 1] = p.infixToPostfix(pre_expr, debug_flag)
				if pre_scope then postfix[#postfix].scope = pre_scope end
			elseif #check_parametric >= 3 then
				postfix[#postfix + 1]={parametric=true}
				postfix[#postfix].x_name = check_parametric[1] or 't'
				postfix[#postfix].y_name = check_parametric[2] or 't'
				postfix[#postfix].x = p.infixToPostfix(check_parametric[1] or 't', debug_flag)
				postfix[#postfix].y = p.infixToPostfix(check_parametric[2] or 't', debug_flag)
				postfix[#postfix].t = check_parametric[3] or 't'
				postfix[#postfix].min = numberConstructer(check_parametric[4]) or numberConstructer(0)
				postfix[#postfix].max = numberConstructer(check_parametric[5]) or numberConstructer(1)
			end
			y_arr[#y_arr + 1] = {}
			x_arr[#x_arr + 1] = {}
		end
	else
		local check_parametric = mw.text.split(expr_arr,';')
		if #check_parametric == 1 then
			local pre_expr, pre_scope = _function_preprocessing(expr_arr, mathlib, numberConstructer, false)
			postfix[#postfix + 1] = p.infixToPostfix(pre_expr, debug_flag)
			if pre_scope then postfix[#postfix].scope = pre_scope end
		elseif #check_parametric >= 3 then
			postfix[#postfix + 1]={parametric=true}
			postfix[#postfix].x_name = check_parametric[1] or 't'
			postfix[#postfix].y_name = check_parametric[2] or 't'
			postfix[#postfix].x = p.infixToPostfix(check_parametric[1] or 't', debug_flag)
			postfix[#postfix].y = p.infixToPostfix(check_parametric[2] or 't', debug_flag)
			postfix[#postfix].t = check_parametric[3] or 't'
			postfix[#postfix].min = numberConstructer(check_parametric[4]) or numberConstructer(0)
			postfix[#postfix].max = numberConstructer(check_parametric[5]) or numberConstructer(1)
		end
		y_arr[#y_arr + 1] = {}
		x_arr[#x_arr + 1] = {}
	end
	local check_cexpr = mw.title.new("cexpr","template"):getContent()
	local check_isreal = mw.title.new("isReal","template"):getContent()
	for i=0,sampling do
		local it = x_start + (i * (x_end-x_start) / sampling)
		local x_val = it
		for j=1,#expr_arr do
			local calc_val = " "
			xpcall(function() 
				if type(postfix[j]) == type({}) and postfix[j].parametric == true then
					local it_t = postfix[j].min + (i * (postfix[j].max - postfix[j].min) / sampling)
					--參數式
					calc_val = p.calc_by_postfix(postfix[j].y, {[postfix[j].t]=it_t}, mathlib, numberConstructer, false)
					x_val = p.calc_by_postfix(postfix[j].x, {[postfix[j].t]=it_t}, mathlib, numberConstructer, false)
				else
					calc_val = p.calc_by_postfix(postfix[j], {
						x=it,
						last=function(num) --for Template:數列
							local last_num = (body_args or {})['last' .. tonumber(tostring(num or 1))] or 0
							return numberConstructer(y_arr[j][#(y_arr[j])-(tonumber(tostring(num))or 1)+1] or last_num)
						end,
					}, mathlib, numberConstructer, false) 
					if( tonumber((body_args or {})["calc diff " .. tostring(j) ]) == 1 )then
						local dy = p.calc_by_postfix(postfix[j], {x=(it + 1e-6)}, mathlib, numberConstructer, false)
						calc_val = 1e6 * (dy - calc_val)
					end
				end
				if y_max and mathlib.re(calc_val) > y_max then calc_val = y_max end
				if y_min and mathlib.re(calc_val) < y_min then calc_val = y_min end
				if x_end and mathlib.re(x_val) > x_end then x_val = x_end end
				if x_start and mathlib.re(x_val) < x_start then x_val = x_start end
			end,function(_)end)
			if tonumber((body_args or {})["round number"]) ~= nil then 
				if calc_val then 
					calc_val = mathlib.round(calc_val, tonumber((body_args or {})["round number"]), 10)
				end
			end
			if tonumber((body_args or {})["nonreal is nan"]) == 1 then 
				if math.abs(tonumber(mathlib.abs(mathlib.nonRealPart(calc_val))) or 0) > 1e-14 then calc_val = nil end
			end
			local num_check = mw.ustring.lower(tostring(numberConstructer(calc_val)))
			if mw.ustring.match(num_check,"nan") or mw.ustring.match(num_check,"nil") or mw.ustring.match(num_check,"inf") then calc_val = ' ' end
			 num_check = mw.ustring.lower(tostring(numberConstructer(x_val)))
			if mw.ustring.match(num_check,"nan") or mw.ustring.match(num_check,"nil") or mw.ustring.match(num_check,"inf") then x_val = ' ' end
			y_arr[j][ (#(y_arr[j]) + 1) ] = tostring(calc_val)
			x_arr[j][ (#(x_arr[j]) + 1) ] = tostring(x_val)
		end
	end
	local result={}
	if #expr_arr > 0 then result.legend = "函數" end
	for i=1,#expr_arr do
		result['x'] = table.concat(x_arr[i],',')
		result['y' .. tostring(i)] = table.concat(y_arr[i],',')
		result['y' .. tostring(i) .. "Title"] = tostring( (body_args or {})[tostring(i) .. " name" ] or expr_arr[i] )
		if type(postfix[i]) == type({}) and postfix[i].parametric == true then
			result['y' .. tostring(i) .. "Title"] = "x=" .. postfix[i].x_name .. "; y=" .. postfix[i].y_name
		elseif( tonumber((body_args or {})["calc diff " .. tostring(i) ]) == 1 )then
			result['y' .. tostring(i) .. "Title"] = '( ' .. result['y' .. tostring(i) .. "Title"] .. " )\'"
		end
		
		if check_func[ result['y' .. tostring(i) .. "Title"] ] ~= nil then
			local new_name = result['y' .. tostring(i) .. "Title"] .. " ,(" .. tostring(check_func[ result['y' .. tostring(i) .. "Title"] ]+1) .. ")"
			check_func[ result['y' .. tostring(i) .. "Title"] ] = check_func[ result['y' .. tostring(i) .. "Title"] ] + 1
			result['y' .. tostring(i) .. "Title"] = new_name
		else check_func[ result['y' .. tostring(i) .. "Title"] ] = 1
		end
	end
	return result
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(function()end))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

--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))
-- 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))
-- 217.146633205
--mw.log(p.calc("(i*j*k)",require("Module:Complex Number").qmath.init(),require("Module:Complex Number").qmath.init().toQuaternionNumber,true))
-- (-1)
function p.calc(input_str, math_lib, number_Constructer, debug_flag, should_use_other_module)
	if comp_number == nil then comp_number = require("Module:Complex Number") end
	if should_use_other_module ~= nil then 
		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 = _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)
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

function p.calc_by_postfix(postfix, scope, 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 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 = function()end,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
	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
			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]
					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("計算失敗:未知的變數 \"" .. _subst_error_strip(tostring(calc_stack[#calc_stack][1])) .. "\" ") 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_name = tostring(calc_stack[#calc_stack][1])
								local try_scope = mathlib[try_scope_name]
								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(tonumber) then	calc_stack[#calc_stack] = try_scope_name
									else calc_stack[#calc_stack] = try_scope end
								else error("計算失敗:未知的變數 \"" .. _subst_error_strip(tostring(calc_stack[#calc_stack][1])) .. "\" " ) 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_name = tostring(calc_stack[#calc_stack - 1][1])
								local try_scope = mathlib[try_scope_name]
								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("計算失敗:未知的變數 \"" .. _subst_error_strip(tostring(calc_stack[#calc_stack - 1][1])) .. "\" ") 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(function()end) then calc_stack[#calc_stack] = get_data
								else error("計算失敗:未知的變數 \"" .. _subst_error_strip(tostring(calc_stack[#calc_stack][1])) .. "\" ") 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("計算失敗:套用運算子 \"" .. _subst_error_strip(mw.text.trim(it.name)) .. "\" 發生錯誤 \"" .. message .. "\" .")
			end)
			xpcall(function() (calc_stack[#calc_stack]):clean() end,function(_)end)
			if it.name == '←' and type(mathlib.mathdef)~=type(function()end) 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(cantass) elseif local_scope then local_scope[to_ass[1]] = calc_stack[#calc_stack] else error(cantass)end
			end
			if do_dbg == true then dbg_func(it.name, '\t', print_sk(calc_stack,', ') ) end
		elseif it.propetry == "func" then
			local calfunc, functype = mathlib[it.name], type(tonumber)
			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 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("計算失敗:執行函數 \"" .. "Module:" .. check_func[2] .. '#' .. check_func[1] .. "\" 發生錯誤 \"" .. message .. "\" .")
					end)
				end
			end
			local callstr = it.name
			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_name = tostring((call_stack[#call_stack])[j][1])
								local try_scope = mathlib[try_scope_name]
								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("計算失敗:未知的變數 \"" .. _subst_error_strip(tostring((call_stack[#call_stack])[j][1])) .. "\" ") 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('') then calc_result = numberConstructer(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 error("計算失敗:未知的變數 \"" .. _subst_error_strip(tostring(calc_stack[#calc_stack][1])) .. "\" ") 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('') then calc_result = numberConstructer(calc_result) end
						calc_stack[#calc_stack] = calc_result
					end
					call_stack[#call_stack] = nil
				end, function(message)
					error("計算失敗:執行函數 \"" .. _subst_error_strip(it.name) .. "\" 發生錯誤 \"" .. message .. "\" .")
				end)
			else
				if it.name == '(' then error("計算失敗:未封閉的括號") end
				error("計算失敗:無法執行函數 \"" .. _subst_error_strip(it.name) .. "\" ")
			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
		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 
		error("計算失敗:缺少運算子,數字 [" .. print_sk(calc_stack,', ') .. "] 無法運算。")
	end
	return numberConstructer(0)
end
p.symbol_table=Operators.symbol_table
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 = function()end,false end
	
	if mw.ustring.find(str,"([%A])[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")
	end
	if mw.ustring.find(str,"^not([^%a%(])") then
		str = mw.ustring.gsub(str,"^not([^%a%(])","~ %1")
	end
	str = mw.ustring.gsub(str,"([%A])[rR][oO][uU][nN][dD]([^%a%(])","%1 ≃ %2")
	str = mw.ustring.gsub(str,"([><=!])=",function(str) return ({['>']='≥',['<']='≤',['!']='≠',['=']=''})[str] end)
	
	str = mw.ustring.gsub(str,"([%+%-]?)(%d*%.?%d+)e([%+%-]?%d+)",function(n_sign,n_num,n_pow)return n_sign.."("..n_num.."*10^("..n_pow.."))"end)
	str = mw.ustring.gsub(str,"([A-Za-hj-z])i","%1I")
	str = mw.ustring.gsub(str,"([A-Za-ik-z])j","%1J")
	str = mw.ustring.gsub(str,"([A-Za-jl-z])k","%1K")
	str = mw.ustring.gsub(str,"i([A-Za-hj-z])","I%1")
	str = mw.ustring.gsub(str,"j([A-Za-ik-z])","J%1")
	str = mw.ustring.gsub(str,"k([A-Za-jl-z])","K%1")
	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 
	); 

	result = mw.ustring.gsub(result,"I","i")
	result = mw.ustring.gsub(result,"J","j")
	result = mw.ustring.gsub(result,"K","k")
	--------------------------------------------------------
	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
	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,function()end)
				if (stack[#stack] or {elements=0}).elements < (psymbol_tablestackstacknamecount or -1) then
					if do_dbg == true then dbg_func("==operator ",stack[#stack].name, " need ",p.symbol_table[stack[#stack].name].count, " elements, but got ",stack[#stack].elements) end
					return {}
				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=function()end}).name] and p.symbol_table[(stack[#stack]or{name=function()end}).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
							if do_dbg == true then dbg_func("==operator ",stack[#stack].name, " need ",p.symbol_table[stack[#stack].name].count, " elements, but got ",stack[#stack].elements) end
							return {}
						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].elements < p.symbol_table[stack[#stack].name].count then
					if do_dbg == true then dbg_func("==operator ",stack[#stack].name, " need ",p.symbol_table[stack[#stack].name].count, " elements, but got ",stack[#stack].elements) end
					return {}
				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
				flag = mw.ustring.match(stack[#stack].name,"[%a%(]")
			end
			if mw.ustring.match(stack[#stack].name,"%a") then
				postfix[#postfix + 1] = {name=func_list[stack[#stack].name] or stack[#stack].name, propetry=stack[#stack].propetry}
			end
			stack[#stack] = nil --pop
			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.calcExpr(frame)
    local result, can_math, should_math, input_math_lib, input_to_number = p._preCalculate(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) --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 result end
    if input_math_lib.abs(result) > 1e-14 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 = p._preCalculate(frame)
    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 input_math_lib.abs(input_math_lib.nonRealPart(result)) > 1e-14 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,
	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,'&','\\and')
	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,'|','\\or')
	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,
	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,
	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)
		local that, oper_id = p.tagmath.toTagMath(expr), ''
		local that_true = p.tagmath.toTagMath(true_expr)
		local that_false = p.tagmath.toTagMath(false_expr)
		that.lowoperator = oper_id
		that.value = mw.ustring.format("\\begin{cases} {%s}, & \\text{if }{%s} \\\\ {%s}, & \\text{otherwise} \\end{cases}", 
			true_expr.value, that.value, false_expr.value)
		return that 
	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)-2)
		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 = "i"
			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,
	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)-2)
		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 = "i"
			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)-2)
		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 = "i"
			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)-2)
		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 = "i"
			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,
	hide=function(this)return""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}",
			["gcd"]="\\gcd",["round"]="\\operatorname{round}",["arg"]="\\arg",["trunc"]="\\operatorname{trunc}",
			["gd"]="\\operatorname{gd}",["cogd"]="\\operatorname{cogd}",
			["diag"]="\\operatorname{diag}",["det"]="\\det",["determinant"]="\\det",
			["adj"]="\\operatorname{adj}",["adjoint"]="\\operatorname{adj}"
		}
		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) 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}"}
		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.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