local util = {}  local insert = table.insert local concat = table.concat local format = mw.ustring.format  --- -- Add all entries in `arr` into `target`. -- An error is raised if `overwrite` is not true -- and any key in `arr` is already in `target`. function util.addAll(target, arr, overwrite) 	if type(target) ~= "table" then 		error("target is not a table") 	end 	for key,value in pairs(arr) do 		if overwrite or target[key] == nil then 			target[key] = value 		else 			error("Duplicate key: " .. tostring(key)) 		end 	end end  local function comp(e1, e2) 	local t1 = type(e1) 	local t2 = type(e2) 	if t1 ~= t2 then return t1 < t2 end 	if t1 == "function" then 		error("Unexpected function type") 	end 	return e1 < e2 end  local arrayToStringAux arrayToStringAux = function(arr, indent) 	if type(arr) ~= "table" then 		error("arr is not a table") 	end 	if type(indent) ~= "number" then 		error("indent is not a number") 	end 	local result = {} 	local keys = {} 	for key in pairs(arr) do insert(keys, key) end 	table.sort(keys, comp) 	for _,key in ipairs(keys) do 		local value = arr[key] 		local keyPrint 		if type(key) == "string" then 			keyPrint = format("\"%s\"", key) 		else 			keyPrint = tostring(key) 		end 		local valuePrint 		if type(value) == "table" then 			valuePrint = format("{\n%s\n%s}", 				arrayToStringAux(value, indent + 4), 				string.rep(" ", indent)) 		elseif type(value) == "string" then 			valuePrint = format("\"%s\"", value) 		else 			valuePrint = tostring(value) 		end 		insert(result, format("%s[%s] = %s", 			string.rep(" ", indent), 			keyPrint, 			valuePrint)) 	end 	return concat(result, ", \n") end  --- Return a string representation of `arr`. function util.arrayToString(arr, indent) 	return arrayToStringAux(arr, indent or 0) end  local function convert(distance, multiplier, desiredPrec) 	if type(distance) ~= "string" then 		error("distance is not a string") 	end 	if type(multiplier) ~= "number" then 		error("multiplier is not a number") 	end 	-- Import math functions. 	local math = require "Module:Math" 	-- This function returns the precision of a given string representing a number. 	local precision = math._precision 	-- This function returns the order of magnitude of a given string representing a number. 	local order = math._order 	-- This function rounds a given number to the given number of digits. 	local round = math._precision_format  	local prec = desiredPrec or precision(distance) 	if not desiredPrec then 		local ord = order(distance) 		-- Adjust precision based on multiplier, as done in . 		prec = prec - order(multiplier / 0.2) 	end  	local converted = distance * multiplier 	local magnitude = order(converted) 	if prec <= -magnitude then 		-- Ensure the result has at least two significant digits. 		prec = -magnitude + 1 	end 	return round(converted, prec) end  --[[- Convert length specified in one unit (mi or km) to length in the other unit. @param #map<#string, #string> lengths 	a map from unit to distance (as a string) in that unit; 	may contain entry `prec` indicating desired conversion precision @param #string blank text to be used if length is unspecified @return #table a table containing the conversion result: 	orig = source unit; 	comp = target unit; 	mi = length in miles; 	ft = converted length in feet; 	km = length in kilometers; 	m = converted length in meters; 	error = error message, if any ]] function util.convertLengths(lengths, blank) 	-- Import math functions. 	local math = require "Module:Math" 	-- In Lua, storing functions locally results in more efficient execution. 	-- This function rounds a given number to the given number of digits. 	local round = math._precision_format 	-- This function returns the precision of a given string representing a number. 	local precision = math._precision  	local kmPerMile = 1.609344 	local ftPerMile = 5280 	-- The length in kilometers as passed to the function. 	local km = lengths.km 	-- The length in miles as passed to the function. 	local mi = lengths.mi 	-- Precision for the converted length. 	local prec = lengths.prec 	local errMsg = {} 	-- Sanitize inputs. 	local km_ = tonumber(km) 	if km and not km_ then 		insert(errMsg, util.err("km is not a number")) 	end 	local mi_ = tonumber(mi) 	if mi and not mi_ then 		insert(errMsg, util.err("mi is not a number")) 	end 	local prec_ = tonumber(prec) 	if prec and not prec_ then 		insert(errMsg, util.err("prec is not a number")) 	end 	prec = prec_  	local ft 	local m 	local orig = "mi" 	local comp = "km" 	if mi and km then 		insert(errMsg, util.err("Both mi and km are specified")) 	elseif mi then 		-- Length in miles was passed. 		if mi_ then 			-- If `mi` is indeed a number, compute and round the length in kilometers. 			km = convert(mi, kmPerMile, prec) 			m = convert(mi, kmPerMile * 1000, prec) 			-- format mi (insert separators as in 1,000) 			mi = round(mi_, precision(mi)) 		else 			-- `mi` is not a number. 			km = blank 			m = blank 		end 	elseif km then 		-- Length in kilometers was passed. 		-- Swap units. 		orig, comp = comp, orig 		if km_ then 			-- If `km` is indeed a number, compute and round the length in miles. 			mi = convert(km, 1 / kmPerMile, prec) 			ft = convert(km, ftPerMile / kmPerMile, prec) 			-- format km (insert separators as in 1,000) 			km = round(km_, precision(km)) 		else 			-- `km` is not a number. 			mi = blank 			ft = blank 		end 	else 		mi = blank 		ft = blank 		km = blank 		m = blank 	end 	local error = concat(errMsg) 	if error == "" then error = nil end 	return {mi = mi, ft = ft, km = km, m = m, orig = orig, comp = comp, 		error = error} end  --- Generates wikitext error messages. function util.err(msg) 	if msg == nil then 		error("Unspecified error message") 	end 	return format('Error: %s', msg) end  return util