Module:Convert: Difference between revisions

Content deleted Content added
implement built-in units for 'hand' and 'Mach'; other tweaks
improvements to disp=xxx and handling of ranges and more
Line 362:
end
if prefix then
result.prefixvprefix = prefix
else
result.prefixvprefix = false -- to avoid calling __index
end
result.sp_us = force_sp_us
Line 605:
exp = exp + 1
end
local digits = format('%.0f', floor((10^(frac + sigfig)) + 0.5))
if #digits > sigfig then
-- Overflow (for sigfig=3: like 0.9999 rounding to "1000"; need "100").
Line 803:
return false, { missing[which] } -- should never occur
end
local propersign, negativeisnegative
if sign == MINUS or sign == '-' or sign == '−' then
propersign = MINUS
negativeisnegative = true
elseif sign == '+' then
propersign = '+'
negativeisnegative = false
elseif sign == '' then
propersign = ''
negativeisnegative = false
else
return false, { invalid[which], text }
Line 820:
if value == nil then
if not no_fraction then
value, show = extract_fraction(clean, negativeisnegative)
end
if value == nil then
Line 828:
end
if show == nil then
singular = (value == 1 and not negativeisnegative)
show = propersign .. with_separator(clean)
end
if negativeisnegative and (value ~= 0) then
value = -value
end
Line 852:
end
return true, tonumber(text)
end
 
local function range_text(range, want_name, parms, before, after)
-- Return before .. rtext .. after
-- where rtext is the text that separates two values in a range.
local rtextadj = range[1]parms.adj
local rtext, =adj_text, range[2]exception
if type(rtextrange) == 'table' then
-- Table must specify range text for abbr=off and for abbr=on,
-- and may specify range text for 'adj=on',
-- and may specify exception = true.
rtext = rtextrange[abbr]want_name and 'off' or rtext['on']
local rtextadj_text = range[2'adj']
exception = range['exception']
else
rtext = endrange
end
if type(rtext)adj == 'tableon' then
if want_name or (exception and parms.abbr_org == 'on') then
rtext = rtext[abbr]adj_text or rtext[:gsub(' ', '-'):gsub(' ', 'on-'])
end
end
if rtext == '–' and after:sub(1, #MINUS) == MINUS then
if type(rtext) == 'table – ' then
end
return before .. rtext .. after
end
 
Line 866 ⟶ 892:
-- whitespace entered in the template, and whitespace is used by some
-- parameters (example: the numbered parameters associated with "disp=x").
local range_types = { -- text to separate input,values outputin ranges;a for 'x', depends on abbrrange
['andby'] = { ' andby ', ' and ' },
['by-'] = { ' by ', ' by ' },
['toand'] = { ['off'] to= ' and ', [' toon'] = ' and ', exception = true },
['-or'] = { ['off'] = ' or ' , ['on'] = ' or ' , exception = true },
['to(-)'] = { [' off'] = ' to ' , ['on'] = ' to ' , exception = true },
['xxx'] = {{ ['out'] = ' by ' , ['in'] = ' × ', ['off'] = ' by ', ['on'] = ' × ' },
{ ['outto(-)'] = ' × ', ['in'] = ' by ' ,{ ['off'] = ' by to ', ['on'] = ' × ' },
['+/-'] = { ['off'] = ' ± ', ['on'] = ' ± ', is_range_x['adj'] = true' ± ' },
['+/-x'] = { [' ± off'] = ' by ', [' ±on'] = ' × ', is_range_x = true },
}
local range_aliases = {
['and(-)'] = 'and',
['&'] = 'and',
['–'] = '-',
['to-–'] = 'to(-)',
['×to-'] = 'xto(-)',
['±×'] = '+/-x',
['±'] = '+/-',
}
local success, info1, info2
Line 999 ⟶ 1,026:
end
end
-- Change disp to standard name so subsequent processing can ignore aliases.
local disp = args.disp
if disp == 'x5' then
args.joinsdisp5 = { args[i] or '', args[i+1] or '' }true
disp == 'u2' orelseif disp == 'unit2flip5' then
args.disp5 = true
args.disp = 'flip'
elseif disp == 'number' then
args.disp = 'output number only'
elseif disp == 'out' or disp == '2' then
args.disp = 'output only'
elseif disp == 'u2' then
args.disp = 'unit2'
elseif disp == 's' or disp == '/' then
args.disp = 'slash'
end
disp = args.disp
if type(rtext)disp == 'tablex' then
args.joins = { args[i] or '', args[i+1] or '' }
end
args.precision = args.precision or precision -- allow named parameter
Line 1,049 ⟶ 1,090:
(in_current.exception == 'temperature' or out_current.exception == 'temperature'))
if exception then
-- Kelvin value can be almost zero, or small but negative due to precision problems.
-- Also, an input value like -300 C (below absolute zero) gives negative kelvins.
-- Calculate minimum precision from absolute value.
adjust = 0
local kelvin = math.abs((invalue - in_current.offset) * in_current.scale)
if kelvin <= 01e-8 then -- canassume getnonzero zero,due orto smallinput butor negative value due tocalculation precision problemsproblem
minprec = 2
else
Line 1,218 ⟶ 1,262:
local precision = parms.precision
local sigfig = parms.sigfig
local dispdisp5 = parms.dispdisp5
if precision then
-- Ignore sigfig, dispdisp5.
success, precision = require_integer(precision, 'cvt_bad_prec')
if not success then return false, precision end
elseif sigfig then
-- Ignore dispdisp5.
success, sigfig = require_integer(sigfig, 'cvt_bad_sigfig')
if not success then return false, sigfig end
Line 1,231 ⟶ 1,275:
end
show, exponent = make_sigfig(outvalue, sigfig)
elseif disp == '5'disp5 then
show = format('%.0f', floor((outvalue / 5) + 0.5) * 5)
else
Line 1,256 ⟶ 1,300:
precision = -precision -- #digits to zero (in addition to digits after dot)
local shift = 10 ^ precision
ifshow shift= >format('%.0f', outvalue then/shift)
if show ~= '0' -- like old template, user can zero all digitsthen
else
show = format('%.0f', floor(outvalue/shift + 0.5))
exponent = #show + precision
end
Line 1,299 ⟶ 1,341:
['slash-nosp'] = { '/' , '' },
['b'] = { ' (' , ')' },
['br'] = { '<br/>' , '' },
}
 
Line 1,511 ⟶ 1,554:
local lk = parms.lk
local usename = unit_table.usename
local singular = valinfo[which].singular or (inout == 'in' and adj == 'on')
if usename then
-- Old template does something like this.
Line 1,536 ⟶ 1,579:
singular = false -- so 1 e3kg gives 1 thousand kilograms (plural)
end
local key_name = (adj == 'on' or (singular and not parms.is_range_x)) and 'name1' or 'name2'
local key_symbol = 'symbol'
if unit_table.sp_us then
Line 1,547 ⟶ 1,590:
else
if abbr_org == nil then
if disp == 'br' or disp == 'or' or disp == 'slash' then
want_name = true
end
Line 1,576 ⟶ 1,619:
local engscale = unit_table.engscale
if engscale then
local inout = unit_table.inout
local info = unit_table.valinfo[which]
local abbr = parms.abbr
if abbr == 'on' or abbr == unit_table.inout then
info.show = info.show ..
'<span style="margin-left:0.2em">×<span style="margin-left:0.1em">10</span></span><s style="display:none">^</s><sup>'
Line 1,585 ⟶ 1,629:
local number_id
local lk = parms.lk
if lk == 'on' or lk == 'in'inout then
number_id = engscale[2] or engscale[1]
else
number_id = engscale[1]
end
info.show = info.show .. (parms.adj == 'on' and '-' or ' ') .. number_id
end
end
local prefix = unit_table.prefixvprefix
if prefix then
local info = unit_table.valinfo[which]
Line 1,605 ⟶ 1,649:
local disp = parms.disp
if disp == 'output only' or
disp == 'output number only' or
disp == 'numberunit2' orthen
disp == 'u2' or disp == 'unit2' then
parms.joins = { '', '' }
return ''
Line 1,624 ⟶ 1,668:
id1 = id1 .. ' ' .. make_id(parms, 1, second_unit)
end
if want_name and parms.adj == 'on' then
return hyphenated(id1)
end
Line 1,657 ⟶ 1,701:
local result = prefix .. valinfo[1].show
if range then
local rtextresult = range_text(range, want_name, parms, result, prefix .. valinfo[12].show)
if type(rtext) == 'table' then
rtext = rtext[abbr] or rtext['off']
end
result = result .. rtext .. prefix .. valinfo[2].show
end
return result
Line 1,677 ⟶ 1,717:
local id = (range == nil) and id1 or make_id(parms, 2, first_unit)
if id ~= '' then
if want_name and parms.adj == 'on' then
mos = false -- if hyphenated, suppress repeat of unit in a range
extra = '-' .. hyphenated(id) .. parms.mid
Line 1,689 ⟶ 1,729:
result = valinfo[1].show
else
local rtext = range[1]
if type(rtext) == 'table' then
rtext = rtext[abbr] or rtext['off']
end
if mos then
decorate_value(parms, in_current, 1)
decorate_value(parms, in_current, 2)
result = valinfo[1].show .. sep .. id1 .. rtext .. valinfo[2].show
elseif parms.is_range_x and not want_name then
if abbr == 'in' or abbr == 'on' then
Line 1,702 ⟶ 1,738:
end
decorate_value(parms, in_current, 2)
result = valinfo[1].show .. sep .. id .. rtext .. valinfo[2].show
else
if abbr == 'in' or abbr == 'on' then
Line 1,708 ⟶ 1,744:
end
decorate_value(parms, in_current, 2)
result = valinfo[1].show .. rtext .. valinfo[2].show
end
result = resultrange_text(range, ..want_name, rtextparms, .. prefix ..result, valinfo[2].show)
end
return result .. extra
Line 1,719 ⟶ 1,756:
local id1, want_name = make_id(parms, 1, out_current)
local disp = parms.disp
if disp == 'u2' or disp == 'unit2' then
if want_name and parms.adj == 'on' then
return hyphenated(id1)
end
Line 1,731 ⟶ 1,768:
local result = prefix .. valinfo[1].show
if range then
local rtextresult = range_text(range, want_name, parms, result, prefix .. valinfo[12].show)
if type(rtext) == 'table' then
rtext = rtext[parms.abbr] or rtext['off']
end
result = result .. rtext .. prefix .. valinfo[2].show
end
return result
end
local result
local extra, id, sep = '', '', ''
local range = parms.range
if not (disp =~= 'output number only' or disp == 'number') then
local id = (range == nil) and id1 or make_id(parms, 2, out_current)
if id ~= '' then
extrasep = out_current.sep .. id
if type(rtext)want_name and parms.adj == 'tableon' then
extra = '-' .. hyphenated(id)
else
rtextextra = rtext[abbr]sep or.. rtext['off']id
end
end
end
Line 1,754 ⟶ 1,792:
else
local abbr = parms.abbr
local rtext = range[2]
if type(rtext) == 'table' then
rtext = rtext[abbr] or rtext['on']
end
if parms.is_range_x and not want_name then
if abbr == 'out' or abbr == 'on' then
Line 1,763 ⟶ 1,797:
end
decorate_value(parms, out_current, 2)
result = valinfo[1].show .. extrasep .. rtext .. valinfo[2].showid
else
if abbr == 'out' or abbr == 'on' then
Line 1,769 ⟶ 1,803:
end
decorate_value(parms, out_current, 2)
result = valinfo[1].show .. rtext .. valinfo[2].show
end
result = resultrange_text(range, ..want_name, rtextparms, .. prefix ..result, valinfo[2].show)
end
return result .. extra
Line 1,856 ⟶ 1,891:
local range = parms.range
if range then
local rtext = range[2]
if type(rtext) == 'table' then
rtext = rtext[abbr] or rtext['on']
end
local success, result2 = make_result(valinfo[2])
if not success then return false, result2 end
result = resultrange_text(range, ..want_name, rtextparms, ..result, result2)
end
return true, result