[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] numfmt: support new ronna, quetta SI prefixes
From: |
Pádraig Brady |
Subject: |
[PATCH] numfmt: support new ronna, quetta SI prefixes |
Date: |
Tue, 29 Nov 2022 18:25:45 +0000 |
Add support for larger quantities,
as voted for in Nov 2022 by the BIPM:
https://www.bipm.org/en/cgpm-2022/resolution-3
This now allows:
$ numfmt --from=si --to=iec 2000R
1.6Q
* src/numfmt.c: Increase limits from 999Y to 999Q.
* tests/misc/numfmt.pl: Adjust accordingly.
* doc/coreutils.texi (numfmt invocation): Describe the
new Ronna, Robi, Quetta, Quebi prefixes.
* NEWS: Mention the improvement.
---
NEWS | 3 ++
doc/coreutils.texi | 6 ++++
src/numfmt.c | 32 ++++++++++++++------
tests/misc/numfmt.pl | 72 ++++++++++++++++++++++----------------------
4 files changed, 67 insertions(+), 46 deletions(-)
diff --git a/NEWS b/NEWS
index b6b5201e7..4e98e5a2d 100644
--- a/NEWS
+++ b/NEWS
@@ -67,6 +67,9 @@ GNU coreutils NEWS -*-
outline -*-
date --debug now diagnoses if multiple --date or --set options are
specified, as only the last specified is significant in that case.
+ numfmt now supports the new Ronna, and Quetta SI prefixes,
+ corresponding to 10^27 and 10^30 respectively.
+
rm outputs more accurate diagnostics in the presence of errors
when removing directories. For example EIO will be faithfully
diagnosed, rather than being conflated with ENOTEMPTY.
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index c801097ee..3040462d4 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -18933,6 +18933,8 @@ one of the following suffixes:
@samp{E} => @math{1000^6 = 10^{18}} (Exa)
@samp{Z} => @math{1000^7 = 10^{21}} (Zetta)
@samp{Y} => @math{1000^8 = 10^{24}} (Yotta)
+@samp{R} => @math{1000^9 = 10^{27}} (Ronna)
+@samp{Q} => @math{1000^{10} = 10^{30}} (Quetta)
@end example
@item iec
@@ -18951,6 +18953,8 @@ one of the following suffixes:
@samp{E} => @math{1024^6 = 2^{60}} (Exbi)
@samp{Z} => @math{1024^7 = 2^{70}} (Zebi)
@samp{Y} => @math{1024^8 = 2^{80}} (Yobi)
+@samp{R} => @math{1024^9 = 2^{90}} (Robi)
+@samp{Q} => @math{1024^{10} = 2^{100}} (Quebi)
@end example
The @option{iec} option uses a single letter suffix (e.g. @samp{G}), which is
@@ -18974,6 +18978,8 @@ one of the following suffixes:
@samp{Ei} => @math{1024^6 = 2^{60}} (Exbi)
@samp{Zi} => @math{1024^7 = 2^{70}} (Zebi)
@samp{Yi} => @math{1024^8 = 2^{80}} (Yobi)
+@samp{Ri} => @math{1024^9 = 2^{90}} (Robi)
+@samp{Qi} => @math{1024^{10} = 2^{100}} (Quebi)
@end example
The @option{iec-i} option uses a two-letter suffix symbol (e.g. @samp{Gi}),
diff --git a/src/numfmt.c b/src/numfmt.c
index b1067d227..de34177f6 100644
--- a/src/numfmt.c
+++ b/src/numfmt.c
@@ -161,10 +161,10 @@ enum { DELIMITER_DEFAULT = CHAR_MAX + 1 };
enum { MAX_UNSCALED_DIGITS = LDBL_DIG };
/* Maximum number of digits we can work with.
- This is equivalent to 999Y.
+ This is equivalent to 999Q.
NOTE: 'long double' can handle more than that, but there's
- no official suffix assigned beyond Yotta (1000^8). */
-enum { MAX_ACCEPTABLE_DIGITS = 27 };
+ no official suffix assigned beyond Quetta (10^30). */
+enum { MAX_ACCEPTABLE_DIGITS = 33 };
static enum scale_type scale_from = scale_none;
static enum scale_type scale_to = scale_none;
@@ -232,7 +232,7 @@ default_scale_base (enum scale_type scale)
static inline int
valid_suffix (const char suf)
{
- static char const *valid_suffixes = "KMGTPEZY";
+ static char const *valid_suffixes = "KMGTPEZYRQ";
return (strchr (valid_suffixes, suf) != NULL);
}
@@ -265,6 +265,12 @@ suffix_power (const char suf)
case 'Y': /* yotta or 2**80. */
return 8;
+ case 'R': /* ronna or 2**90. */
+ return 9;
+
+ case 'Q': /* quetta or 2**100. */
+ return 10;
+
default: /* should never happen. assert? */
return 0;
}
@@ -302,6 +308,12 @@ suffix_power_char (unsigned int power)
case 8:
return "Y";
+ case 9:
+ return "R";
+
+ case 10:
+ return "Q";
+
default:
return "(error)";
}
@@ -460,7 +472,7 @@ enum simple_strtod_error
Returns:
SSE_OK - valid number.
SSE_OK_PRECISION_LOSS - if more than 18 digits were used.
- SSE_OVERFLOW - if more than 27 digits (999Y) were used.
+ SSE_OVERFLOW - if more than 33 digits (999Q) were used.
SSE_INVALID_NUMBER - if no digits were found. */
static enum simple_strtod_error
simple_strtod_int (char const *input_str,
@@ -525,7 +537,7 @@ simple_strtod_int (char const *input_str,
Returns:
SSE_OK - valid number.
SSE_OK_PRECISION_LOSS - if more than 18 digits were used.
- SSE_OVERFLOW - if more than 27 digits (999Y) were used.
+ SSE_OVERFLOW - if more than 33 digits (999Q) were used.
SSE_INVALID_NUMBER - if no digits were found. */
static enum simple_strtod_error
simple_strtod_float (char const *input_str,
@@ -598,7 +610,7 @@ simple_strtod_float (char const *input_str,
Returns:
SSE_OK - valid number.
SSE_OK_PRECISION_LOSS - if more than LDBL_DIG digits were used.
- SSE_OVERFLOW - if more than 27 digits (999Y) were used.
+ SSE_OVERFLOW - if more than 33 digits (999Q) were used.
SSE_INVALID_NUMBER - if no digits were found.
SSE_VALID_BUT_FORBIDDEN_SUFFIX
SSE_INVALID_SUFFIX
@@ -830,7 +842,7 @@ unit_to_umax (char const *n_string)
size_t n_len = strlen (n_string);
char *end = NULL;
uintmax_t n;
- char const *suffixes = "KMGTPEZY";
+ char const *suffixes = "KMGTPEZYRQ";
/* Adjust suffixes so K=1000, Ki=1024, KiB=invalid. */
if (n_len && ! c_isdigit (n_string[n_len - 1]))
@@ -845,7 +857,7 @@ unit_to_umax (char const *n_string)
{
*++end = 'B';
*++end = '\0';
- suffixes = "KMGTPEZY0";
+ suffixes = "KMGTPEZYRQ0";
}
c_string = t_string;
@@ -1224,7 +1236,7 @@ prepare_padded_number (const long double val, size_t
precision)
{
if (inval_style != inval_ignore)
error (conv_exit_code, 0, _("value too large to be printed: '%Lg'"
- " (cannot handle values > 999Y)"), val);
+ " (cannot handle values > 999Q)"), val);
return 0;
}
diff --git a/tests/misc/numfmt.pl b/tests/misc/numfmt.pl
index 7ec04b1ef..87c27b3e4 100755
--- a/tests/misc/numfmt.pl
+++ b/tests/misc/numfmt.pl
@@ -116,29 +116,29 @@ my @Tests =
# Test Suffix logic
['suf-1', '4000', {OUT=>'4000'}],
- ['suf-2', '4Q',
- {ERR => "$prog: invalid suffix in input: '4Q'\n"},
+ ['suf-2', '4S',
+ {ERR => "$prog: invalid suffix in input: '4S'\n"},
{EXIT => '2'}],
['suf-2.1', '4M',
{ERR => "$prog: rejecting suffix " .
"in input: '4M' (consider using --from)\n"},
{EXIT => '2'}],
['suf-3', '--from=si 4M', {OUT=>'4000000'}],
- ['suf-4', '--from=si 4Q',
- {ERR => "$prog: invalid suffix in input: '4Q'\n"},
+ ['suf-4', '--from=si 4S',
+ {ERR => "$prog: invalid suffix in input: '4S'\n"},
{EXIT => '2'}],
- ['suf-5', '--from=si 4MQ',
- {ERR => "$prog: invalid suffix in input '4MQ': 'Q'\n"},
+ ['suf-5', '--from=si 4MS',
+ {ERR => "$prog: invalid suffix in input '4MS': 'S'\n"},
{EXIT => '2'}],
['suf-6', '--from=iec 4M', {OUT=>'4194304'}],
['suf-7', '--from=auto 4M', {OUT=>'4000000'}],
['suf-8', '--from=auto 4Mi', {OUT=>'4194304'}],
- ['suf-9', '--from=auto 4MiQ',
- {ERR => "$prog: invalid suffix in input '4MiQ': 'Q'\n"},
+ ['suf-9', '--from=auto 4MiS',
+ {ERR => "$prog: invalid suffix in input '4MiS': 'S'\n"},
{EXIT => '2'}],
- ['suf-10', '--from=auto 4QiQ',
- {ERR => "$prog: invalid suffix in input: '4QiQ'\n"},
+ ['suf-10', '--from=auto 4SiS',
+ {ERR => "$prog: invalid suffix in input: '4SiS'\n"},
{EXIT => '2'}],
# characters after a white space are OK - printed as-is
@@ -443,8 +443,8 @@ my @Tests =
{EXIT=>2}],
# INVALID_SUFFIX
- ['strtod-9', '--from=si 12.2Q',
- {ERR=>"$prog: invalid suffix in input: '12.2Q'\n"},
+ ['strtod-9', '--from=si 12.2S',
+ {ERR=>"$prog: invalid suffix in input: '12.2S'\n"},
{EXIT=>2}],
# VALID_BUT_FORBIDDEN_SUFFIX
@@ -731,18 +731,18 @@ my @Tests =
## Check all errors again, this time with --invalid=fail
## Input will be printed without conversion,
## and exit code will be 2
- ['ign-err-1', '--invalid=fail 4Q',
- {ERR => "$prog: invalid suffix in input: '4Q'\n"},
- {OUT => "4Q\n"},
+ ['ign-err-1', '--invalid=fail 4S',
+ {ERR => "$prog: invalid suffix in input: '4S'\n"},
+ {OUT => "4S\n"},
{EXIT => 2}],
['ign-err-2', '--invalid=fail 4M',
{ERR => "$prog: rejecting suffix " .
"in input: '4M' (consider using --from)\n"},
{OUT => "4M\n"},
{EXIT => 2}],
- ['ign-err-3', '--invalid=fail --from=si 4MQ',
- {ERR => "$prog: invalid suffix in input '4MQ': 'Q'\n"},
- {OUT => "4MQ\n"},
+ ['ign-err-3', '--invalid=fail --from=si 4MS',
+ {ERR => "$prog: invalid suffix in input '4MS': 'S'\n"},
+ {OUT => "4MS\n"},
{EXIT => 2}],
['ign-err-4', '--invalid=fail --suffix=Foo --to=si 7000FooF',
{ERR => "$prog: invalid suffix in input: '7000FooF'\n"},
@@ -880,10 +880,10 @@ my @Limit_Tests =
['large-3.26','--to=si 76543210000000000000000000', {OUT=> "77Y"}],
['large-3.27','--to=si 876543210000000000000000000', {OUT=>"877Y"}],
- # More than 27 digits is not OK
- ['large-3.28','--to=si 9876543210000000000000000000',
+ # More than 33 digits is not OK
+ ['large-3.28','--to=si 9876543210000000000000000000000000',
{ERR => "$prog: value too large to be converted: " .
- "'9876543210000000000000000000'\n"},
+ "'9876543210000000000000000000000000'\n"},
{EXIT => 2}],
# Test Output
@@ -941,9 +941,9 @@ my @Limit_Tests =
['large-7','--from=si --to=si 80Y', {OUT=>"80Y"}],
['large-8','--from=si --to=si 9000Z', {OUT=>"9.0Y"}],
- ['large-10','--from=si --to=si 999Y', {OUT=>"999Y"}],
- ['large-11','--from=si --to=iec 999Y', {OUT=>"827Y"}],
- ['large-12','--from=si --round=down --to=iec 999Y', {OUT=>"826Y"}],
+ ['large-10','--from=si --to=si 999Q', {OUT=>"999Q"}],
+ ['large-11','--from=si --to=iec 999Q', {OUT=>"789Q"}],
+ ['large-12','--from=si --round=down --to=iec 999Q', {OUT=>"788Q"}],
# units can also affect the output
['large-13','--from=si --from-unit=1000000 9P',
@@ -952,15 +952,15 @@ my @Limit_Tests =
{EXIT => 2}],
['large-13.1','--from=si --from-unit=1000000 --to=si 9P', {OUT=>"9.0Z"}],
- # Numbers>999Y are never acceptable, regardless of scaling
- ['large-14','--from=si --to=si 999Y', {OUT=>"999Y"}],
- ['large-14.1','--from=si --to=si 1000Y',
- {ERR => "$prog: value too large to be printed: '1e+27' " .
- "(cannot handle values > 999Y)\n"},
+ # Numbers>999Q are never acceptable, regardless of scaling
+ ['large-14','--from=si --to=si 999Q', {OUT=>"999Q"}],
+ ['large-14.1','--from=si --to=si 1000Q',
+ {ERR => "$prog: value too large to be printed: '1e+33' " .
+ "(cannot handle values > 999Q)\n"},
{EXIT => 2}],
- ['large-14.2','--from=si --to=si --from-unit=10000 1Y',
- {ERR => "$prog: value too large to be printed: '1e+28' " .
- "(cannot handle values > 999Y)\n"},
+ ['large-14.2','--from=si --to=si --from-unit=10000 1Q',
+ {ERR => "$prog: value too large to be printed: '1e+34' " .
+ "(cannot handle values > 999Q)\n"},
{EXIT => 2}],
# intmax_t overflow when rounding caused this to fail before 8.24
@@ -999,10 +999,10 @@ my @Limit_Tests =
"(consider using --to)\n"},
{OUT => "10000000000000000000\n"},
{EXIT=>2}],
- ['ign-err-11','--invalid=fail --to=si 9876543210000000000000000000',
+ ['ign-err-11','--invalid=fail --to=si 9876543210000000000000000000000000',
{ERR => "$prog: value too large to be converted: " .
- "'9876543210000000000000000000'\n"},
- {OUT => "9876543210000000000000000000\n"},
+ "'9876543210000000000000000000000000'\n"},
+ {OUT => "9876543210000000000000000000000000\n"},
{EXIT => 2}],
);
# Restrict these tests to systems with LDBL_DIG == 18
@@ -1067,7 +1067,7 @@ push @Tests, @Locale_Tests if $locale ne 'C';
## Check all valid/invalid suffixes
foreach my $suf ( 'A' .. 'Z', 'a' .. 'z' ) {
- if ( $suf =~ /^[KMGTPEZY]$/ )
+ if ( $suf =~ /^[KMGTPEZYRQ]$/ )
{
push @Tests, ["auto-suf-si-$suf","--from=si --to=si 1$suf",
{OUT=>"1.0$suf"}];
--
2.26.2
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH] numfmt: support new ronna, quetta SI prefixes,
Pádraig Brady <=