.
[coreutils.git] / lib / human.c
blobddd4b4aef6920855a7881bd70b818f1899f98788
1 /* human.c -- print human readable file size
2 Copyright (C) 1996, 1997 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Originally contributed by lm@sgi.com;
19 --si and large file support added by eggert@twinsun.com. */
21 #include <config.h>
23 #if HAVE_INTTYPES_H
24 # include <inttypes.h>
25 #endif
27 #include <sys/types.h>
28 #include <stdio.h>
30 #if HAVE_LIMITS_H
31 # include <limits.h>
32 #endif
34 #ifndef CHAR_BIT
35 # define CHAR_BIT 8
36 #endif
38 #include "human.h"
40 static const char suffixes[] =
42 0, /* not used */
43 'k', /* kilo */
44 'M', /* Mega */
45 'G', /* Giga */
46 'T', /* Tera */
47 'P', /* Peta */
48 'E', /* Exa */
49 'Z', /* Zetta */
50 'Y' /* Yotta */
53 /* Convert N to a human readable format in BUF.
55 N is expressed in units of FROM_UNITS; use units of TO_UNITS in the
56 output number. FROM_UNITS and TO_UNITS must be positive, and one must
57 be a multiple of the other.
59 If BASE is nonzero, use a format like "127k" if possible,
60 using powers of BASE; otherwise, use ordinary decimal format.
61 Normally BASE is either 1000 or 1024; it must be at least 2.
62 Most people visually process strings of 3-4 digits effectively,
63 but longer strings of digits are more prone to misinterpretation.
64 Hence, converting to an abbreviated form usually improves readability.
65 Use a suffix indicating which power is being used.
66 For example, assuming BASE is 1024, 8500 would be converted to 8.3k,
67 133456345 to 127M, 56990456345 to 53G, and so on. Numbers smaller
68 than BASE aren't modified. */
70 char *
71 human_readable (uintmax_t n, char *buf, int from_units, int to_units, int base)
73 uintmax_t amt;
74 int tenths;
75 int power;
76 char *p;
78 /* 0 means adjusted N == AMT.TENTHS;
79 1 means AMT.TENTHS < adjusted N < AMT.TENTHS + 0.05;
80 2 means adjusted N == AMT.TENTHS + 0.05;
81 3 means AMT.TENTHS + 0.05 < adjusted N < AMT.TENTHS + 0.1. */
82 int rounding;
84 p = buf + LONGEST_HUMAN_READABLE;
85 *p = '\0';
87 #ifdef lint
88 /* Suppress `used before initialized' warning. */
89 power = 0;
90 #endif
92 /* Adjust AMT out of FROM_UNITS units and into TO_UNITS units. */
94 if (to_units <= from_units)
96 int multiplier = from_units / to_units;
97 amt = n * multiplier;
98 tenths = rounding = 0;
100 if (amt / multiplier != n)
102 /* Overflow occurred during multiplication. We should use
103 multiple precision arithmetic here, but we'll be lazy and
104 resort to floating point. This can yield answers that
105 are slightly off. In practice it is quite rare to
106 overflow uintmax_t, so this is good enough for now. */
108 double damt = n * (double) multiplier;
110 if (! base)
111 sprintf (buf, "%.0f", damt);
112 else
114 double e = 1;
115 power = 0;
119 e *= base;
120 power++;
122 while (e * base <= amt && power < sizeof suffixes - 1);
124 damt /= e;
126 sprintf (buf, "%.1f%c", damt, suffixes[power]);
127 if (4 < strlen (buf))
128 sprintf (buf, "%.0f%c", damt, suffixes[power]);
131 return buf;
134 else
136 int divisor = to_units / from_units;
137 int r10 = (n % divisor) * 10;
138 int r2 = (r10 % divisor) * 2;
139 amt = n / divisor;
140 tenths = r10 / divisor;
141 rounding = r2 < divisor ? 0 < r2 : 2 + (divisor < r2);
145 /* Use power of BASE notation if adjusted AMT is large enough. */
147 if (base && base <= amt)
149 power = 0;
153 int r10 = (amt % base) * 10 + tenths;
154 int r2 = (r10 % base) * 2 + (rounding >> 1);
155 amt /= base;
156 tenths = r10 / base;
157 rounding = (r2 < base
158 ? 0 < r2 + rounding
159 : 2 + (base < r2 + rounding));
160 power++;
162 while (base <= amt && power < sizeof suffixes - 1);
164 *--p = suffixes[power];
166 if (amt < 10)
168 tenths += 2 < rounding + (tenths & 1);
170 if (tenths == 10)
172 amt++;
173 tenths = 0;
176 if (amt < 10)
178 *--p = '0' + tenths;
179 *--p = '.';
180 tenths = 0;
185 if (5 < tenths + (2 < rounding + (amt & 1)))
187 amt++;
189 if (amt == base && power < sizeof suffixes - 1)
191 *p = suffixes[power + 1];
192 *--p = '0';
193 *--p = '.';
194 amt = 1;
199 *--p = '0' + (int) (amt % 10);
200 while ((amt /= 10) != 0);
202 return p;