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
37 #include "debug-print.h"
39 /* Public functions. */
41 typedef int numeric_converter (char *, const struct fmt_spec *, double);
42 static numeric_converter convert_F, convert_N, convert_E, convert_F_plus;
43 static numeric_converter convert_Z, convert_IB, convert_P, convert_PIB;
44 static numeric_converter convert_PIBHEX, convert_PK, convert_RB;
45 static numeric_converter convert_RBHEX, convert_CCx, convert_date;
46 static numeric_converter convert_time, convert_WKDAY, convert_MONTH;
48 static numeric_converter try_F, convert_infinite;
50 typedef int string_converter (char *, const struct fmt_spec *, const char *);
51 static string_converter convert_A, convert_AHEX;
53 /* Converts binary value V into printable form in the exactly
54 FP->W character in buffer S according to format specification
55 FP. No null terminator is appended to the buffer. */
57 data_out (char *s, const struct fmt_spec *fp, const union value *v)
59 int cat = formats[fp->type].cat;
62 assert (check_output_specifier (fp, 0));
63 if (!(cat & FCAT_STRING))
65 /* Numeric formatting. */
68 /* Handle SYSMIS turning into blanks. */
69 if ((cat & FCAT_BLANKS_SYSMIS) && number == SYSMIS)
71 memset (s, ' ', fp->w);
72 s[fp->w - fp->d - 1] = '.';
76 /* Handle decimal shift. */
77 if ((cat & FCAT_SHIFT_DECIMAL) && number != SYSMIS && fp->d)
78 number *= pow (10.0, fp->d);
83 ok = convert_F (s, fp, number);
87 ok = convert_N (s, fp, number);
91 ok = convert_E (s, fp, number);
94 case FMT_COMMA: case FMT_DOT: case FMT_DOLLAR: case FMT_PCT:
95 ok = convert_F_plus (s, fp, number);
99 ok = convert_Z (s, fp, number);
111 ok = convert_IB (s, fp, number);
115 ok = convert_P (s, fp, number);
119 ok = convert_PIB (s, fp, number);
123 ok = convert_PIBHEX (s, fp, number);
127 ok = convert_PK (s, fp, number);
131 ok = convert_RB (s, fp, number);
135 ok = convert_RBHEX (s, fp, number);
138 case FMT_CCA: case FMT_CCB: case FMT_CCC: case FMT_CCD: case FMT_CCE:
139 ok = convert_CCx (s, fp, number);
142 case FMT_DATE: case FMT_EDATE: case FMT_SDATE: case FMT_ADATE:
143 case FMT_JDATE: case FMT_QYR: case FMT_MOYR: case FMT_WKYR:
145 ok = convert_date (s, fp, number);
148 case FMT_TIME: case FMT_DTIME:
149 ok = convert_time (s, fp, number);
153 ok = convert_WKDAY (s, fp, number);
157 ok = convert_MONTH (s, fp, number);
167 /* String formatting. */
168 const char *string = v->s;
173 ok = convert_A (s, fp, string);
177 ok = convert_AHEX (s, fp, string);
186 /* Error handling. */
188 strncpy (s, "ERROR", fp->w);
191 /* Converts V into S in F format with width W and D decimal places,
192 then deletes trailing zeros. S is not null-terminated. */
194 num_to_string (double v, char *s, int w, int d)
196 struct fmt_spec f = make_output_format (FMT_F, w, d);
197 convert_F (s, &f, v);
200 /* Main conversion functions. */
202 static void insert_commas (char *dst, const char *src,
203 const struct fmt_spec *fp);
204 static int year4 (int year);
205 static int try_CCx (char *s, const struct fmt_spec *fp, double v);
208 #error Write your own floating-point output routines.
211 /* Converts a number between 0 and 15 inclusive to a `hexit'
213 #define MAKE_HEXIT(X) ("0123456789ABCDEF"[X])
215 /* Table of powers of 10. */
216 static const double power10[] =
219 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, 1e10,
220 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20,
221 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30,
222 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, 1e40,
225 /* Handles F format. */
227 convert_F (char *dst, const struct fmt_spec *fp, double number)
229 if (!try_F (dst, fp, number))
230 convert_E (dst, fp, number);
234 /* Handles N format. */
236 convert_N (char *dst, const struct fmt_spec *fp, double number)
238 double d = floor (number);
240 if (d < 0 || d == SYSMIS)
242 msg (ME, _("The N output format cannot be used to output a "
243 "negative number or the system-missing value."));
247 if (d < power10[fp->w])
250 sprintf (buf, "%0*.0f", fp->w, number);
251 memcpy (dst, buf, fp->w);
254 memset (dst, '*', fp->w);
259 /* Handles E format. Also operates as fallback for some other
262 convert_E (char *dst, const struct fmt_spec *fp, double number)
264 /* Temporary buffer. */
267 /* Ranged number of decimal places. */
270 if (!finite (number))
271 return convert_infinite (dst, fp, number);
273 /* Check that the format is wide enough.
274 Although PSPP generally checks this, convert_E() can be called as
275 a fallback from other formats which do not check. */
278 memset (dst, '*', fp->w);
282 /* Put decimal places in usable range. */
283 d = min (fp->d, fp->w - 6);
288 sprintf (buf, "%*.*E", fp->w, d, number);
290 /* What we do here is force the exponent part to have four
291 characters whenever possible. That is, 1.00E+99 is okay (`E+99')
292 but 1.00E+100 (`E+100') must be coerced to 1.00+100 (`+100'). On
293 the other hand, 1.00E1000 (`E+100') cannot be canonicalized.
294 Note that ANSI C guarantees at least two digits in the
296 if (fabs (number) > 1e99)
298 /* Pointer to the `E' in buf. */
301 cp = strchr (buf, 'E');
304 /* Exponent better not be bigger than an int. */
305 int exp = atoi (cp + 1);
307 if (abs (exp) > 99 && abs (exp) < 1000)
309 /* Shift everything left one place: 1.00e+100 -> 1.00+100. */
315 else if (abs (exp) >= 1000)
316 memset (buf, '*', fp->w);
320 /* The C locale always uses a period `.' as a decimal point.
321 Translate to comma if necessary. */
322 if ((get_decimal() == ',' && fp->type != FMT_DOT)
323 || (get_decimal() == '.' && fp->type == FMT_DOT))
325 char *cp = strchr (buf, '.');
330 memcpy (dst, buf, fp->w);
334 /* Handles COMMA, DOT, DOLLAR, and PCT formats. */
336 convert_F_plus (char *dst, const struct fmt_spec *fp, double number)
340 if (try_F (buf, fp, number))
341 insert_commas (dst, buf, fp);
343 convert_E (dst, fp, number);
349 convert_Z (char *dst, const struct fmt_spec *fp, double number)
351 static int warned = 0;
356 _("Quality of zoned decimal (Z) output format code is "
357 "suspect. Check your results. Report bugs to %s."),
362 if (number == SYSMIS)
364 msg (ME, _("The system-missing value cannot be output as a zoned "
374 d = fabs (floor (number));
375 if (d >= power10[fp->w])
377 msg (ME, _("Number %g too big to fit in field with format Z%d.%d."),
378 number, fp->w, fp->d);
382 sprintf (buf, "%*.0f", fp->w, number);
383 for (i = 0; i < fp->w; i++)
384 dst[i] = (buf[i] - '0') | 0xf0;
386 dst[fp->w - 1] &= 0xdf;
393 convert_A (char *dst, const struct fmt_spec *fp, const char *string)
395 memcpy (dst, string, fp->w);
400 convert_AHEX (char *dst, const struct fmt_spec *fp, const char *string)
404 for (i = 0; i < fp->w / 2; i++)
406 *dst++ = MAKE_HEXIT ((string[i]) >> 4);
407 *dst++ = MAKE_HEXIT ((string[i]) & 0xf);
414 convert_IB (char *dst, const struct fmt_spec *fp, double number)
416 /* Strategy: Basically the same as convert_PIBHEX() but with
417 base 256. Then negate the two's-complement result if number
420 /* Used for constructing the two's-complement result. */
423 /* Fraction (mantissa). */
429 /* Difference between exponent and (-8*fp->w-1). */
435 /* Make the exponent (-8*fp->w-1). */
436 frac = frexp (fabs (number), &exp);
437 diff = exp - (-8 * fp->w - 1);
439 frac *= ldexp (1.0, diff);
441 /* Extract each base-256 digit. */
442 for (i = 0; i < fp->w; i++)
446 temp[i] = floor (frac);
449 /* Perform two's-complement negation if number is negative. */
452 /* Perform NOT operation. */
453 for (i = 0; i < fp->w; i++)
455 /* Add 1 to the whole number. */
456 for (i = fp->w - 1; i >= 0; i--)
463 memcpy (dst, temp, fp->w);
464 #ifndef WORDS_BIGENDIAN
465 buf_reverse (dst, fp->w);
472 convert_P (char *dst, const struct fmt_spec *fp, double number)
474 /* Buffer for fp->w*2-1 characters + a decimal point if library is
475 not quite compliant + a null. */
481 /* Main extraction. */
482 sprintf (buf, "%0*.0f", fp->w * 2 - 1, floor (fabs (number)));
484 for (i = 0; i < fp->w; i++)
485 ((unsigned char *) dst)[i]
486 = ((buf[i * 2] - '0') << 4) + buf[i * 2 + 1] - '0';
489 dst[fp->w - 1] &= 0xf0;
491 dst[fp->w - 1] |= 0xf;
493 dst[fp->w - 1] |= 0xd;
499 convert_PIB (char *dst, const struct fmt_spec *fp, double number)
501 /* Strategy: Basically the same as convert_IB(). */
503 /* Fraction (mantissa). */
509 /* Difference between exponent and (-8*fp->w). */
515 /* Make the exponent (-8*fp->w). */
516 frac = frexp (fabs (number), &exp);
517 diff = exp - (-8 * fp->w);
519 frac *= ldexp (1.0, diff);
521 /* Extract each base-256 digit. */
522 for (i = 0; i < fp->w; i++)
526 ((unsigned char *) dst)[i] = floor (frac);
528 #ifndef WORDS_BIGENDIAN
529 buf_reverse (dst, fp->w);
536 convert_PIBHEX (char *dst, const struct fmt_spec *fp, double number)
538 /* Strategy: Use frexp() to create a normalized result (but mostly
539 to find the base-2 exponent), then change the base-2 exponent to
540 (-4*fp->w) using multiplication and division by powers of two.
541 Extract each hexit by multiplying by 16. */
543 /* Fraction (mantissa). */
549 /* Difference between exponent and (-4*fp->w). */
555 /* Make the exponent (-4*fp->w). */
556 frac = frexp (fabs (number), &exp);
557 diff = exp - (-4 * fp->w);
559 frac *= ldexp (1.0, diff);
561 /* Extract each hexit. */
562 for (i = 0; i < fp->w; i++)
566 *dst++ = MAKE_HEXIT ((int) floor (frac));
573 convert_PK (char *dst, const struct fmt_spec *fp, double number)
575 /* Buffer for fp->w*2 characters + a decimal point if library is not
576 quite compliant + a null. */
582 /* Main extraction. */
583 sprintf (buf, "%0*.0f", fp->w * 2, floor (fabs (number)));
585 for (i = 0; i < fp->w; i++)
586 ((unsigned char *) dst)[i]
587 = ((buf[i * 2] - '0') << 4) + buf[i * 2 + 1] - '0';
593 convert_RB (char *dst, const struct fmt_spec *fp, double number)
603 memcpy (dst, u.c, fp->w);
609 convert_RBHEX (char *dst, const struct fmt_spec *fp, double number)
621 for (i = 0; i < fp->w / 2; i++)
623 *dst++ = MAKE_HEXIT (u.c[i] >> 4);
624 *dst++ = MAKE_HEXIT (u.c[i] & 15);
631 convert_CCx (char *dst, const struct fmt_spec *fp, double number)
633 if (try_CCx (dst, fp, number))
643 return convert_F_plus (dst, &f, number);
648 convert_date (char *dst, const struct fmt_spec *fp, double number)
650 static const char *months[12] =
652 "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
653 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
657 int ofs = number / 86400.;
658 int month, day, year;
663 calendar_offset_to_gregorian (ofs, &year, &month, &day);
668 sprintf (buf, "%02d-%s-%04d", day, months[month - 1], year);
670 sprintf (buf, "%02d-%s-%02d", day, months[month - 1], year % 100);
674 sprintf (buf, "%02d.%02d.%04d", day, month, year);
676 sprintf (buf, "%02d.%02d.%02d", day, month, year % 100);
680 sprintf (buf, "%04d/%02d/%02d", year, month, day);
682 sprintf (buf, "%02d/%02d/%02d", year % 100, month, day);
686 sprintf (buf, "%02d/%02d/%04d", month, day, year);
688 sprintf (buf, "%02d/%02d/%02d", month, day, year % 100);
692 int yday = calendar_offset_to_yday (ofs);
695 sprintf (buf, "%02d%03d", year % 100, yday);
696 else if (year4 (year))
697 sprintf (buf, "%04d%03d", year, yday);
703 sprintf (buf, "%d Q% 04d", (month - 1) / 3 + 1, year);
705 sprintf (buf, "%d Q% 02d", (month - 1) / 3 + 1, year % 100);
709 sprintf (buf, "%s% 04d", months[month - 1], year);
711 sprintf (buf, "%s% 02d", months[month - 1], year % 100);
715 int yday = calendar_offset_to_yday (ofs);
718 sprintf (buf, "%02d WK% 04d", (yday - 1) / 7 + 1, year);
720 sprintf (buf, "%02d WK% 02d", (yday - 1) / 7 + 1, year % 100);
727 cp = spprintf (buf, "%02d-%s-%04d %02d:%02d",
728 day, months[month - 1], year,
729 (int) fmod (floor (number / 60. / 60.), 24.),
730 (int) fmod (floor (number / 60.), 60.));
735 if (fp->w >= 22 && fp->d > 0)
737 d = min (fp->d, fp->w - 21);
746 cp = spprintf (cp, ":%0*.*f", w, d, fmod (number, 60.));
756 buf_copy_str_rpad (dst, fp->w, buf);
761 convert_time (char *dst, const struct fmt_spec *fp, double number)
769 if (fabs (number) > 1e20)
771 msg (ME, _("Time value %g too large in magnitude to convert to "
772 "alphanumeric time."), number);
780 *cp++ = '-', time = -time;
781 if (fp->type == FMT_DTIME)
783 double days = floor (time / 60. / 60. / 24.);
784 cp = spprintf (temp_buf, "%02.0f ", days);
785 time = time - days * 60. * 60. * 24.;
791 cp = spprintf (cp, "%02.0f:%02.0f",
792 fmod (floor (time / 60. / 60.), 24.),
793 fmod (floor (time / 60.), 60.));
799 if (width >= 10 && fp->d >= 0 && fp->d != 0)
800 d = min (fp->d, width - 9), w = 3 + d;
804 cp = spprintf (cp, ":%0*.*f", w, d, fmod (time, 60.));
806 buf_copy_str_rpad (dst, fp->w, temp_buf);
812 convert_WKDAY (char *dst, const struct fmt_spec *fp, double wkday)
814 static const char *weekdays[7] =
816 "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
817 "THURSDAY", "FRIDAY", "SATURDAY",
820 if (wkday < 1 || wkday > 7)
822 msg (ME, _("Weekday index %f does not lie between 1 and 7."),
826 buf_copy_str_rpad (dst, fp->w, weekdays[(int) wkday - 1]);
832 convert_MONTH (char *dst, const struct fmt_spec *fp, double month)
834 static const char *months[12] =
836 "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
837 "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER",
840 if (month < 1 || month > 12)
842 msg (ME, _("Month index %f does not lie between 1 and 12."),
847 buf_copy_str_rpad (dst, fp->w, months[(int) month - 1]);
852 /* Helper functions. */
854 /* Copies SRC to DST, inserting commas and dollar signs as appropriate
855 for format spec *FP. */
857 insert_commas (char *dst, const char *src, const struct fmt_spec *fp)
859 /* Number of leading spaces in the number. This is the amount of
860 room we have for inserting commas and dollar signs. */
863 /* Number of digits before the decimal point. This is used to
864 determine the Number of commas to insert. */
867 /* Number of commas to insert. */
870 /* Number of items ,%$ to insert. */
873 /* Number of n_items items not to use for commas. */
876 /* Digit iterator. */
879 /* Source pointer. */
882 /* Count spaces and digits. */
884 while (sp < src + fp->w && *sp == ' ')
891 while (sp + n_digits < src + fp->w && isdigit ((unsigned char) sp[n_digits]))
893 n_commas = (n_digits - 1) / 3;
894 n_items = n_commas + (fp->type == FMT_DOLLAR || fp->type == FMT_PCT);
896 /* Check whether we have enough space to do insertions. */
897 if (!n_spaces || !n_items)
899 memcpy (dst, src, fp->w);
902 if (n_items > n_spaces)
907 memcpy (dst, src, fp->w);
912 /* Put spaces at the beginning if there's extra room. */
913 if (n_spaces > n_items)
915 memset (dst, ' ', n_spaces - n_items);
916 dst += n_spaces - n_items;
919 /* Insert $ and reserve space for %. */
921 if (fp->type == FMT_DOLLAR)
926 else if (fp->type == FMT_PCT)
929 /* Copy negative sign and digits, inserting commas. */
930 if (sp - src > n_spaces)
932 for (i = n_digits; i; i--)
934 if (i % 3 == 0 && n_digits > i && n_items > n_reserved)
937 *dst++ = fp->type == FMT_COMMA ? get_grouping() : get_decimal();
942 /* Copy decimal places and insert % if necessary. */
943 memcpy (dst, sp, fp->w - (sp - src));
944 if (fp->type == FMT_PCT && n_items > 0)
945 dst[fp->w - (sp - src)] = '%';
948 /* Returns 1 if YEAR (i.e., 1987) can be represented in four digits, 0
953 if (year >= 1 && year <= 9999)
955 msg (ME, _("Year %d cannot be represented in four digits for "
956 "output formatting purposes."), year);
961 try_CCx (char *dst, const struct fmt_spec *fp, double number)
963 const struct set_cust_currency *cc = get_cc(fp->type - FMT_CCA);
971 /* Determine length available, decimal character for number
973 f.type = cc->decimal == get_decimal() ? FMT_COMMA : FMT_DOT;
974 f.w = fp->w - strlen (cc->prefix) - strlen (cc->suffix);
976 f.w -= strlen (cc->neg_prefix) + strlen (cc->neg_suffix) - 1;
978 /* Convert -0 to +0. */
979 number = fabs (number);
985 /* There's room for all that currency crap. Let's do the F
987 if (!convert_F (buf, &f, number) || *buf == '*')
989 insert_commas (buf2, buf, &f);
991 /* Postprocess back into buf. */
994 cp = stpcpy (cp, cc->neg_prefix);
995 cp = stpcpy (cp, cc->prefix);
1001 assert ((number >= 0) ^ (*bp == '-'));
1005 memcpy (cp, bp, f.w - (bp - buf2));
1006 cp += f.w - (bp - buf2);
1008 cp = stpcpy (cp, cc->suffix);
1010 cp = stpcpy (cp, cc->neg_suffix);
1012 /* Copy into dst. */
1013 assert (cp - buf <= fp->w);
1014 if (cp - buf < fp->w)
1016 memcpy (&dst[fp->w - (cp - buf)], buf, cp - buf);
1017 memset (dst, ' ', fp->w - (cp - buf));
1020 memcpy (dst, buf, fp->w);
1026 format_and_round (char *dst, double number, const struct fmt_spec *fp,
1029 /* Tries to format NUMBER into DST as the F format specified in
1030 *FP. Return true if successful, false on failure. */
1032 try_F (char *dst, const struct fmt_spec *fp, double number)
1034 assert (fp->w <= 40);
1035 if (finite (number))
1037 if (fabs (number) < power10[fp->w])
1039 /* The value may fit in the field. */
1042 /* There are no decimal places, so there's no way
1043 that the value can be shortened. Either it fits
1046 sprintf (buf, "%*.0f", fp->w, number);
1047 if (strlen (buf) <= fp->w)
1049 buf_copy_str_lpad (dst, fp->w, buf);
1057 /* First try to format it with 2 extra decimal
1058 places. This gives us a good chance of not
1059 needing even more decimal places, but it also
1060 avoids wasting too much time formatting more
1061 decimal places on the first try. */
1062 int result = format_and_round (dst, number, fp, fp->d + 2);
1066 /* 2 extra decimal places weren't enough to
1067 correctly round. Try again with the maximum
1068 number of places. */
1069 return format_and_round (dst, number, fp, LDBL_DIG + 1);
1074 /* The value is too big to fit in the field. */
1079 return convert_infinite (dst, fp, number);
1082 /* Tries to compose NUMBER into DST in format FP by first
1083 formatting it with DECIMALS decimal places, then rounding off
1084 to as many decimal places will fit or the number specified in
1085 FP, whichever is fewer.
1087 Returns 1 if conversion succeeds, 0 if this try at conversion
1088 failed and so will any other tries (because the integer part
1089 of the number is too long), or -1 if this try failed but
1090 another with higher DECIMALS might succeed (because we'd be
1091 able to properly round). */
1093 format_and_round (char *dst, double number, const struct fmt_spec *fp,
1096 /* Number of characters before the decimal point,
1097 which includes digits and possibly a minus sign. */
1100 /* Number of digits in the output fraction,
1101 which may be smaller than fp->d if there's not enough room. */
1102 int fraction_digits;
1104 /* Points to last digit that will remain in the fraction after
1106 char *final_frac_dig;
1113 assert (decimals > fp->d);
1114 if (decimals > LDBL_DIG)
1115 decimals = LDBL_DIG + 1;
1117 sprintf (buf, "%.*f", decimals, number);
1119 /* Omit integer part if it's 0. */
1120 if (!memcmp (buf, "0.", 2))
1121 memmove (buf, buf + 1, strlen (buf));
1122 else if (!memcmp (buf, "-0.", 3))
1123 memmove (buf + 1, buf + 2, strlen (buf + 1));
1125 predot_chars = strcspn (buf, ".");
1126 if (predot_chars > fp->w)
1128 /* Can't possibly fit. */
1131 else if (predot_chars == fp->w)
1133 /* Exact fit for integer part and sign. */
1134 memcpy (dst, buf, fp->w);
1137 else if (predot_chars + 1 == fp->w)
1139 /* There's room for the decimal point, but not for any
1140 digits of the fraction.
1141 Right-justify the integer part and sign. */
1143 memcpy (dst + 1, buf, fp->w);
1147 /* It looks like we have room for at least one digit of the
1148 fraction. Figure out how many. */
1149 fraction_digits = fp->w - predot_chars - 1;
1150 if (fraction_digits > fp->d)
1151 fraction_digits = fp->d;
1152 final_frac_dig = buf + predot_chars + fraction_digits;
1154 /* Decide rounding direction and truncate string. */
1155 if (final_frac_dig[1] == '5'
1156 && strspn (final_frac_dig + 2, "0") == strlen (final_frac_dig + 2))
1159 if (decimals <= LDBL_DIG)
1161 /* Don't have enough fractional digits to know which way to
1162 round. We can format with more decimal places, so go
1168 /* We used up all our fractional digits and still don't
1169 know. Round to even. */
1170 round_up = (final_frac_dig[0] - '0') % 2 != 0;
1174 round_up = final_frac_dig[1] >= '5';
1175 final_frac_dig[1] = '\0';
1180 char *cp = final_frac_dig;
1183 if (*cp >= '0' && *cp <= '8')
1188 else if (*cp == '9')
1191 assert (*cp == '.');
1193 if (cp == buf || *--cp == '-')
1197 /* Tried to go past the leftmost digit. Insert a 1. */
1198 memmove (cp + 1, cp, strlen (cp) + 1);
1201 length = strlen (buf);
1204 /* Inserting the `1' overflowed our space.
1205 Drop a decimal place. */
1206 buf[--length] = '\0';
1208 /* If that was the last decimal place, drop the
1209 decimal point too. */
1210 if (buf[length - 1] == '.')
1211 buf[length - 1] = '\0';
1219 /* Omit `-' if value output is zero. */
1220 if (buf[0] == '-' && buf[strspn (buf, "-.0")] == '\0')
1221 memmove (buf, buf + 1, strlen (buf));
1223 buf_copy_str_lpad (dst, fp->w, buf);
1227 /* Formats non-finite NUMBER into DST according to the width
1230 convert_infinite (char *dst, const struct fmt_spec *fp, double number)
1232 assert (!finite (number));
1240 else if (isinf (number))
1241 s = number > 0 ? "+Infinity" : "-Infinity";
1245 buf_copy_str_lpad (dst, fp->w, s);
1248 memset (dst, '*', fp->w);