Module:FunctionGraph

From wiki
Jump to navigation Jump to search

local p = {} local comp_number = nil local getArgs = require('Module:Arguments').getArgs local lib_calc = require('Module:Complex_Number/Calculate') local TrackingCategory = require('Module:TrackingCategory') local noop_func = function()end

function p.applyFunctionGraph(frame) local working_frame = mw.getCurrentFrame() local body = working_frame:extensionTag{ name = 'graph', content = require('Module:FunctionGraph/Graph').chart(frame) } 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 local check_arg_name = mw.ustring.lower(tostring(arg_name)) if tonumber(arg_name) ~= nil then exprs[#exprs + 1] = lib_calc._remove_strip_marker(arg_value) elseif check_arg_name == "start" then x_start = tonumber(arg_value) elseif check_arg_name == "end" then x_end = tonumber(arg_value) elseif check_arg_name == "sampling" then sampling = tonumber(arg_value) elseif check_arg_name == "min" then y_min = tonumber(arg_value) elseif check_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 lib_calc.use_other_module = true end

local math_class = frame.args['class']or

   local mymath = cmath
   local mytomath = cmath.toComplexNumber
   if mw.ustring.sub(math_class,1,7):upper()=="MODULE:" then

local module_name, math_lib_name = lib_calc.checkModuleClass(math_class) xpcall(function() local load_module = require("Module:"..module_name) if load_module ~= nil then local load_math_lib = load_module[math_lib_name] if load_module ~= nil then local func_type = type(noop_func) local my_math_lib = (type(load_math_lib.init) == func_type) and load_math_lib.init() or load_math_lib if type(my_math_lib.constructor) == func_type then math_class = "mymath" mymath = my_math_lib mytomath = my_math_lib.constructor end end end end,noop_func) end

   local body = p._functionGraph(exprs,
   	x_start, x_end, sampling, y_min, y_max, body_args, ( {

cmath = cmath, qmath = qmath, mymath = mymath, } ) [math_class] , (( { cmath = cmath.toComplexNumber, qmath = qmath.toQuaternionNumber, mymath = mytomath, } ) [math_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} body = p.applyFunctionGraph(body) if use_ext_mathlib == true then TrackingCategory.append('使用擴充複變函數庫的頁面') end return body end

function p.calc_table(frame) local variable_process = require("Module:Number/data")

   local args
   local can_math = false
   local should_math = false
   local show_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
   lib_calc._randomseed()
   local yesno = require('Module:Yesno')
   if yesno(args.useOtherModule or 'no') == true then lib_calc.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 ,',') if #first_number_show == 1 and mw.text.trim(first_number_show[1]) == then first_number_show = {} end 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 ,',') if #second_number_show == 1 and mw.text.trim(second_number_show[1]) == then second_number_show = {} end end

if args['calculate'] then calculate_str = mw.text.trim(lib_calc._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 = lib_calc.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 = lib_calc.checkModuleClass(math_class) xpcall(function() local load_module = require("Module:"..module_name) if load_module ~= nil then local load_math_lib = load_module[math_lib_name] if load_module ~= nil then local func_type = type(noop_func) local my_math_lib = (type(load_math_lib.init) == func_type) and load_math_lib.init() or load_math_lib if type(my_math_lib.constructor) == func_type then math_class = "mymath" mymath = my_math_lib mytomath = my_math_lib.constructor end end end end,noop_func) end 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 if args.class ~= "mathtag" and yesno(args['show math'] or args['show_math']) then second_num_math = lib_calc._re_math_output(second_num_math) end second_num_math = lib_calc._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 if args.class ~= "mathtag" and yesno(args['show math'] or args['show_math']) then first_num_math = lib_calc._re_math_output(first_num_math) end first_num_math = lib_calc._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 = lib_calc.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 if args.class ~= "mathtag" and yesno(args['show math'] or args['show_math']) then exec_result_str = lib_calc._re_math_output(exec_result_str) end exec_result_str = lib_calc._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._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 lib_calc.use_other_module = true end if comp_number == nil then comp_number = require("Module:Complex Number") end math = comp_number.math.init()

   lib_calc._randomseed()

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 local_func_sign = '↦' local check_parametric = mw.text.split(expr_arr[i],';') --解決 函數-參數式 衝突 if mw.ustring.find(expr_arr[i], local_func_sign) then check_parametric = mw.text.split(expr_arr[i],'\\;')end if #check_parametric == 1 then local pre_expr, pre_scope = lib_calc._function_preprocessing(expr_arr[i], mathlib, numberConstructer, false) postfix[#postfix + 1] = lib_calc.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 = lib_calc.infixToPostfix(check_parametric[1] or 't', debug_flag) postfix[#postfix].y = lib_calc.infixToPostfix(check_parametric[2] or 't', debug_flag) postfix[#postfix].t = mw.text.trim(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 local_func_sign = '↦' local check_parametric = mw.text.split(expr_arr,';') --解決 函數-參數式 衝突 if mw.ustring.find(expr_arr, local_func_sign) then check_parametric = mw.text.split(expr_arr,'\\;')end

if #check_parametric == 1 then local pre_expr, pre_scope = lib_calc._function_preprocessing(expr_arr, mathlib, numberConstructer, false) postfix[#postfix + 1] = lib_calc.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 = lib_calc.infixToPostfix(check_parametric[1] or 't', debug_flag) postfix[#postfix].y = lib_calc.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() local check_ifNumeric = mw.title.new("ifNumeric","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 = lib_calc.calc_by_postfix(postfix[j].y, {[postfix[j].t]=it_t}, mathlib, numberConstructer, false) x_val = lib_calc.calc_by_postfix(postfix[j].x, {[postfix[j].t]=it_t}, mathlib, numberConstructer, false) else calc_val = lib_calc.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 or ((yesno or require('Module:Yesno'))((body_args or {})["calc diff " .. tostring(j) ]or'no')==true) )then local dy = lib_calc.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

function p.complex_graph(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 expr = args[1] or args['1'] or 'x' local body_args, x_start, x_end, y_start, y_end, sampling, width = {}, -5, 5, -5, 5, 100, 120 for arg_name, arg_value in pairs( args ) do local check_arg_name = mw.ustring.gsub(mw.ustring.lower(tostring(arg_name)), "[ _]", "") if check_arg_name == "xstart" then x_start = tonumber(arg_value) elseif check_arg_name == "xend" then x_end = tonumber(arg_value) elseif check_arg_name == "ystart" then y_start = tonumber(arg_value) elseif check_arg_name == "yend" then y_end = tonumber(arg_value) elseif check_arg_name == "sampling" then sampling = tonumber(arg_value) elseif check_arg_name == "width" then width = 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 lib_calc.use_other_module = true end

local math_class = frame.args['class']or

   local mymath = cmath
   local mytomath = cmath.toComplexNumber
   if mw.ustring.sub(math_class,1,7):upper()=="MODULE:" then

local module_name, math_lib_name = lib_calc.checkModuleClass(math_class) xpcall(function() local load_module = require("Module:"..module_name) if load_module ~= nil then local load_math_lib = load_module[math_lib_name] if load_module ~= nil then local func_type = type(noop_func) local my_math_lib = (type(load_math_lib.init) == func_type) and load_math_lib.init() or load_math_lib if type(my_math_lib.constructor) == func_type then math_class = "mymath" mymath = my_math_lib mytomath = my_math_lib.constructor end end end end,noop_func) end

   local calc_result = p._complex_graph(expr,
   	x_start, x_end, y_start, y_end, sampling ,width, body_args, ( {

cmath = cmath, qmath = qmath, mymath = mymath, } ) [math_class] , (( { cmath = cmath.toComplexNumber, qmath = qmath.toQuaternionNumber, mymath = mytomath, } ) [math_class] ) ) local body = frame:callParserFunction{ name = '#tag:graph', args = {

   	mw.text.jsonEncode(calc_result)

} } if use_ext_mathlib == true then TrackingCategory.append('使用擴充複變函數庫的頁面') end return body

end function p._complex_graph(expr, x_start, x_end, y_start, y_end, sampling, width, body_args, math_lib, number_Constructer) if (yesno or require('Module:Yesno'))((body_args or {}).useOtherModule or 'no') == true then lib_calc.use_other_module = true end if comp_number == nil then comp_number = require("Module:Complex Number") end local cmath = comp_number.cmath.init() lib_calc._randomseed() local mathlib, numberConstructer = math_lib or cmath, number_Constructer or cmath.constructor

local pxsize = width

local pre_expr, pre_scope = lib_calc._function_preprocessing(expr, mathlib, numberConstructer, false) local postfix = lib_calc.infixToPostfix(pre_expr, debug_flag) if pre_scope then postfix.scope = pre_scope end

local function HSBToRGB(h, s, b) local function k(n) return (n + h / 60) % 6 end local function f(n) return b * (1 - s * math.max(0, math.min(k(n), 4 - k(n), 1))) end return 255 * f(5), 255 * f(3), 255 * f(1); end

local result = {} local i_value = mathlib.elements and (mathlib.elements[2] and mathlib.elements[2] or mathlib.i) or mathlib.i if not i_value then error("繪製失敗:所用數體無非實數單位元") end for i=0,sampling do local it_y = y_start + (i * (y_end-y_start) / sampling) local calc_row = {} for j=0,sampling-1 do local it_x = x_start + (j * (x_end-x_start) / sampling) local it = mathlib[0] + it_x + i_value * it_y local calc_val = lib_calc.calc_by_postfix(postfix, {x=it}, mathlib, numberConstructer, false) local check_nan = not not(tostring(calc_val):match("[%+%-]?[Nn][IiAa][LlNn]")) local check_inf = not not(tostring(calc_val):match("[%+%-]?[Ii][Nn][Ff]")) local result_color = "rgb(127,127,127)" if not check_nan then if check_inf then result_color = "rgb(255,255,255)" else local h, s, b = (mathlib.re(mathlib.arg(calc_val)) / math.pi * 180) % 360, mathlib.re(mathlib.inverse(mathlib.log(mathlib.abs(calc_val) + 1) * 0.3 + 1)), mathlib.re(-mathlib.inverse(mathlib.log(mathlib.abs(calc_val) + 1) * 5 + 1.1) + 1) result_color = string.format("rgb(%d,%d,%d)", HSBToRGB(h + ((h < 0)and 360 or 0), s, b)) end end calc_row[#calc_row + 1] = result_color end result[#result + 1] = calc_row end local w_count = #result local cell_width = pxsize / (w_count+2) local graph_data = { width=pxsize, height=pxsize, data={}, padding={left=cell_width,top=cell_width,bottom=cell_width,right=cell_width}, scales={ {name="x",type="linear",domain={0,w_count},range="width"}, {name="y",type="linear",domain={0,w_count},range="height"}, }, marks={ { type="rect", from={data="funcdata"}, properties={ enter={ x={scale="x",field="0"},y={scale="y",field="1"}, width={value=cell_width},height={value=cell_width}, stroke={field="2"}, fill={field="2"}, } } } } } local func_data = {name="funcdata",values={}} for x=1,w_count do for y=1,#(result[x]) do func_data.values[#(func_data.values)+1] = {x-1,#(result[x])-y+1,result[y][x]} end end graph_data.data[#(graph_data.data)+1] = func_data return graph_data end


return p