Module:Utils: Difference between revisions

From Xenharmonic Wiki
Jump to navigation Jump to search
ArrowHead294 (talk | contribs)
mNo edit summary
ArrowHead294 (talk | contribs)
mNo edit summary
Line 3: Line 3:


-- Trim a string
-- Trim a string
function trim(s)
function p.trim(s)
   return s:match("^%s*(.-)%s*$")
   return s:match("^%s*(.-)%s*$")
end
end


-- check if a table contains x
-- Check if a table contains x
function p.table_contains(tbl, x)
function p.table_contains(tbl, x)
for i = 1, #tbl do
for i = 1, #tbl do
Line 17: Line 17:
end
end


-- return the first index with the given value (or nil if not found)
-- Return the first index with the given value (or nil if not found)
function p.index_of(array, value)
function p.index_of(array, value)
for i, v in ipairs(array) do
for i, v in ipairs(array) do
Line 27: Line 27:
end
end


-- check whether the input is a non-empty string
-- Check whether the input is a non-empty string
function p.value_provided(s)
function p.value_provided(s)
return type(s) == "string" and #s > 0
return type(s) == "string" and #s > 0
end
end


-- evaluate input on error use default; cannot be used with {{#invoke:}}
-- Evaluate input on error use default; cannot be used with {{#invoke:}}
function p.eval_num_arg(input, def_value)
function p.eval_num_arg(input, def_value)
local result = input
local result = input
Line 38: Line 38:
result = def_value
result = def_value
if type(input) == "string" then
if type(input) == "string" then
-- check for fraction notation
-- Check for fraction notation
if input:match("/") == "/" then
if input:match("/") == "/" then
local numerator, denominator = input:match("^%s*([0-9]+)[/?]([0-9]+)%s*$")
local numerator, denominator = input:match("^%s*([0-9]+)[/?]([0-9]+)%s*$")
Line 50: Line 50:
end
end


-- return logarithm base b of x
-- Return logarithm base b of x
function p.log(frame)
function p.log(frame)
local args = get_args(frame)
local args = get_args(frame)
Line 57: Line 57:


local LN_2 = math.log(2)
local LN_2 = math.log(2)
-- return logarithm base 2 of x
-- Return logarithm base 2 of x
function p.log2(x)
function p.log2(x)
return math.log(x) / LN_2
return math.log(x) / LN_2
Line 70: Line 70:
end
end


-- return greatest common divisor of a and b
-- Return greatest common divisor of a and b
function p.gcd(frame)
function p.gcd(frame)
local args = get_args(frame)
local args = get_args(frame)
Line 84: Line 84:
end
end


-- return x rounded to places decimal places
-- Return x rounded to places decimal places
function p.round_dec(frame)
function p.round_dec(frame)
local args = get_args(frame)
local args = get_args(frame)
Line 98: Line 98:
end
end


-- return x rounded to a precision of prec significant figures
-- Return x rounded to a precision of prec significant figures
function p.round(frame)
function p.round(frame)
local args = get_args(frame)
local args = get_args(frame)
Line 116: Line 116:
end
end


-- cached list of primes for is_prime
-- Cached list of primes for is_prime
local primes_cache = {
local primes_cache = {
[0] = false,
[0] = false,
Line 122: Line 122:
}
}


-- returns true if integer n is prime; cannot be used with {{#invoke:}}
-- Returns true if integer n is prime; cannot be used with {{#invoke:}}
function p.is_prime(n)
function p.is_prime(n)
local cached = primes_cache[n]
local cached = primes_cache[n]
Line 138: Line 138:
end
end


-- returns prime factorization of integer n > 1; cannot be used with {{#invoke:}}
-- Returns prime factorization of integer n > 1; cannot be used with {{#invoke:}}
-- note: the order of keys is not specified for Lua tables
-- Note: the order of keys is not specified for Lua tables
function p.prime_factorization_raw(n)
function p.prime_factorization_raw(n)
local factors = {}
local factors = {}
Line 159: Line 159:
end
end


-- returns prime factorization of integer n > 2 (with wiki markup for exponents)
-- Returns prime factorization of integer n > 2 (with wiki markup for exponents)
function p.prime_factorization(frame)
function p.prime_factorization(frame)
local args = get_args(frame)
local args = get_args(frame)
Line 194: Line 194:
end
end


-- returns signum(x); cannot be used with {{#invoke:}}
-- Returns signum(x); cannot be used with {{#invoke:}}
function p.signum(x)
function p.signum(x)
if type(x) ~= "number" then
if type(x) ~= "number" then
Line 208: Line 208:
end
end


-- returns the next Young diagram of the same size or nil; cannot be used with {{#invoke:}}
-- Returns the next Young diagram of the same size or nil; cannot be used with {{#invoke:}}
-- modifies the input table
-- Modifies the input table
function p.next_young_diagram(d)
function p.next_young_diagram(d)
if #d == 0 then
if #d == 0 then

Revision as of 14:09, 21 April 2025

Module documentation[view] [edit] [history] [purge]

This module provides several mathematical functions which are likely to be used frequently on the Xenharmonic Wiki.

Namely, the functions in this module can be called from other modules by using require("Module:Utils") and calling the underscore-prefixed functions.

Functions

trim(s)
Removes leading and trailing whitespaces (but not interior ones) from a string.
_yesno(frame)
Allows Module:Yesno, which is not invokable directly, to be accessed by templates through Template:Yesno.
table_contains(tbl, x)*
Check if table contains x.
index_of(array, index)*
Return the first index with the given value (or nil if not found).
value_provided(s)*
Checks if s is a non-empty string.
wlink(a, b)
Provides a link to Wikipedia.
eval_num_arg(input, def_value)*
Checks if input is a number; on error, use def_value.
log(x, b)
Returns the logarithm base b of x. Parameter b defaults to base 2 (octave) if it is omitted.
gcd(a, b)
Returns the greatest common divisor of a and b.
round_dec(x, places)
Returns x rounded to a precision of places decimal places. Parameter places defaults to 0 if it is omitted.
round(x, prec)
Returns x rounded to a precision of prec significant figures. Parameter prec defaults to 6 if it is omitted.
is_prime(n)*
Returns true if the given integer n is a prime number.
prime_factorization(n)
Returns the prime factorization of the given integer n using the exponential form (in wikitext).
prime_factorization_raw(n)*
Returns a table encoding the prime factorization of n.
signum(x)*
Returns 1 for positive numbers, −1 for negative ones, and 0 for zero and non-integer inputs.
next_young_diagram(d)
Returns the next Young diagram of the same size; the first one is [N], the last one is [1, 1, ..., 1]. After the last one, nil is returned. The input table is modified.


* These functions are designed to be used by other modules only; they cannot be called with {{#invoke: }}.


local get_args = require("Module:Arguments").getArgs
local p = {}

-- Trim a string
function p.trim(s)
   return s:match("^%s*(.-)%s*$")
end

-- Check if a table contains x
function p.table_contains(tbl, x)
	for i = 1, #tbl do
		if x == tbl[i] then
			return true
		end
	end
	return false
end

-- Return the first index with the given value (or nil if not found)
function p.index_of(array, value)
	for i, v in ipairs(array) do
		if v == value then
			return i
		end
	end
	return nil
end

-- Check whether the input is a non-empty string
function p.value_provided(s)
	return type(s) == "string" and #s > 0
end

-- Evaluate input on error use default; cannot be used with {{#invoke:}}
function p.eval_num_arg(input, def_value)
	local result = input
	if type(input) ~= "number" then
		result = def_value
		if type(input) == "string" then
			-- Check for fraction notation
			if input:match("/") == "/" then
				local numerator, denominator = input:match("^%s*([0-9]+)[/?]([0-9]+)%s*$")
				result = (tonumber(numerator) or def_value) / (tonumber(denominator) or 1)
			else
				result = tonumber(trim(input))
			end
		end
	end
	return result
end

-- Return logarithm base b of x
function p.log(frame)
	local args = get_args(frame)
	return p._log(args[1], args[2])
end

local LN_2 = math.log(2)
-- Return logarithm base 2 of x
function p.log2(x)
	return math.log(x) / LN_2
end

function p._log(x, b)
	-- x defaults to 0
	x = p.eval_num_arg(x, 0)
	-- b defaults to 2 ("octave")
	b = p.eval_num_arg(b, 2)
	return math.log(x) / math.log(b)
end

-- Return greatest common divisor of a and b
function p.gcd(frame)
	local args = get_args(frame)
	return p._gcd(args[1], args[2])
end

function p._gcd(a, b)
	if b ~= 0 then
		return p._gcd(b, a % b)
	else
		return math.abs(a)
	end
end

-- Return x rounded to places decimal places
function p.round_dec(frame)
	local args = get_args(frame)
	return p._round_dec(args[1], args[2])
end

function p._round_dec(x, places)
	-- x defaults to 0
	x = p.eval_num_arg(x, 0)
	-- places defaults to 0
	places = p.eval_num_arg(places, 0)
	return math.floor(x * 10 ^ places + 0.5) / 10 ^ places
end

-- Return x rounded to a precision of prec significant figures
function p.round(frame)
	local args = get_args(frame)
	return p._round(args[1], args[2])
end

function p._round(x, prec)
	-- x defaults to 0
	x = p.eval_num_arg(x, 0)
	-- prec defaults to 6
	prec = p.eval_num_arg(prec, 6)
	if x == 0 then
		return 0
	else
		return p._round_dec(x, prec - math.floor(p._log(math.abs(x), 10)) - 1)
	end
end

-- Cached list of primes for is_prime
local primes_cache = {
	[0] = false,
	[1] = false,
}

-- Returns true if integer n is prime; cannot be used with {{#invoke:}}
function p.is_prime(n)
	local cached = primes_cache[n]
	if cached ~= nil then
		return cached
	end
	for i = 2, math.sqrt(n) do
		if n % i == 0 then
			primes_cache[n] = false
			return false
		end
	end
	primes_cache[n] = true
	return true
end

-- Returns prime factorization of integer n > 1; cannot be used with {{#invoke:}}
-- Note: the order of keys is not specified for Lua tables
function p.prime_factorization_raw(n)
	local factors = {}
	local m = n
	for i = 2, math.sqrt(n) + 1 do
		while m % i == 0 do
			factors[i] = factors[i] or 0
			factors[i] = factors[i] + 1
			m = m / i
		end
		if m == 1 then
			break
		end
	end
	if m > 1 then
		factors[m] = factors[m] or 1
	end
	return factors
end

-- Returns prime factorization of integer n > 2 (with wiki markup for exponents)
function p.prime_factorization(frame)
	local args = get_args(frame)
	return p._prime_factorization(p.eval_num_arg(args[1], 12)) -- default to 12
end

function p._prime_factorization(n)
	if n <= 1 then
		return "n/a"
	end
	local factors, powers = {}, {}
	local new_number = n
	for i = 2, n do
		if p.is_prime(i) then
			if new_number % i == 0 then
				factors[#factors + 1] = i
				powers[#factors] = 0
				while new_number % i == 0 do
					powers[#factors] = powers[#factors] + 1
					new_number = new_number / i
				end
				if powers[#factors] > 1 then
					powers[#factors] = factors[#factors] .. "<sup>" .. powers[#factors] .. "</sup>"
				else
					powers[#factors] = factors[#factors]
				end
			end
		end
		if new_number == 1 then
			break
		end
	end
	return table.concat(powers, " × ")
end

-- Returns signum(x); cannot be used with {{#invoke:}}
function p.signum(x)
	if type(x) ~= "number" then
		return 0
	end
	if x > 0 then
		return 1
	end
	if x < 0 then
		return -1
	end
	return 0
end

-- Returns the next Young diagram of the same size or nil; cannot be used with {{#invoke:}}
-- Modifies the input table
function p.next_young_diagram(d)
	if #d == 0 then
		return nil
	end
	local i_from = nil
	local size = 0
	for i = #d, 1, -1 do
		if d[i] > 1 then
			i_from = i
			break
		end
		size = size + d[i]
	end
	if i_from == nil then
		return nil
	end
	d[i_from] = d[i_from] - 1
	size = size + 1
	-- repacking the tail
	local max_d = d[i_from]
	for i = i_from + 1, #d + 1 do
		if size >= max_d then
			d[i] = max_d
			size = size - max_d
		elseif size > 0 then
			d[i] = size
			size = 0
		else
			d[i] = nil
		end
	end
	return d
end

-- stylua: ignore
p.primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
			   101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
			   211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271}

return p