1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
38 #define _(msgid) gettext (msgid)
40 #include "debug-print.h"
42 /* Public functions. */
44 typedef int numeric_converter (char *, const struct fmt_spec *, double);
45 static numeric_converter convert_F, convert_N, convert_E, convert_F_plus;
46 static numeric_converter convert_Z, convert_IB, convert_P, convert_PIB;
47 static numeric_converter convert_PIBHEX, convert_PK, convert_RB;
48 static numeric_converter convert_RBHEX, convert_CCx, convert_date;
49 static numeric_converter convert_time, convert_WKDAY, convert_MONTH;
51 static numeric_converter try_F, convert_infinite;
53 typedef int string_converter (char *, const struct fmt_spec *, const char *);
54 static string_converter convert_A, convert_AHEX;
56 /* Converts binary value V into printable form in the exactly
57 FP->W character in buffer S according to format specification
58 FP. No null terminator is appended to the buffer. */
60 data_out (char *s, const struct fmt_spec *fp, const union value *v)
62 int cat = formats[fp->type].cat;
65 assert (check_output_specifier (fp, 0));
66 if (!(cat & FCAT_STRING))
68 /* Numeric formatting. */
71 /* Handle SYSMIS turning into blanks. */
72 if ((cat & FCAT_BLANKS_SYSMIS) && number == SYSMIS)
74 memset (s, ' ', fp->w);
75 s[fp->w - fp->d - 1] = '.';
79 /* Handle decimal shift. */
80 if ((cat & FCAT_SHIFT_DECIMAL) && number != SYSMIS && fp->d)
81 number *= pow (10.0, fp->d);
86 ok = convert_F (s, fp, number);
90 ok = convert_N (s, fp, number);
94 ok = convert_E (s, fp, number);
97 case FMT_COMMA: case FMT_DOT: case FMT_DOLLAR: case FMT_PCT:
98 ok = convert_F_plus (s, fp, number);
102 ok = convert_Z (s, fp, number);
114 ok = convert_IB (s, fp, number);
118 ok = convert_P (s, fp, number);
122 ok = convert_PIB (s, fp, number);
126 ok = convert_PIBHEX (s, fp, number);
130 ok = convert_PK (s, fp, number);
134 ok = convert_RB (s, fp, number);
138 ok = convert_RBHEX (s, fp, number);
141 case FMT_CCA: case FMT_CCB: case FMT_CCC: case FMT_CCD: case FMT_CCE:
142 ok = convert_CCx (s, fp, number);
145 case FMT_DATE: case FMT_EDATE: case FMT_SDATE: case FMT_ADATE:
146 case FMT_JDATE: case FMT_QYR: case FMT_MOYR: case FMT_WKYR:
148 ok = convert_date (s, fp, number);
151 case FMT_TIME: case FMT_DTIME:
152 ok = convert_time (s, fp, number);
156 ok = convert_WKDAY (s, fp, number);
160 ok = convert_MONTH (s, fp, number);
170 /* String formatting. */
171 const char *string = v->s;
176 ok = convert_A (s, fp, string);
180 ok = convert_AHEX (s, fp, string);
189 /* Error handling. */
191 strncpy (s, "ERROR", fp->w);
196 /* Converts V into S in F format with width W and D decimal places,
197 then deletes trailing zeros. S is not null-terminated. */
199 num_to_string (double v, char *s, int w, int d)
201 struct fmt_spec f = make_output_format (FMT_F, w, d);
202 convert_F (s, &f, v);
205 /* Main conversion functions. */
207 static void insert_commas (char *dst, const char *src,
208 const struct fmt_spec *fp);
209 static int year4 (int year);
210 static int try_CCx (char *s, const struct fmt_spec *fp, double v);
213 #error Write your own floating-point output routines.
216 /* Converts a number between 0 and 15 inclusive to a `hexit'
218 #define MAKE_HEXIT(X) ("0123456789ABCDEF"[X])
220 /* Table of powers of 10. */
221 static const double power10[] =
224 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, 1e10,
225 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20,
226 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30,
227 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, 1e40,
230 /* Handles F format. */
232 convert_F (char *dst, const struct fmt_spec *fp, double number)
234 if (!try_F (dst, fp, number))
235 convert_E (dst, fp, number);
239 /* Handles N format. */
241 convert_N (char *dst, const struct fmt_spec *fp, double number)
243 double d = floor (number);
245 if (d < 0 || d == SYSMIS)
247 msg (ME, _("The N output format cannot be used to output a "
248 "negative number or the system-missing value."));
252 if (d < power10[fp->w])
255 sprintf (buf, "%0*.0f", fp->w, number);
256 memcpy (dst, buf, fp->w);
259 memset (dst, '*', fp->w);
264 /* Handles E format. Also operates as fallback for some other
267 convert_E (char *dst, const struct fmt_spec *fp, double number)
269 /* Temporary buffer. */
272 /* Ranged number of decimal places. */
275 if (!finite (number))
276 return convert_infinite (dst, fp, number);
278 /* Check that the format is wide enough.
279 Although PSPP generally checks this, convert_E() can be called as
280 a fallback from other formats which do not check. */
283 memset (dst, '*', fp->w);
287 /* Put decimal places in usable range. */
288 d = min (fp->d, fp->w - 6);
293 sprintf (buf, "%*.*E", fp->w, d, number);
295 /* What we do here is force the exponent part to have four
296 characters whenever possible. That is, 1.00E+99 is okay (`E+99')
297 but 1.00E+100 (`E+100') must be coerced to 1.00+100 (`+100'). On
298 the other hand, 1.00E1000 (`E+100') cannot be canonicalized.
299 Note that ANSI C guarantees at least two digits in the
301 if (fabs (number) > 1e99)
303 /* Pointer to the `E' in buf. */
306 cp = strchr (buf, 'E');
309 /* Exponent better not be bigger than an int. */
310 int exp = atoi (cp + 1);
312 if (abs (exp) > 99 && abs (exp) < 1000)
314 /* Shift everything left one place: 1.00e+100 -> 1.00+100. */
320 else if (abs (exp) >= 1000)
321 memset (buf, '*', fp->w);
325 /* The C locale always uses a period `.' as a decimal point.
326 Translate to comma if necessary. */
327 if ((get_decimal() == ',' && fp->type != FMT_DOT)
328 || (get_decimal() == '.' && fp->type == FMT_DOT))
330 char *cp = strchr (buf, '.');
335 memcpy (dst, buf, fp->w);
339 /* Handles COMMA, DOT, DOLLAR, and PCT formats. */
341 convert_F_plus (char *dst, const struct fmt_spec *fp, double number)
345 if (try_F (buf, fp, number))
346 insert_commas (dst, buf, fp);
348 convert_E (dst, fp, number);
354 convert_Z (char *dst, const struct fmt_spec *fp, double number)
356 static int warned = 0;
361 _("Quality of zoned decimal (Z) output format code is "
362 "suspect. Check your results. Report bugs to %s."),
367 if (number == SYSMIS)
369 msg (ME, _("The system-missing value cannot be output as a zoned "
379 d = fabs (floor (number));
380 if (d >= power10[fp->w])
382 msg (ME, _("Number %g too big to fit in field with format Z%d.%d."),
383 number, fp->w, fp->d);
387 sprintf (buf, "%*.0f", fp->w, number);
388 for (i = 0; i < fp->w; i++)
389 dst[i] = (buf[i] - '0') | 0xf0;
391 dst[fp->w - 1] &= 0xdf;
398 convert_A (char *dst, const struct fmt_spec *fp, const char *string)
400 memcpy (dst, string, fp->w);
405 convert_AHEX (char *dst, const struct fmt_spec *fp, const char *string)
409 for (i = 0; i < fp->w / 2; i++)
411 *dst++ = MAKE_HEXIT ((string[i]) >> 4);
412 *dst++ = MAKE_HEXIT ((string[i]) & 0xf);
419 convert_IB (char *dst, const struct fmt_spec *fp, double number)
421 /* Strategy: Basically the same as convert_PIBHEX() but with
422 base 256. Then negate the two's-complement result if number
425 /* Used for constructing the two's-complement result. */
428 /* Fraction (mantissa). */
434 /* Difference between exponent and (-8*fp->w-1). */
440 /* Make the exponent (-8*fp->w-1). */
441 frac = frexp (fabs (number), &exp);
442 diff = exp - (-8 * fp->w - 1);
444 frac *= ldexp (1.0, diff);
446 /* Extract each base-256 digit. */
447 for (i = 0; i < fp->w; i++)
451 temp[i] = floor (frac);
454 /* Perform two's-complement negation if number is negative. */
457 /* Perform NOT operation. */
458 for (i = 0; i < fp->w; i++)
460 /* Add 1 to the whole number. */
461 for (i = fp->w - 1; i >= 0; i--)
468 memcpy (dst, temp, fp->w);
469 #ifndef WORDS_BIGENDIAN
470 buf_reverse (dst, fp->w);
477 convert_P (char *dst, const struct fmt_spec *fp, double number)
479 /* Buffer for fp->w*2-1 characters + a decimal point if library is
480 not quite compliant + a null. */
486 /* Main extraction. */
487 sprintf (buf, "%0*.0f", fp->w * 2 - 1, floor (fabs (number)));
489 for (i = 0; i < fp->w; i++)
490 ((unsigned char *) dst)[i]
491 = ((buf[i * 2] - '0') << 4) + buf[i * 2 + 1] - '0';
494 dst[fp->w - 1] &= 0xf0;
496 dst[fp->w - 1] |= 0xf;
498 dst[fp->w - 1] |= 0xd;
504 convert_PIB (char *dst, const struct fmt_spec *fp, double number)
506 /* Strategy: Basically the same as convert_IB(). */
508 /* Fraction (mantissa). */
514 /* Difference between exponent and (-8*fp->w). */
520 /* Make the exponent (-8*fp->w). */
521 frac = frexp (fabs (number), &exp);
522 diff = exp - (-8 * fp->w);
524 frac *= ldexp (1.0, diff);
526 /* Extract each base-256 digit. */
527 for (i = 0; i < fp->w; i++)
531 ((unsigned char *) dst)[i] = floor (frac);
533 #ifndef WORDS_BIGENDIAN
534 buf_reverse (dst, fp->w);
541 convert_PIBHEX (char *dst, const struct fmt_spec *fp, double number)
543 /* Strategy: Use frexp() to create a normalized result (but mostly
544 to find the base-2 exponent), then change the base-2 exponent to
545 (-4*fp->w) using multiplication and division by powers of two.
546 Extract each hexit by multiplying by 16. */
548 /* Fraction (mantissa). */
554 /* Difference between exponent and (-4*fp->w). */
560 /* Make the exponent (-4*fp->w). */
561 frac = frexp (fabs (number), &exp);
562 diff = exp - (-4 * fp->w);
564 frac *= ldexp (1.0, diff);
566 /* Extract each hexit. */
567 for (i = 0; i < fp->w; i++)
571 *dst++ = MAKE_HEXIT ((int) floor (frac));
578 convert_PK (char *dst, const struct fmt_spec *fp, double number)
580 /* Buffer for fp->w*2 characters + a decimal point if library is not
581 quite compliant + a null. */
587 /* Main extraction. */
588 sprintf (buf, "%0*.0f", fp->w * 2, floor (fabs (number)));
590 for (i = 0; i < fp->w; i++)
591 ((unsigned char *) dst)[i]
592 = ((buf[i * 2] - '0') << 4) + buf[i * 2 + 1] - '0';
598 convert_RB (char *dst, const struct fmt_spec *fp, double number)
608 memcpy (dst, u.c, fp->w);
614 convert_RBHEX (char *dst, const struct fmt_spec *fp, double number)
626 for (i = 0; i < fp->w / 2; i++)
628 *dst++ = MAKE_HEXIT (u.c[i] >> 4);
629 *dst++ = MAKE_HEXIT (u.c[i] & 15);
636 convert_CCx (char *dst, const struct fmt_spec *fp, double number)
638 if (try_CCx (dst, fp, number))
648 return convert_F_plus (dst, &f, number);
653 convert_date (char *dst, const struct fmt_spec *fp, double number)
655 static const char *months[12] =
657 "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
658 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
662 int ofs = number / 86400.;
663 int month, day, year;
668 calendar_offset_to_gregorian (ofs, &year, &month, &day);
673 sprintf (buf, "%02d-%s-%04d", day, months[month - 1], year);
675 sprintf (buf, "%02d-%s-%02d", day, months[month - 1], year % 100);
679 sprintf (buf, "%02d.%02d.%04d", day, month, year);
681 sprintf (buf, "%02d.%02d.%02d", day, month, year % 100);
685 sprintf (buf, "%04d/%02d/%02d", year, month, day);
687 sprintf (buf, "%02d/%02d/%02d", year % 100, month, day);
691 sprintf (buf, "%02d/%02d/%04d", month, day, year);
693 sprintf (buf, "%02d/%02d/%02d", month, day, year % 100);
697 int yday = calendar_offset_to_yday (ofs);
700 sprintf (buf, "%02d%03d", year % 100, yday);
701 else if (year4 (year))
702 sprintf (buf, "%04d%03d", year, yday);
708 sprintf (buf, "%d Q% 04d", (month - 1) / 3 + 1, year);
710 sprintf (buf, "%d Q% 02d", (month - 1) / 3 + 1, year % 100);
714 sprintf (buf, "%s% 04d", months[month - 1], year);
716 sprintf (buf, "%s% 02d", months[month - 1], year % 100);
720 int yday = calendar_offset_to_yday (ofs);
723 sprintf (buf, "%02d WK% 04d", (yday - 1) / 7 + 1, year);
725 sprintf (buf, "%02d WK% 02d", (yday - 1) / 7 + 1, year % 100);
732 cp = spprintf (buf, "%02d-%s-%04d %02d:%02d",
733 day, months[month - 1], year,
734 (int) fmod (floor (number / 60. / 60.), 24.),
735 (int) fmod (floor (number / 60.), 60.));
740 if (fp->w >= 22 && fp->d > 0)
742 d = min (fp->d, fp->w - 21);
751 cp = spprintf (cp, ":%0*.*f", w, d, fmod (number, 60.));
761 buf_copy_str_rpad (dst, fp->w, buf);
766 convert_time (char *dst, const struct fmt_spec *fp, double number)
774 if (fabs (number) > 1e20)
776 msg (ME, _("Time value %g too large in magnitude to convert to "
777 "alphanumeric time."), number);
785 *cp++ = '-', time = -time;
786 if (fp->type == FMT_DTIME)
788 double days = floor (time / 60. / 60. / 24.);
789 cp = spprintf (temp_buf, "%02.0f ", days);
790 time = time - days * 60. * 60. * 24.;
796 cp = spprintf (cp, "%02.0f:%02.0f",
797 fmod (floor (time / 60. / 60.), 24.),
798 fmod (floor (time / 60.), 60.));
804 if (width >= 10 && fp->d >= 0 && fp->d != 0)
805 d = min (fp->d, width - 9), w = 3 + d;
809 cp = spprintf (cp, ":%0*.*f", w, d, fmod (time, 60.));
811 buf_copy_str_rpad (dst, fp->w, temp_buf);
817 convert_WKDAY (char *dst, const struct fmt_spec *fp, double wkday)
819 static const char *weekdays[7] =
821 "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
822 "THURSDAY", "FRIDAY", "SATURDAY",
825 if (wkday < 1 || wkday > 7)
827 msg (ME, _("Weekday index %f does not lie between 1 and 7."),
831 buf_copy_str_rpad (dst, fp->w, weekdays[(int) wkday - 1]);
837 convert_MONTH (char *dst, const struct fmt_spec *fp, double month)
839 static const char *months[12] =
841 "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
842 "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER",
845 if (month < 1 || month > 12)
847 msg (ME, _("Month index %f does not lie between 1 and 12."),
852 buf_copy_str_rpad (dst, fp->w, months[(int) month - 1]);
857 /* Helper functions. */
859 /* Copies SRC to DST, inserting commas and dollar signs as appropriate
860 for format spec *FP. */
862 insert_commas (char *dst, const char *src, const struct fmt_spec *fp)
864 /* Number of leading spaces in the number. This is the amount of
865 room we have for inserting commas and dollar signs. */
868 /* Number of digits before the decimal point. This is used to
869 determine the Number of commas to insert. */
872 /* Number of commas to insert. */
875 /* Number of items ,%$ to insert. */
878 /* Number of n_items items not to use for commas. */
881 /* Digit iterator. */
884 /* Source pointer. */
887 /* Count spaces and digits. */
889 while (sp < src + fp->w && *sp == ' ')
896 while (sp + n_digits < src + fp->w && isdigit ((unsigned char) sp[n_digits]))
898 n_commas = (n_digits - 1) / 3;
899 n_items = n_commas + (fp->type == FMT_DOLLAR || fp->type == FMT_PCT);
901 /* Check whether we have enough space to do insertions. */
902 if (!n_spaces || !n_items)
904 memcpy (dst, src, fp->w);
907 if (n_items > n_spaces)
912 memcpy (dst, src, fp->w);
917 /* Put spaces at the beginning if there's extra room. */
918 if (n_spaces > n_items)
920 memset (dst, ' ', n_spaces - n_items);
921 dst += n_spaces - n_items;
924 /* Insert $ and reserve space for %. */
926 if (fp->type == FMT_DOLLAR)
931 else if (fp->type == FMT_PCT)
934 /* Copy negative sign and digits, inserting commas. */
935 if (sp - src > n_spaces)
937 for (i = n_digits; i; i--)
939 if (i % 3 == 0 && n_digits > i && n_items > n_reserved)
942 *dst++ = fp->type == FMT_COMMA ? get_grouping() : get_decimal();
947 /* Copy decimal places and insert % if necessary. */
948 memcpy (dst, sp, fp->w - (sp - src));
949 if (fp->type == FMT_PCT && n_items > 0)
950 dst[fp->w - (sp - src)] = '%';
953 /* Returns 1 if YEAR (i.e., 1987) can be represented in four digits, 0
958 if (year >= 1 && year <= 9999)
960 msg (ME, _("Year %d cannot be represented in four digits for "
961 "output formatting purposes."), year);
966 try_CCx (char *dst, const struct fmt_spec *fp, double number)
968 const struct custom_currency *cc = get_cc(fp->type - FMT_CCA);
976 /* Determine length available, decimal character for number
978 f.type = cc->decimal == get_decimal () ? FMT_COMMA : FMT_DOT;
979 f.w = fp->w - strlen (cc->prefix) - strlen (cc->suffix);
981 f.w -= strlen (cc->neg_prefix) + strlen (cc->neg_suffix) - 1;
983 /* Convert -0 to +0. */
984 number = fabs (number);
990 /* There's room for all that currency crap. Let's do the F
992 if (!convert_F (buf, &f, number) || *buf == '*')
994 insert_commas (buf2, buf, &f);
996 /* Postprocess back into buf. */
999 cp = stpcpy (cp, cc->neg_prefix);
1000 cp = stpcpy (cp, cc->prefix);
1006 assert ((number >= 0) ^ (*bp == '-'));
1010 memcpy (cp, bp, f.w - (bp - buf2));
1011 cp += f.w - (bp - buf2);
1013 cp = stpcpy (cp, cc->suffix);
1015 cp = stpcpy (cp, cc->neg_suffix);
1017 /* Copy into dst. */
1018 assert (cp - buf <= fp->w);
1019 if (cp - buf < fp->w)
1021 memcpy (&dst[fp->w - (cp - buf)], buf, cp - buf);
1022 memset (dst, ' ', fp->w - (cp - buf));
1025 memcpy (dst, buf, fp->w);
1031 format_and_round (char *dst, double number, const struct fmt_spec *fp,
1034 /* Tries to format NUMBER into DST as the F format specified in
1035 *FP. Return true if successful, false on failure. */
1037 try_F (char *dst, const struct fmt_spec *fp, double number)
1039 assert (fp->w <= 40);
1040 if (finite (number))
1042 if (fabs (number) < power10[fp->w])
1044 /* The value may fit in the field. */
1047 /* There are no decimal places, so there's no way
1048 that the value can be shortened. Either it fits
1051 sprintf (buf, "%*.0f", fp->w, number);
1052 if (strlen (buf) <= fp->w)
1054 buf_copy_str_lpad (dst, fp->w, buf);
1062 /* First try to format it with 2 extra decimal
1063 places. This gives us a good chance of not
1064 needing even more decimal places, but it also
1065 avoids wasting too much time formatting more
1066 decimal places on the first try. */
1067 int result = format_and_round (dst, number, fp, fp->d + 2);
1071 /* 2 extra decimal places weren't enough to
1072 correctly round. Try again with the maximum
1073 number of places. */
1074 return format_and_round (dst, number, fp, LDBL_DIG + 1);
1079 /* The value is too big to fit in the field. */
1084 return convert_infinite (dst, fp, number);
1087 /* Tries to compose NUMBER into DST in format FP by first
1088 formatting it with DECIMALS decimal places, then rounding off
1089 to as many decimal places will fit or the number specified in
1090 FP, whichever is fewer.
1092 Returns 1 if conversion succeeds, 0 if this try at conversion
1093 failed and so will any other tries (because the integer part
1094 of the number is too long), or -1 if this try failed but
1095 another with higher DECIMALS might succeed (because we'd be
1096 able to properly round). */
1098 format_and_round (char *dst, double number, const struct fmt_spec *fp,
1101 /* Number of characters before the decimal point,
1102 which includes digits and possibly a minus sign. */
1105 /* Number of digits in the output fraction,
1106 which may be smaller than fp->d if there's not enough room. */
1107 int fraction_digits;
1109 /* Points to last digit that will remain in the fraction after
1111 char *final_frac_dig;
1118 assert (decimals > fp->d);
1119 if (decimals > LDBL_DIG)
1120 decimals = LDBL_DIG + 1;
1122 sprintf (buf, "%.*f", decimals, number);
1124 /* Omit integer part if it's 0. */
1125 if (!memcmp (buf, "0.", 2))
1126 memmove (buf, buf + 1, strlen (buf));
1127 else if (!memcmp (buf, "-0.", 3))
1128 memmove (buf + 1, buf + 2, strlen (buf + 1));
1130 predot_chars = strcspn (buf, ".");
1131 if (predot_chars > fp->w)
1133 /* Can't possibly fit. */
1136 else if (predot_chars == fp->w)
1138 /* Exact fit for integer part and sign. */
1139 memcpy (dst, buf, fp->w);
1142 else if (predot_chars + 1 == fp->w)
1144 /* There's room for the decimal point, but not for any
1145 digits of the fraction.
1146 Right-justify the integer part and sign. */
1148 memcpy (dst + 1, buf, fp->w);
1152 /* It looks like we have room for at least one digit of the
1153 fraction. Figure out how many. */
1154 fraction_digits = fp->w - predot_chars - 1;
1155 if (fraction_digits > fp->d)
1156 fraction_digits = fp->d;
1157 final_frac_dig = buf + predot_chars + fraction_digits;
1159 /* Decide rounding direction and truncate string. */
1160 if (final_frac_dig[1] == '5'
1161 && strspn (final_frac_dig + 2, "0") == strlen (final_frac_dig + 2))
1164 if (decimals <= LDBL_DIG)
1166 /* Don't have enough fractional digits to know which way to
1167 round. We can format with more decimal places, so go
1173 /* We used up all our fractional digits and still don't
1174 know. Round to even. */
1175 round_up = (final_frac_dig[0] - '0') % 2 != 0;
1179 round_up = final_frac_dig[1] >= '5';
1180 final_frac_dig[1] = '\0';
1185 char *cp = final_frac_dig;
1188 if (*cp >= '0' && *cp <= '8')
1193 else if (*cp == '9')
1196 assert (*cp == '.');
1198 if (cp == buf || *--cp == '-')
1202 /* Tried to go past the leftmost digit. Insert a 1. */
1203 memmove (cp + 1, cp, strlen (cp) + 1);
1206 length = strlen (buf);
1209 /* Inserting the `1' overflowed our space.
1210 Drop a decimal place. */
1211 buf[--length] = '\0';
1213 /* If that was the last decimal place, drop the
1214 decimal point too. */
1215 if (buf[length - 1] == '.')
1216 buf[length - 1] = '\0';
1224 /* Omit `-' if value output is zero. */
1225 if (buf[0] == '-' && buf[strspn (buf, "-.0")] == '\0')
1226 memmove (buf, buf + 1, strlen (buf));
1228 buf_copy_str_lpad (dst, fp->w, buf);
1232 /* Formats non-finite NUMBER into DST according to the width
1235 convert_infinite (char *dst, const struct fmt_spec *fp, double number)
1237 assert (!finite (number));
1245 else if (isinf (number))
1246 s = number > 0 ? "+Infinity" : "-Infinity";
1250 buf_copy_str_lpad (dst, fp->w, s);
1253 memset (dst, '*', fp->w);