Module:Math

p = {}

local function makeArgArray(...) -- Makes an array of arguments from a list of arguments that might include nils. local args = {...} -- Table of arguments. It might contain nils or non-number values, so we can't use ipairs. local nums = {} -- Stores the numbers of valid numerical arguments. local ret = {} for k, v in pairs(args) do		v = p._cleanNumber(v) if v then nums[#nums + 1] = k			args[k] = v		end end table.sort(nums) for i, num in ipairs(nums) do		ret[#ret + 1] = args[num] end return ret end

local function fold(func, ...) -- Use a function on all supplied arguments, and return the result. The function must accept two numbers as parameters, -- and must return a number as an output. This number is then supplied as input to the next function call. local vals = makeArgArray(...) local count = #vals -- The number of valid arguments if count == 0 then return -- Exit if we have no valid args, otherwise removing the first arg would cause an error. nil, 0 end local ret = table.remove(vals, 1) for _, val in ipairs(vals) do		ret = func(ret, val) end return ret, count end

-- Helper function that interprets the input numerically. If the input does not appear to be a number, attempts evaluating it as a parser functions expression.

function p._cleanNumber(number_string) if type(number_string) == 'number' then -- We were passed a number, so we don't need to do any processing. return number_string, tostring(number_string) elseif type(number_string) ~= 'string' or not number_string:find('%S') then -- We were passed a non-string or a blank string, so exit. return nil, nil; end

-- Attempt basic conversion local number = tonumber(number_string)

-- If failed, attempt to evaluate input as an expression if number == nil then local success, result = pcall(mw.ext.ParserFunctions.expr, number_string) if success then number = tonumber(result) number_string = tostring(number) else number = nil number_string = nil end else number_string = number_string:match("^%s*(.-)%s*$") -- String is valid but may contain padding, clean it. number_string = number_string:match("^%+(.*)$") or number_string -- Trim any leading + signs. if number_string:find('^%-?0[xX]') then -- Number is using 0xnnn notation to indicate base 16; use the number that Lua detected instead. number_string = tostring(number) end end

return number, number_string end

function p._sum(...) local sums, count = fold((function(a, b) return a + b end), ...) if not sums then return 0 else return sums end end

function p.sum(frame) local pframe = frame:getParent local args = pframe.args return p._sum(args) end

return p