Re: lib/60635: humanize_number(3): exa/exbi issues

Taylor R Campbell <[email protected]>
Newsgroups gmane.os.netbsd.bugs
Message-ID <[email protected]>
pr60635-humanizeiec.patch (text/plain, 5.4 KB)
# HG changeset patch
# User Taylor R Campbell <[email protected]>
# Date 1787506011 0
#      Sun Aug 23 17:26:51 2026 +0000
# Branch trunk
# Node ID cc8c7b6b7bd389ee5f3db6fdd197869e8577a0cd
# Parent  6f8d3c18f5e5266c57e1b8b3736224c0146f1726
# EXP-Topic riastradh-pr59411-prgrowingnowaitcleanup
humanize_number(3): New option HN_IEC for IEC prefixes.

PR lib/60635: humanize_number(3): exa/exbi issues

diff -r 6f8d3c18f5e5 -r cc8c7b6b7bd3 lib/libc/gen/humanize_number.3
--- a/lib/libc/gen/humanize_number.3	Sun Aug 23 16:54:15 2026 +0000
+++ b/lib/libc/gen/humanize_number.3	Sun Aug 23 17:26:51 2026 +0000
@@ -61,20 +61,52 @@ would be too long to fit into
 .Fa buffer ,
 then repeatedly divide
 .Fa number
-by 1024 until it will fit.
+by a base, either 1024 (default) or 1000 (decimal, with
+.Dv HN_DIVISOR_1000 ) ,
+until it will fit.
 In this case, prefix
 .Fa suffix
-with the appropriate SI designator.
+with the corresponding scale designator.
+.Pp
+For the default binary base (1024), the prefixes are:
+.Bl -column "Prefix" "IEC" "Name" "Multiplier" -offset indent
+.It Sy "Prefix" Ta Sy "IEC" Ta Sy "Name" Ta Sy "Multiplier"
+.It K	Ki	kibi	1,024
+.It M	Mi	mebi	1,048,576
+.It G	Gi	gibi	1,073,741,824
+.It T	Ti	tebi	1,099,511,627,776
+.It P	Pi	pebi	1,125,899,906,842,624
+.It E	Ei	exbi	1,152,921,504,606,846,976
+.El
 .Pp
-The prefixes are:
-.Bl -column "Prefix" "Description" "Multiplier" -offset indent
-.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier"
-.It k	kilo	1024
-.It M	mega	1048576
-.It G	giga	1073741824
-.It T	tera	1099511627776
-.It P	peta	1125899906842624
-.It E	exa	1152921504606846976
+The nonstandard
+.Dq Tn SI
+or
+.Tn JEDEC Ns No - Ns style
+prefixes
+.Dq K ,
+.Dq M ,
+etc., are chosen by default.
+The
+.Tn IEC
+prefixes
+.Dq Ki ,
+.Dq Mi ,
+etc., are chosen by the
+.Dv HN_IEC
+option.
+.Pp
+For the decimal base (1000, chosen by
+.Dv HN_DIVISOR_1000 ) ,
+the SI prefixes are:
+.Bl -column "Prefix" "Name" "Multiplier" -offset indent
+.It Sy "Prefix" Ta Sy "Name" Ta Sy "Multiplier"
+.It k	kilo	1,000
+.It M	mega	1,000,000
+.It G	giga	1,000,000,000
+.It T	tera	1,000,000,000,000
+.It P	peta	1,000,000,000,000,000
+.It E	exa	1,000,000,000,000,000,000
 .El
 .Pp
 .Fa len
@@ -123,6 +155,17 @@ Divide
 .Fa number
 with 1000 instead of 1024.
 That is, use decimal scaling instead of binary.
+.Pp
+Exclusive with
+.Dv HN_IEC .
+.It Dv HN_IEC
+Use IEC prefixes
+.Dq Ki ,
+.Dq Mi ,
+etc.
+.Pp
+Exclusive with
+.Dv HN_DIVISOR_1000 .
 .El
 .Pp
 To generate the shortest meaningful value,
diff -r 6f8d3c18f5e5 -r cc8c7b6b7bd3 lib/libc/gen/humanize_number.c
--- a/lib/libc/gen/humanize_number.c	Sun Aug 23 16:54:15 2026 +0000
+++ b/lib/libc/gen/humanize_number.c	Sun Aug 23 17:26:51 2026 +0000
@@ -52,9 +52,12 @@ humanize_number(char *buf, size_t len, i
 	int64_t	divisor, max, post = 1;
 	size_t	baselen;
 	int	maxscale;
+	int	prefixbytes = 1;
 
 	_DIAGASSERT(buf != NULL);
 	_DIAGASSERT(scale >= 0);
+	_DIAGASSERT((flags & (HN_DIVISOR_1000|HN_IEC)) !=
+	    (HN_DIVISOR_1000|HN_IEC));
 
 	if (suffix == NULL)
 		suffix = "";
@@ -68,17 +71,31 @@ humanize_number(char *buf, size_t len, i
 			prefixes = "\0\0k\0M\0G\0T\0P\0E";
 	} else {
 		/*
-		 * binary multiplies
-		 * XXX IEC 60027-2 recommends Ki, Mi, Gi...
+		 * binary multiplies with `SI'/JEDEC-style or IEC
+		 * prefixes
 		 */
 		divisor = 1024;
-		if (flags & HN_B)
+		switch (flags & (HN_B|HN_IEC)) {
+		case HN_B:
 			prefixes = "B\0K\0M\0G\0T\0P\0E";
-		else
+			break;
+		case 0:
 			prefixes = "\0\0K\0M\0G\0T\0P\0E";
+			break;
+		case HN_B|HN_IEC:
+			prefixes = "B\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
+			prefixbytes = 2;
+			break;
+		case HN_IEC:
+			prefixes = "\0\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
+			prefixbytes = 2;
+			break;
+		default:
+			__unreachable();
+		}
 	}
 
-#define	SCALE2PREFIX(scale)	(&prefixes[(scale) << 1])
+#define	SCALE2PREFIX(scale)	(&prefixes[(scale) * (prefixbytes + 1)])
 	maxscale = 6;
 
 	if (scale < 0 || (scale > maxscale &&
diff -r 6f8d3c18f5e5 -r cc8c7b6b7bd3 tests/lib/libc/gen/t_humanize_number.c
--- a/tests/lib/libc/gen/t_humanize_number.c	Sun Aug 23 16:54:15 2026 +0000
+++ b/tests/lib/libc/gen/t_humanize_number.c	Sun Aug 23 17:26:51 2026 +0000
@@ -112,6 +112,32 @@ const struct hnopts {
 	  NULL },
 	{ 4, 1024LL*1024*1024*1024*1024*1024, "", HN_AUTOSCALE, HN_B, 3, "1 E",
 	  "PR lib/60635: humanize_number(3): exa/exbi issues" },
+
+	{ 5, 1, "", HN_AUTOSCALE, HN_IEC, 2, "1 ", NULL },
+	{ 5, 1024LL, "", HN_AUTOSCALE, HN_IEC, 4, "1 Ki", NULL },
+	{ 5, 1024LL*1024, "", HN_AUTOSCALE, HN_IEC, 4, "1 Mi", NULL },
+	{ 5, 1024LL*1024*1024, "", HN_AUTOSCALE, HN_IEC, 4, "1 Gi", NULL },
+	{ 5, 1024LL*1024*1024*1024, "", HN_AUTOSCALE, HN_IEC, 4, "1 Ti",
+	  NULL },
+	{ 5, 1024LL*1024*1024*1024*1024, "", HN_AUTOSCALE, HN_IEC, 4, "1 Pi",
+	  NULL },
+	{ 5, 1024LL*1024*1024*1024*1024*1024, "", HN_AUTOSCALE,HN_IEC, 4,
+	  "1 Ei",
+	  "PR lib/60635: humanize_number(3): exa/exbi issues" },
+
+	{ 5, 1, "", HN_AUTOSCALE, HN_IEC|HN_B, 3, "1 B", NULL },
+	{ 5, 1024LL, "", HN_AUTOSCALE, HN_IEC|HN_B, 4, "1 Ki", NULL },
+	{ 5, 1024LL*1024, "", HN_AUTOSCALE, HN_IEC|HN_B, 4, "1 Mi", NULL },
+	{ 5, 1024LL*1024*1024, "", HN_AUTOSCALE, HN_IEC|HN_B, 4, "1 Gi",
+	  NULL },
+	{ 5, 1024LL*1024*1024*1024, "", HN_AUTOSCALE, HN_IEC|HN_B, 4, "1 Ti",
+	  NULL },
+	{ 5, 1024LL*1024*1024*1024*1024, "", HN_AUTOSCALE, HN_IEC|HN_B, 4,
+	  "1 Pi",
+	  NULL },
+	{ 5, 1024LL*1024*1024*1024*1024*1024, "", HN_AUTOSCALE, HN_IEC|HN_B, 4,
+	  "1 Ei",
+	  "PR lib/60635: humanize_number(3): exa/exbi issues" },
 };
 
 struct hnflags {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.