From 994f59501b9eecf736792d256434ceb7d519adc7 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 4 Jan 2019 08:46:26 +0100 Subject: util.human.units: A library for formatting numbers with SI units --- util/human/units.lua | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 util/human/units.lua (limited to 'util/human/units.lua') diff --git a/util/human/units.lua b/util/human/units.lua new file mode 100644 index 00000000..2c4662cd --- /dev/null +++ b/util/human/units.lua @@ -0,0 +1,58 @@ +local large = { + "k", 1000, + "M", 1000000, + "G", 1000000000, + "T", 1000000000000, + "P", 1000000000000000, + "E", 1000000000000000000, + "Z", 1000000000000000000000, + "Y", 1000000000000000000000000, +} +local small = { + "m", 0.001, + "μ", 0.000001, + "n", 0.000000001, + "p", 0.000000000001, + "f", 0.000000000000001, + "a", 0.000000000000000001, + "z", 0.000000000000000000001, + "y", 0.000000000000000000000001, +} + +local binary = { + "Ki", 2^10, + "Mi", 2^20, + "Gi", 2^30, + "Ti", 2^40, + "Pi", 2^50, + "Ei", 2^60, + "Zi", 2^70, + "Yi", 2^80, +} + +-- n: number, the number to format +-- unit: string, the base unit +-- b: optional enum 'b', thousands base +local function format(n, unit, b) --> string + local round = math.floor; + local prefixes = large; + local logbase = 1000; + local fmt = "%.3g %s%s"; + if n == 0 then + return fmt:format(n, "", unit); + end + if b == 'b' then + prefixes = binary; + logbase = 1024; + elseif n < 1 then + prefixes = small; + round = math.ceil; + end + local m = math.max(0, math.min(8, round(math.abs(math.log(math.abs(n), logbase))))); + local prefix, multiplier = table.unpack(prefixes, m * 2-1, m*2); + return fmt:format(n / (multiplier or 1), prefix or "", unit); +end + +return { + format = format; +}; -- cgit v1.2.3 From b95b0e602662861b8db5524d5e5971a927fb076f Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Wed, 3 Jun 2020 19:46:17 +0200 Subject: util.human.units: Handle location of unpack() in Lua 5.1 --- util/human/units.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'util/human/units.lua') diff --git a/util/human/units.lua b/util/human/units.lua index 2c4662cd..91d6f0d5 100644 --- a/util/human/units.lua +++ b/util/human/units.lua @@ -1,3 +1,5 @@ +local unpack = table.unpack or unpack; --luacheck: ignore 113 + local large = { "k", 1000, "M", 1000000, @@ -49,7 +51,7 @@ local function format(n, unit, b) --> string round = math.ceil; end local m = math.max(0, math.min(8, round(math.abs(math.log(math.abs(n), logbase))))); - local prefix, multiplier = table.unpack(prefixes, m * 2-1, m*2); + local prefix, multiplier = unpack(prefixes, m * 2-1, m*2); return fmt:format(n / (multiplier or 1), prefix or "", unit); end -- cgit v1.2.3 From b73cad7f8e92862a77d03ecc3eb9e24bb389cc07 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Wed, 3 Jun 2020 20:16:00 +0200 Subject: util.human.units: Put math functions into locals Primarily because the next commit will deal with math.log behaving differently on Lua 5.1 and that's eaiser with locals. --- util/human/units.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'util/human/units.lua') diff --git a/util/human/units.lua b/util/human/units.lua index 91d6f0d5..471c82a0 100644 --- a/util/human/units.lua +++ b/util/human/units.lua @@ -1,3 +1,9 @@ +local math_abs = math.abs; +local math_ceil = math.ceil; +local math_floor = math.floor; +local math_log = math.log; +local math_max = math.max; +local math_min = math.min; local unpack = table.unpack or unpack; --luacheck: ignore 113 local large = { @@ -36,7 +42,7 @@ local binary = { -- unit: string, the base unit -- b: optional enum 'b', thousands base local function format(n, unit, b) --> string - local round = math.floor; + local round = math_floor; local prefixes = large; local logbase = 1000; local fmt = "%.3g %s%s"; @@ -48,9 +54,9 @@ local function format(n, unit, b) --> string logbase = 1024; elseif n < 1 then prefixes = small; - round = math.ceil; + round = math_ceil; end - local m = math.max(0, math.min(8, round(math.abs(math.log(math.abs(n), logbase))))); + local m = math_max(0, math_min(8, round(math_abs(math_log(math_abs(n), logbase))))); local prefix, multiplier = unpack(prefixes, m * 2-1, m*2); return fmt:format(n / (multiplier or 1), prefix or "", unit); end -- cgit v1.2.3 From b2ad87f966f17bacb36366f9e3bf21c21c31b6f7 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Wed, 3 Jun 2020 20:17:33 +0200 Subject: util.human.units: Handle lack of math.log(n, base) on Lua 5.1 --- util/human/units.lua | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'util/human/units.lua') diff --git a/util/human/units.lua b/util/human/units.lua index 471c82a0..5a083783 100644 --- a/util/human/units.lua +++ b/util/human/units.lua @@ -6,6 +6,14 @@ local math_max = math.max; local math_min = math.min; local unpack = table.unpack or unpack; --luacheck: ignore 113 +if math_log(10, 10) ~= 1 then + -- Lua 5.1 COMPAT + local log10 = math.log10; + function math_log(n, base) + return log10(n) / log10(base); + end +end + local large = { "k", 1000, "M", 1000000, -- cgit v1.2.3 From 8c7811ec43bd254b110319f983043e5fa16dcabf Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 4 Jun 2020 16:56:28 +0200 Subject: util.human.units: Factor out function for getting multiplier --- util/human/units.lua | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'util/human/units.lua') diff --git a/util/human/units.lua b/util/human/units.lua index 5a083783..af233e98 100644 --- a/util/human/units.lua +++ b/util/human/units.lua @@ -46,17 +46,10 @@ local binary = { "Yi", 2^80, } --- n: number, the number to format --- unit: string, the base unit --- b: optional enum 'b', thousands base -local function format(n, unit, b) --> string +local function adjusted_unit(n, b) local round = math_floor; local prefixes = large; local logbase = 1000; - local fmt = "%.3g %s%s"; - if n == 0 then - return fmt:format(n, "", unit); - end if b == 'b' then prefixes = binary; logbase = 1024; @@ -66,9 +59,22 @@ local function format(n, unit, b) --> string end local m = math_max(0, math_min(8, round(math_abs(math_log(math_abs(n), logbase))))); local prefix, multiplier = unpack(prefixes, m * 2-1, m*2); - return fmt:format(n / (multiplier or 1), prefix or "", unit); + return multiplier or 1, prefix; +end + +-- n: number, the number to format +-- unit: string, the base unit +-- b: optional enum 'b', thousands base +local function format(n, unit, b) --> string + local fmt = "%.3g %s%s"; + if n == 0 then + return fmt:format(n, "", unit); + end + local multiplier, prefix = adjusted_unit(n, b); + return fmt:format(n / multiplier, prefix or "", unit); end return { + adjust = adjusted_unit; format = format; }; -- cgit v1.2.3