Module:sandbox/foreign numerals

Hello, you have come here looking for the meaning of the word Module:sandbox/foreign numerals. In DICTIOUS you will not only get to know all the dictionary meanings for the word Module:sandbox/foreign numerals, but we will also tell you about its etymology, its characteristics and you will know how to say Module:sandbox/foreign numerals in singular and plural. Everything you need to know about the word Module:sandbox/foreign numerals you have here. The definition of the word Module:sandbox/foreign numerals will help you to be more precise and correct when speaking or writing your texts. Knowing the definition ofModule:sandbox/foreign numerals, as well as those of other words, enriches your vocabulary and provides you with more and better linguistic resources.


local export = {}

-- Roman numerals

local from_Roman_tab = {
	M  = 1000; CM = 900; D  = 500; CD = 400;
	C  =  100; XC =  90; L  =  50; XL =  40;
	X  =   10; IX =   9; V  =   5; IV =   4;
	I  =    1;
}

local to_Roman_tab = {
	{ 1000, "M"  }; {  900, "CM" }; {  500, "D"  }; {  400, "CD" };
	{  100, "C"  }; {   90, "XC" }; {   50, "L"  }; {   40, "XL" };
	{   10, "X"  }; {    9, "IX" }; {    5, "V"  }; {    4, "IV" };
	{    1, "I"  };
}

local new_to_Roman_tab = {}

local overline = mw.ustring.char(0x305)
local double_overline = mw.ustring.char(0x33F)
for _, v in ipairs(to_Roman_tab) do
	local number, symbol = unpack(v)
	if number > 1 then
		table.insert(new_to_Roman_tab, { number * 1000, (symbol:gsub(".", "%1" .. overline)) })
		table.insert(new_to_Roman_tab, { number * 1000000, (symbol:gsub(".", "%1" .. double_overline)) })
	end
end

for _, v in ipairs(to_Roman_tab) do
	table.insert(new_to_Roman_tab, v)
end

to_Roman_tab = new_to_Roman_tab

function export.to_Roman(numeral)
	if type(numeral) == 'table' then
		numeral = tonumber(numeral.args)
	end
	
	local output = {}
	for _, item in ipairs(to_Roman_tab) do
		local limit, letter = item, item
		while numeral >= limit do
			table.insert(output, letter)
			numeral = numeral - limit
		end
	end

	return table.concat(output)
end

function export.from_Roman(numeral)
	if type(numeral) == 'table' then
		numeral = numeral.args
	end
	if tonumber(numeral) then
		return tonumber(numeral)	
	end
	
	local accum = 0
	-- shame on Lua for having no regex alternations...

	while numeral ~= "" do
		local l2, l1 = numeral:sub(1, 2), numeral:sub(1, 1)
		if from_Roman_tab then
			accum = accum + from_Roman_tab
			numeral = numeral:sub(3)
		elseif from_Roman_tab then
			accum = accum + from_Roman_tab
			numeral = numeral:sub(2)
		else
			return nil
		end
	end
	
	return accum
end

-- Armenian numerals

local from_Armenian_tab = {
	 =    1;  =    2;  =    3;  =    4;  =    5;  =    6;  =    7;  =    8;  =    9;
	 =   10;  =   20;  =   30;  =   40;  =   50;  =   60;  =   70;  =   80;  =   90;
	 =  100;  =  200;  =  300;  =  400;  =  500;  =  600;  =  700;  =  800;  =  900;
	 = 1000;  = 2000;  = 3000;  = 4000;  = 5000;  = 6000;  = 7000;  = 8000;  = 9000;
}

function export.from_Armenian(numeral)
	if type(numeral) == 'table' then
		numeral = numeral.args
	end
	if tonumber(numeral) then
		return tonumber(numeral)	
	end

	local accum = 0
	for char in mw.ustring.gmatch(numeral, ".") do
		local value = from_Armenian_tab
		if value then
			accum = accum + value
		else
			return nil
		end
	end

	return accum	
end

-- Hebrew numerals

local from_Hebrew_tab = {
	 = 1,
	 = 2,
	 = 3,
	 = 4,
	 = 5,
	 = 6,
	 = 7,
	 = 8,
	 = 9,
	 = 10,
	 = 20,
	 = 20,
	 = 30,
	 = 40,
	 = 40,
	 = 50,
	 = 50,
	 = 60,
	 = 70,
	 = 80,
	 = 80,
	 = 90,
	 = 90,
	 = 100,
	 = 200,
	 = 300,
	 = 400,
}

local to_Hebrew_ones = { = '', 'א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט'}
local to_Hebrew_tens = { = '', 'י', 'כ', 'ל', 'מ', 'נ', 'ס', 'ע', 'פ', 'צ'}
local to_Hebrew_hundreds = { = '', 'ק', 'ר', 'ש', 'ת', 'תק', 'תר', 'תש', 'תת', 'תתק'}
local to_Hebrew_special = {
	 = 'טו',
	 = 'טז',
}

-- This only works for numbers such that 0 < value < 1000, because beyond that the logic gets complicated
function export.from_Hebrew(numeral)
	if type(numeral) == 'table' then
		numeral = numeral.args
	end
	if tonumber(numeral) then
		return tonumber(numeral)
	end

	local value = 0
	for c in mw.ustring.gmatch(numeral, '') do
		value = value + (from_Hebrew_tab or 0)
	end

	if value == 0 then
		return nil
	end

	return value
end

-- This only works for numbers such that 0 < value < 1000, because beyond that the logic gets complicated
function export.to_Hebrew(value, use_gershayim)
	if type(value) == 'table' then
		use_gershayim = value.args ~= '' and value.args
		value = value.args
	end
	if type(value) ~= 'number' then
		if tonumber(value) then
			value = tonumber(value)
		else
			return nil
		end
	end

	if value <= 0 or value >= 1000 then
		return nil
	end

	local tens_and_ones = value % 100
	local hundreds = to_Hebrew_hundreds
	if to_Hebrew_special then
		tens_and_ones = to_Hebrew_special
	else
		local ones = tens_and_ones % 10
		local tens = (tens_and_ones - ones) / 10
		tens_and_ones = to_Hebrew_tens .. to_Hebrew_ones
	end

	local numeral = hundreds .. tens_and_ones

	if use_gershayim then
		if mw.ustring.match(numeral, '^.$') then
			numeral = numeral .. '׳'
		else
			numeral = mw.ustring.gsub(numeral, '.$', '״%0')
		end
	end

	return numeral
end

-- Decimal numerals

-- Generated from the names of code points with General Category Nd
-- and name ending in DIGIT ZERO
-- in http://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
-- by removing the DIGIT ZERO suffix, lowercasing, replacing a hyphen or space
-- with an underscore, and replacing DIGIT ZERO with latin:
--[[
local lines = {}
for hex, name in unicode_data:gmatch "%f(+);(+);Nd" do
	local code_point = tonumber(hex, 16)
	local script_name
	if name == "DIGIT ZERO" then
		script_name = "latin"
	else
		script_name = name:gsub(" DIGIT ZERO$", ""):lower():gsub("", "_")
	end
	table.insert(lines, "\t" .. script_name .. ' = "' .. mw.ustring.char(code_point) .. '",')
end

table.sort(lines)

print(table.concat(lines, "\n"))
--]]
local decimal_zero_characters = {
	adlam = "𞥐",
	ahom = "𑜰",
	arabic_indic = "٠",
	balinese = "᭐",
	bengali = "০",
	bhaiksuki = "𑱐",
	brahmi = "𑁦",
	chakma = "𑄶",
	cham = "꩐",
	devanagari = "०",
	dives_akuru = "𑥐",
	extended_arabic_indic = "۰",
	fullwidth = "0",
	gujarati = "૦",
	gunjala_gondi = "𑶠",
	gurmukhi = "੦",
	hanifi_rohingya = "𐴰",
	javanese = "꧐",
	kannada = "೦",
	kayah_li = "꤀",
	khmer = "០",
	khudawadi = "𑋰",
	lao = "໐",
	latin = "0",
	lepcha = "᱀",
	limbu = "᥆",
	malayalam = "൦",
	masaram_gondi = "𑵐",
	mathematical_bold = "𝟎",
	mathematical_double_struck = "𝟘",
	mathematical_monospace = "𝟶",
	mathematical_sans_serif = "𝟢",
	mathematical_sans_serif_bold = "𝟬",
	meetei_mayek = "꯰",
	modi = "𑙐",
	mongolian = "᠐",
	mro = "𖩠",
	myanmar = "၀",
	myanmar_shan = "႐",
	myanmar_tai_laing = "꧰",
	new_tai_lue = "᧐",
	newa = "𑑐",
	nko = "߀",
	nyiakeng_puachue_hmong = "𞅀",
	ol_chiki = "᱐",
	oriya = "୦",
	osmanya = "𐒠",
	pahawh_hmong = "𖭐",
	saurashtra = "꣐",
	segmented = "🯰",
	sharada = "𑇐",
	sinhala_lith = "෦",
	sora_sompeng = "𑃰",
	sundanese = "᮰",
	tai_tham_hora = "᪀",
	tai_tham_tham = "᪐",
	takri = "𑛀",
	tamil = "௦",
	telugu = "౦",
	thai = "๐",
	tibetan = "༠",
	tirhuta = "𑓐",
	vai = "꘠",
	wancho = "𞋰",
	warang_citi = "𑣠",
}

function export.convert_decimal(from, to, number)
	if type(from) == "table" then
		local frame = from
		local args = assert(frame.args)
		from, to, number = args, args, args
	end
	assert(from and to and number)
	local from_zero, to_zero =
		assert(decimal_zero_characters),
		assert(decimal_zero_characters)
	local get_code = mw.ustring.codepoint
	local get_char = mw.ustring.char
	local from_zero_code, to_zero_code = get_code(from_zero), get_code(to_zero)
	local converted = mw.ustring.gsub(
		number,
		"",
		function(digit)
			return get_char(get_code(digit) - from_zero_code + to_zero_code)
		end)
	return converted
end

-- Indian numerals

function export.from_Indian(numeral)
	if type(numeral) == 'table' then
		value = numeral.args
	else
		value = numeral
	end
	return export.convert_decimal("devanagari", "latin", value)
end

function export.to_Indian(numeral)
	if type(numeral) == 'table' then
		value = numeral.args
	else
		value = numeral
	end
	return export.convert_decimal("latin", "devanagari", numeral)
end

return export