local p = {}  local getArgs  function p.main(frame) 	if not getArgs then 		getArgs = require('Module:Arguments').getArgs 	end  	local args = getArgs(frame, {wrappers = 'টেমপ্লেট:Gapnum'}) 	local n = args[1]  	if not n then 		error('Parameter 1 is required') 	elseif not tonumber(n) and not tonumber(n, 36) then -- Validates any number with base ≤ 36 		error('Unable to convert "' .. args[1] .. '" to a number') 	end  	local gap = args.gap 	local precision = tonumber(args.prec)  	return p.gaps(n,{gap=gap,prec=precision}) end  -- Not named p._main so that it has a better function name when required by Module:Val function p.gaps(n,tbl) 	local nstr = tostring(n) 	if not tbl then 		tbl = {} 	end 	local gap = tbl.gap or '.25em'  	local int_part, frac_part = p.groups(n,tbl.prec)  	local ret = mw.html.create('span') 							:css('white-space','nowrap') 							-- No gap necessary on first group 							:wikitext(table.remove(int_part,1))  	-- Build int part 	for _, v in ipairs(int_part) do 		ret:tag('span') 				:css('margin-left',gap) 				:wikitext(v) 	end  	if frac_part then 		-- The first group after the decimal shouldn't have a gap 		ret:wikitext('.' .. table.remove(frac_part,1)) 		-- Build frac part 		for _, v in ipairs(frac_part) do 			ret:tag('span') 					:css('margin-left',gap) 					:wikitext(v) 		end 	end  	return ret end  -- Creates tables where each element is a different group of the number function p.groups(num,precision) 	local nstr = tostring(num) 	if not precision then 		precision = -1 	end  	local decimalloc = nstr:find('.', 1, true) 	local int_part, frac_part 	if decimalloc == nil then 		int_part = nstr 	else 		int_part = nstr:sub(1, decimalloc-1) 		frac_part = nstr:sub(decimalloc + 1) 	end 	-- only define ret_i as an empty table, let ret_d stay nil 	local ret_i,ret_d = {} 	-- Loop to handle most of the groupings; from right to left, so that if a group has less than 3 members, it will be the first group 	while int_part:len() > 3 do 		-- Insert in first spot, since we're moving backwards 		table.insert(ret_i,1,int_part:sub(-3)) 		int_part = int_part:sub(1,-4) 	end 	-- handle any left over numbers 	if int_part:len() > 0 then 		table.insert(ret_i,1,int_part) 	end  	if precision ~= 0 and frac_part then 		ret_d = {} 		if precision == -1 then 			precision = frac_part:len() 		end 		-- Reduce the length of the string if required precision is less than actual precision 		-- OR 		-- Increase it (by adding 0s) if the required precision is more than actual 		local offset = precision - frac_part:len() 		if offset < 0 then 			frac_part = frac_part:sub(1,precision) 		elseif offset > 0 then 			frac_part = frac_part .. string.rep('0', offset) 		end  		-- Allow groups of 3 or 2 (3 first) 		for v in string.gmatch(frac_part,'%d%d%d?') do 			table.insert(ret_d,v) 		end 		-- Preference for groups of 4 instead of groups of 1 at the end 		if #frac_part % 3 == 1 then 			if frac_part:len() == 1 then 				ret_d = {frac_part} 			else 				local last_g = ret_d[#ret_d] or '' 				last_g = last_g..frac_part:sub(-1) 				ret_d[#ret_d] = last_g 			end 		end 	end  	return ret_i,ret_d end  local default_method = 2  -- 2 or 3 for default grouping method local default_gaps3 = false  -- if true, group only in threes after decimal mark; example: "1.234 5" rather than "1.2345" function p.groups_val(text, method) 	-- Parameter text is a number as a string with an optional '.'. 	-- Parameter method is a number or nil: 	--   3 for 3-digit grouping, or 	--   2 for 3-then-2 grouping (for digits before decimal mark). 	-- Return one or two lists of digit groups. 	-- The first list has the groups before any decimal mark. 	-- If there is a decimal mark, the second list has the groups after the mark. 	method = method or default_method 	local len_right  -- nil or number of digits after decimal mark (0 or more) 	local len_left = text:find('.', 1, true) 	if len_left then 		len_right = #text - len_left 		len_left = len_left - 1 	else 		len_left = #text 	end 	local n3, n2, nR  -- number of three-groups, two-groups, remainder digits 	-- Handle left-hand side (digits before decimal mark). 	if method == 3 then 		n3 = math.floor(len_left / 3) 		n2 = 0 		nR = math.fmod(len_left, 3) 	elseif len_left < 3 then 		n3 = 0 		n2 = math.floor(len_left / 2) 		nR = math.fmod(len_left, 2) 	else 		n3 = 1 		n2 = math.floor((len_left - 3) / 2) 		nR = math.fmod((len_left - 3), 2) 	end 	local l_groups = {} 	if nR > 0 then 		table.insert(l_groups, text:sub(1, nR)) 	end 	local pos = nR + 1 	for _ = 1, n2 do 		table.insert(l_groups, text:sub(pos, pos + 1)) 		pos = pos + 2 	end 	for _ = 1, n3 do 		table.insert(l_groups, text:sub(pos, pos + 2)) 		pos = pos + 3 	end 	-- Handle right-hand side (digits after decimal mark). 	-- Methods 2 and 3 are the same (group by three or possibly four for last group). 	local r_groups 	if len_right then 		n3 = math.floor(len_right / 3) 		nR = math.fmod(len_right, 3) 		pos = len_left + 2 		local extra 		if n3 > 0 and nR == 1 and not default_gaps3 then 			extra = true  -- append extra digit to last group 			nR = 0 		end 		r_groups = {} 		for i = 1, n3 do 			local x = (extra and i == n3) and 1 or 0 			table.insert(r_groups, text:sub(pos, pos + 2 + x)) 			pos = pos + 3 + x 		end 		if nR > 0 then 			table.insert(r_groups, text:sub(pos, pos + nR - 1)) 		end 	end 	return l_groups, r_groups end  return p