summaryrefslogtreecommitdiff
path: root/lib/human.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2000-06-16 12:51:28 +0000
committerJim Meyering <jim@meyering.net>2000-06-16 12:51:28 +0000
commitff5aea354f38f5abbedd448750c0e9bd5edcdb08 (patch)
tree63a9fd8553d97e36f6daf8c85d2f35d76756d0e9 /lib/human.c
parenta6b94414503f0e6f5c4c408a8de290a300a80107 (diff)
downloadcoreutils-ff5aea354f38f5abbedd448750c0e9bd5edcdb08.tar.xz
(adjust_value): New function.
(human_readable_inexact): Apply rounding style even when printing approximate values.
Diffstat (limited to 'lib/human.c')
-rw-r--r--lib/human.c116
1 files changed, 69 insertions, 47 deletions
diff --git a/lib/human.c b/lib/human.c
index 839ecda86..92b051cae 100644
--- a/lib/human.c
+++ b/lib/human.c
@@ -76,6 +76,23 @@ static const char suffixes[] =
'Y' /* Yotta */
};
+/* If INEXACT_STYLE is not human_round_to_even, and if easily
+ possible, adjust VALUE according to the style. */
+static double
+adjust_value (enum human_inexact_style inexact_style, double value)
+{
+ /* Do not use the floor or ceil functions, as that would mean
+ linking with the standard math library, which is a porting pain.
+ So leave the value alone if it is too large to easily round. */
+ if (inexact_style != human_round_to_even && value < (uintmax_t) -1)
+ {
+ uintmax_t u = value;
+ value = u + (inexact_style == human_ceiling && u != value);
+ }
+
+ return value;
+}
+
/* Like human_readable_inexact, except always round to even. */
char *
human_readable (uintmax_t n, char *buf,
@@ -117,10 +134,6 @@ human_readable_inexact (uintmax_t n, char *buf,
int base;
int to_block_size;
int tenths = 0;
- int multiplier;
- int divisor;
- int r2;
- int r10;
int power;
char *p;
@@ -151,49 +164,58 @@ human_readable_inexact (uintmax_t n, char *buf,
/* Adjust AMT out of FROM_BLOCK_SIZE units and into TO_BLOCK_SIZE units. */
- if (to_block_size <= from_block_size
- ? (from_block_size % to_block_size != 0
- || (multiplier = from_block_size / to_block_size,
- (amt = n * multiplier) / multiplier != n))
- : (from_block_size == 0
- || to_block_size % from_block_size != 0
- || (divisor = to_block_size / from_block_size,
- r10 = (n % divisor) * 10,
- r2 = (r10 % divisor) * 2,
- amt = n / divisor,
- tenths = r10 / divisor,
- rounding = r2 < divisor ? 0 < r2 : 2 + (divisor < r2),
- 0)))
- {
- /* Either the result cannot be computed easily using uintmax_t,
- or from_block_size is zero. Fall back on floating point.
- FIXME: This can yield answers that are slightly off. */
-
- double damt = n * (from_block_size / (double) to_block_size);
-
- if (! base)
- sprintf (buf, "%.0f", damt);
- else
- {
- double e = 1;
- power = 0;
-
- do
- {
- e *= base;
- power++;
- }
- while (e * base <= damt && power < sizeof suffixes - 1);
-
- damt /= e;
-
- sprintf (buf, "%.1f%c", damt, suffixes[power]);
- if (4 < strlen (buf))
- sprintf (buf, "%.0f%c", damt, suffixes[power]);
- }
-
- return buf;
- }
+ {
+ int multiplier;
+ int divisor;
+ int r2;
+ int r10;
+ if (to_block_size <= from_block_size
+ ? (from_block_size % to_block_size != 0
+ || (multiplier = from_block_size / to_block_size,
+ (amt = n * multiplier) / multiplier != n))
+ : (from_block_size == 0
+ || to_block_size % from_block_size != 0
+ || (divisor = to_block_size / from_block_size,
+ r10 = (n % divisor) * 10,
+ r2 = (r10 % divisor) * 2,
+ amt = n / divisor,
+ tenths = r10 / divisor,
+ rounding = r2 < divisor ? 0 < r2 : 2 + (divisor < r2),
+ 0)))
+ {
+ /* Either the result cannot be computed easily using uintmax_t,
+ or from_block_size is zero. Fall back on floating point.
+ FIXME: This can yield answers that are slightly off. */
+
+ double damt = n * (from_block_size / (double) to_block_size);
+
+ if (! base)
+ sprintf (buf, "%.0f", adjust_value (inexact_style, damt));
+ else
+ {
+ double e = 1;
+ power = 0;
+
+ do
+ {
+ e *= base;
+ power++;
+ }
+ while (e * base <= damt && power < sizeof suffixes - 1);
+
+ damt /= e;
+
+ sprintf (buf, "%.1f%c", adjust_value (inexact_style, damt),
+ suffixes[power]);
+ if (4 < strlen (buf))
+ sprintf (buf, "%.0f%c",
+ adjust_value (inexact_style, damt * 10) / 10,
+ suffixes[power]);
+ }
+
+ return buf;
+ }
+ }
/* Use power of BASE notation if adjusted AMT is large enough. */