1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2009 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 3 of the License, or
7 (at your option) 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, see <http://www.gnu.org/licenses/>. */
28 #include <data/calendar.h>
29 #include <data/format.h>
30 #include <data/settings.h>
31 #include <data/value.h>
33 #include <libpspp/assertion.h>
34 #include <libpspp/float-format.h>
35 #include <libpspp/integer-format.h>
36 #include <libpspp/message.h>
37 #include <libpspp/misc.h>
38 #include <libpspp/str.h>
39 #include <libpspp/pool.h>
44 #define _(msgid) gettext (msgid)
46 /* A representation of a number that can be quickly rounded to
47 any desired number of decimal places (up to a specified
51 char string[64]; /* Magnitude of number with excess precision. */
52 int integer_digits; /* Number of digits before decimal point. */
53 int leading_nines; /* Number of `9's or `.'s at start of string. */
54 int leading_zeros; /* Number of `0's or `.'s at start of string. */
55 bool negative; /* Is the number negative? */
58 static void rounder_init (struct rounder *, double number, int max_decimals);
59 static int rounder_width (const struct rounder *, int decimals,
60 int *integer_digits, bool *negative);
61 static void rounder_format (const struct rounder *, int decimals,
64 typedef void data_out_converter_func (const union value *,
65 const struct fmt_spec *,
67 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) \
68 static data_out_converter_func output_##METHOD;
71 static bool output_decimal (const struct rounder *, const struct fmt_spec *,
72 bool require_affixes, char *);
73 static bool output_scientific (double, const struct fmt_spec *,
74 bool require_affixes, char *);
76 static double power10 (int) PURE_FUNCTION;
77 static double power256 (int) PURE_FUNCTION;
79 static void output_infinite (double, const struct fmt_spec *, char *);
80 static void output_missing (const struct fmt_spec *, char *);
81 static void output_overflow (const struct fmt_spec *, char *);
82 static bool output_bcd_integer (double, int digits, char *);
83 static void output_binary_integer (uint64_t, int bytes, enum integer_format,
85 static void output_hex (const void *, size_t bytes, char *);
88 static data_out_converter_func *const converters[FMT_NUMBER_OF_FORMATS] =
90 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) output_##METHOD,
94 /* Similar to data_out. Additionally recodes the output from
95 native form into the given legacy character ENCODING.
96 OUTPUT must be provided by the caller and must be at least
97 FORMAT->w long. No null terminator is appended to OUTPUT.
100 data_out_legacy (const union value *input, const char *encoding,
101 const struct fmt_spec *format, char *output)
103 assert (fmt_check_output (format));
105 converters[format->type] (input, format, output);
106 if (0 != strcmp (encoding, LEGACY_NATIVE)
107 && fmt_get_category (format->type) != FMT_CAT_BINARY)
108 legacy_recode (LEGACY_NATIVE, output, encoding, output, format->w);
111 /* Converts the INPUT value into printable form, according to format
112 specification FORMAT.
114 VALUE must be the correct width for FORMAT, that is, its
115 width must be fmt_var_width(FORMAT).
117 The return value is dynamically allocated, and must be freed
118 by the caller. If POOL is non-null, then the return value is
119 allocated on that pool.
122 data_out_pool (const union value *input, const struct fmt_spec *format,
125 char *output = pool_malloc (pool, format->w + 1);
126 assert (fmt_check_output (format));
128 converters[format->type] (input, format, output);
129 output[format->w] = '\0';
134 data_out (const union value *input, const struct fmt_spec *format)
136 return data_out_pool (input, format, NULL);
140 /* Main conversion functions. */
142 /* Outputs F, COMMA, DOT, DOLLAR, PCT, E, CCA, CCB, CCC, CCD, and
145 output_number (const union value *input, const struct fmt_spec *format,
148 double number = input->f;
150 if (number == SYSMIS)
151 output_missing (format, output);
152 else if (!isfinite (number))
153 output_infinite (number, format, output);
156 if (format->type != FMT_E && fabs (number) < 1.5 * power10 (format->w))
159 rounder_init (&r, number, format->d);
161 if (output_decimal (&r, format, true, output)
162 || output_scientific (number, format, true, output)
163 || output_decimal (&r, format, false, output))
167 if (!output_scientific (number, format, false, output))
168 output_overflow (format, output);
172 /* Outputs N format. */
174 output_N (const union value *input, const struct fmt_spec *format,
177 double number = input->f * power10 (format->d);
178 if (input->f == SYSMIS || number < 0)
179 output_missing (format, output);
183 number = fabs (round (number));
184 if (number < power10 (format->w)
185 && sprintf (buf, "%0*.0f", format->w, number) == format->w)
186 memcpy (output, buf, format->w);
188 output_overflow (format, output);
192 /* Outputs Z format. */
194 output_Z (const union value *input, const struct fmt_spec *format,
197 double number = input->f * power10 (format->d);
199 if (input->f == SYSMIS)
200 output_missing (format, output);
201 else if (fabs (number) >= power10 (format->w)
202 || sprintf (buf, "%0*.0f", format->w,
203 fabs (round (number))) != format->w)
204 output_overflow (format, output);
207 if (number < 0 && strspn (buf, "0") < format->w)
209 char *p = &buf[format->w - 1];
210 *p = "}JKLMNOPQR"[*p - '0'];
212 memcpy (output, buf, format->w);
216 /* Outputs P format. */
218 output_P (const union value *input, const struct fmt_spec *format,
221 if (output_bcd_integer (fabs (input->f * power10 (format->d)),
222 format->w * 2 - 1, output)
224 output[format->w - 1] |= 0xd;
226 output[format->w - 1] |= 0xf;
229 /* Outputs PK format. */
231 output_PK (const union value *input, const struct fmt_spec *format,
234 output_bcd_integer (input->f * power10 (format->d), format->w * 2, output);
237 /* Outputs IB format. */
239 output_IB (const union value *input, const struct fmt_spec *format,
242 double number = round (input->f * power10 (format->d));
243 if (input->f == SYSMIS
244 || number >= power256 (format->w) / 2 - 1
245 || number < -power256 (format->w) / 2)
246 memset (output, 0, format->w);
249 uint64_t integer = fabs (number);
252 output_binary_integer (integer, format->w,
253 settings_get_output_integer_format (),
258 /* Outputs PIB format. */
260 output_PIB (const union value *input, const struct fmt_spec *format,
263 double number = round (input->f * power10 (format->d));
264 if (input->f == SYSMIS
265 || number < 0 || number >= power256 (format->w))
266 memset (output, 0, format->w);
268 output_binary_integer (number, format->w,
269 settings_get_output_integer_format (), output);
272 /* Outputs PIBHEX format. */
274 output_PIBHEX (const union value *input, const struct fmt_spec *format,
277 double number = round (input->f);
278 if (input->f == SYSMIS)
279 output_missing (format, output);
280 else if (input->f < 0 || number >= power256 (format->w / 2))
281 output_overflow (format, output);
285 output_binary_integer (number, format->w / 2, INTEGER_MSB_FIRST, tmp);
286 output_hex (tmp, format->w / 2, output);
290 /* Outputs RB format. */
292 output_RB (const union value *input, const struct fmt_spec *format,
296 memcpy (output, &d, format->w);
299 /* Outputs RBHEX format. */
301 output_RBHEX (const union value *input, const struct fmt_spec *format,
305 output_hex (&d, format->w / 2, output);
308 /* Outputs DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, WKYR,
309 DATETIME, TIME, and DTIME formats. */
311 output_date (const union value *input, const struct fmt_spec *format,
314 double number = input->f;
315 int year, month, day, yday;
317 const char *template = fmt_date_template (format->type);
318 size_t template_width = strlen (template);
319 int excess_width = format->w - template_width;
324 assert (format->w >= template_width);
325 if (number == SYSMIS)
328 if (fmt_get_category (format->type) == FMT_CAT_DATE)
332 calendar_offset_to_gregorian (number / 60. / 60. / 24.,
333 &year, &month, &day, &yday);
334 number = fmod (number, 60. * 60. * 24.);
337 year = month = day = yday = 0;
339 while (*template != '\0')
343 while (template[count] == ch)
351 p += sprintf (p, "%02d", day);
353 p += sprintf (p, "%03d", yday);
357 p += sprintf (p, "%02d", month);
360 static const char *const months[12] =
362 "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
363 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
365 p = stpcpy (p, months[month - 1]);
369 if (count >= 4 || excess_width >= 2)
372 p += sprintf (p, "%04d", year);
373 else if (format->type == FMT_DATETIME)
374 p = stpcpy (p, "****");
380 int epoch = settings_get_epoch ();
381 int offset = year - epoch;
382 if (offset < 0 || offset > 99)
384 p += sprintf (p, "%02d", abs (year) % 100);
388 p += sprintf (p, "%d", (month - 1) / 3 + 1);
391 p += sprintf (p, "%2d", (yday - 1) / 7 + 1);
396 number = fabs (number);
397 p += sprintf (p, "%*.0f", count, floor (number / 60. / 60. / 24.));
398 number = fmod (number, 60. * 60. * 24.);
403 number = fabs (number);
404 p += sprintf (p, "%0*.0f", count, floor (number / 60. / 60.));
405 number = fmod (number, 60. * 60.);
408 p += sprintf (p, "%02d", (int) floor (number / 60.));
409 number = fmod (number, 60.);
410 excess_width = format->w - (p - tmp);
411 if (excess_width < 0)
413 if (excess_width == 3 || excess_width == 4
414 || (excess_width >= 5 && format->d == 0))
415 p += sprintf (p, ":%02d", (int) number);
416 else if (excess_width >= 5)
418 int d = MIN (format->d, excess_width - 4);
420 sprintf (p, ":%0*.*f", w, d, number);
421 if (settings_get_decimal_char (FMT_F) != '.')
423 char *cp = strchr (p, '.');
425 *cp = settings_get_decimal_char (FMT_F);
440 buf_copy_lpad (output, format->w, tmp, p - tmp, ' ');
444 output_overflow (format, output);
448 output_missing (format, output);
452 /* Outputs WKDAY format. */
454 output_WKDAY (const union value *input, const struct fmt_spec *format,
457 static const char *const weekdays[7] =
459 "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
460 "THURSDAY", "FRIDAY", "SATURDAY",
463 if (input->f >= 1 && input->f < 8)
464 buf_copy_str_rpad (output, format->w, weekdays[(int) input->f - 1], ' ');
467 if (input->f != SYSMIS)
468 msg (ME, _("Weekday number %f is not between 1 and 7."), input->f);
469 output_missing (format, output);
473 /* Outputs MONTH format. */
475 output_MONTH (const union value *input, const struct fmt_spec *format,
478 static const char *const months[12] =
480 "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
481 "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER",
484 if (input->f >= 1 && input->f < 13)
485 buf_copy_str_rpad (output, format->w, months[(int) input->f - 1], ' ');
488 if (input->f != SYSMIS)
489 msg (ME, _("Month number %f is not between 1 and 12."), input->f);
490 output_missing (format, output);
494 /* Outputs A format. */
496 output_A (const union value *input, const struct fmt_spec *format,
499 memcpy (output, value_str (input, format->w), format->w);
502 /* Outputs AHEX format. */
504 output_AHEX (const union value *input, const struct fmt_spec *format,
507 output_hex (value_str (input, format->w), format->w / 2, output);
510 /* Decimal and scientific formatting. */
512 /* If REQUEST plus the current *WIDTH fits within MAX_WIDTH,
513 increments *WIDTH by REQUEST and return true.
514 Otherwise returns false without changing *WIDTH. */
516 allocate_space (int request, int max_width, int *width)
518 assert (*width <= max_width);
519 if (request + *width <= max_width)
528 /* Tries to compose the number represented by R, in the style of
529 FORMAT, into OUTPUT. Returns true if successful, false on
530 failure, which occurs if FORMAT's width is too narrow. If
531 REQUIRE_AFFIXES is true, then the prefix and suffix specified
532 by FORMAT's style must be included; otherwise, they may be
533 omitted to make the number fit. */
535 output_decimal (const struct rounder *r, const struct fmt_spec *format,
536 bool require_affixes, char *output)
538 const struct fmt_number_style *style =
539 settings_get_style (format->type);
543 for (decimals = format->d; decimals >= 0; decimals--)
545 /* Formatted version of magnitude of NUMBER. */
548 /* Number of digits in MAGNITUDE's integer and fractional parts. */
551 /* Amount of space within the field width already claimed.
552 Initially this is the width of MAGNITUDE, then it is reduced
553 in stages as space is allocated to prefixes and suffixes and
554 grouping characters. */
557 /* Include various decorations? */
562 /* Position in output. */
565 /* Make sure there's room for the number's magnitude, plus
566 the negative suffix, plus (if negative) the negative
568 width = rounder_width (r, decimals, &integer_digits, &add_neg_prefix);
569 width += ss_length (style->neg_suffix);
571 width += ss_length (style->neg_prefix);
572 if (width > format->w)
575 /* If there's room for the prefix and suffix, allocate
576 space. If the affixes are required, but there's no
578 add_affixes = allocate_space (fmt_affix_width (style),
580 if (!add_affixes && require_affixes)
583 /* Check whether we should include grouping characters.
584 We need room for a complete set or we don't insert any at all.
585 We don't include grouping characters if decimal places were
586 requested but they were all dropped. */
587 add_grouping = (style->grouping != 0
588 && integer_digits > 3
589 && (format->d == 0 || decimals > 0)
590 && allocate_space ((integer_digits - 1) / 3,
593 /* Format the number's magnitude. */
594 rounder_format (r, decimals, magnitude);
596 /* Assemble number. */
598 if (format->w > width)
599 p = mempset (p, ' ', format->w - width);
601 p = mempcpy (p, ss_data (style->neg_prefix),
602 ss_length (style->neg_prefix));
604 p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix));
606 p = mempcpy (p, magnitude, integer_digits);
610 for (i = 0; i < integer_digits; i++)
612 if (i > 0 && (integer_digits - i) % 3 == 0)
613 *p++ = style->grouping;
619 *p++ = style->decimal;
620 p = mempcpy (p, &magnitude[integer_digits + 1], decimals);
623 p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix));
625 p = mempcpy (p, ss_data (style->neg_suffix),
626 ss_length (style->neg_suffix));
628 p = mempset (p, ' ', ss_length (style->neg_suffix));
629 assert (p == output + format->w);
636 /* Formats NUMBER into OUTPUT in scientific notation according to
637 the style of the format specified in FORMAT. */
639 output_scientific (double number, const struct fmt_spec *format,
640 bool require_affixes, char *output)
642 const struct fmt_number_style *style =
643 settings_get_style (format->type);
649 /* Allocate minimum required space. */
650 width = 6 + ss_length (style->neg_suffix);
652 width += ss_length (style->neg_prefix);
653 if (width > format->w)
656 /* Check for room for prefix and suffix. */
657 add_affixes = allocate_space (fmt_affix_width (style), format->w, &width);
658 if (require_affixes && !add_affixes)
661 /* Figure out number of characters we can use for the fraction,
662 if any. (If that turns out to be 1, then we'll output a
663 decimal point without any digits following; that's what the
664 # flag does in the call to sprintf, below.) */
665 fraction_width = MIN (MIN (format->d + 1, format->w - width), 16);
666 if (format->type != FMT_E && fraction_width == 1)
668 width += fraction_width;
670 /* Format (except suffix). */
672 if (width < format->w)
673 p = mempset (p, ' ', format->w - width);
675 p = mempcpy (p, ss_data (style->neg_prefix),
676 ss_length (style->neg_prefix));
678 p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix));
679 if (fraction_width > 0)
680 sprintf (p, "%#.*E", fraction_width - 1, fabs (number));
682 sprintf (p, "%.0E", fabs (number));
684 /* The C locale always uses a period `.' as a decimal point.
685 Translate to comma if necessary. */
686 if (style->decimal != '.')
688 char *cp = strchr (p, '.');
690 *cp = style->decimal;
693 /* Make exponent have exactly three digits, plus sign. */
695 char *cp = strchr (p, 'E') + 1;
696 long int exponent = strtol (cp, NULL, 10);
697 if (abs (exponent) > 999)
699 sprintf (cp, "%+04ld", exponent);
703 p = strchr (p, '\0');
705 p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix));
707 p = mempcpy (p, ss_data (style->neg_suffix),
708 ss_length (style->neg_suffix));
710 p = mempset (p, ' ', ss_length (style->neg_suffix));
712 assert (p == buf + format->w);
713 memcpy (output, buf, format->w);
718 /* Returns true if the magnitude represented by R should be
719 rounded up when chopped off at DECIMALS decimal places, false
720 if it should be rounded down. */
722 should_round_up (const struct rounder *r, int decimals)
724 int digit = r->string[r->integer_digits + decimals + 1];
725 assert (digit >= '0' && digit <= '9');
729 /* Initializes R for formatting the magnitude of NUMBER to no
730 more than MAX_DECIMAL decimal places. */
732 rounder_init (struct rounder *r, double number, int max_decimals)
734 assert (fabs (number) < 1e41);
735 assert (max_decimals >= 0 && max_decimals <= 16);
736 if (max_decimals == 0)
738 /* Fast path. No rounding needed.
740 We append ".00" to the integer representation because
741 round_up assumes that fractional digits are present. */
742 sprintf (r->string, "%.0f.00", fabs (round (number)));
748 This is more difficult than it really should be because
749 we have to make sure that numbers that are exactly
750 halfway between two representations are always rounded
751 away from zero. This is not what sprintf normally does
752 (usually it rounds to even), so we have to fake it as
753 best we can, by formatting with extra precision and then
754 doing the rounding ourselves.
756 We take up to two rounds to format numbers. In the
757 first round, we obtain 2 digits of precision beyond
758 those requested by the user. If those digits are
759 exactly "50", then in a second round we format with as
760 many digits as are significant in a "double".
762 It might be better to directly implement our own
763 floating-point formatting routine instead of relying on
764 the system's sprintf implementation. But the classic
765 Steele and White paper on printing floating-point
766 numbers does not hint how to do what we want, and it's
767 not obvious how to change their algorithms to do so. It
768 would also be a lot of work. */
769 sprintf (r->string, "%.*f", max_decimals + 2, fabs (number));
770 if (!strcmp (r->string + strlen (r->string) - 2, "50"))
772 int binary_exponent, decimal_exponent, format_decimals;
773 frexp (number, &binary_exponent);
774 decimal_exponent = binary_exponent * 3 / 10;
775 format_decimals = (DBL_DIG + 1) - decimal_exponent;
776 if (format_decimals > max_decimals + 2)
777 sprintf (r->string, "%.*f", format_decimals, fabs (number));
781 if (r->string[0] == '0')
782 memmove (r->string, &r->string[1], strlen (r->string));
784 r->leading_zeros = strspn (r->string, "0.");
785 r->leading_nines = strspn (r->string, "9.");
786 r->integer_digits = strchr (r->string, '.') - r->string;
787 r->negative = number < 0;
790 /* Returns the number of characters required to format the
791 magnitude represented by R to DECIMALS decimal places.
792 The return value includes integer digits and a decimal point
793 and fractional digits, if any, but it does not include any
794 negative prefix or suffix or other affixes.
796 *INTEGER_DIGITS is set to the number of digits before the
797 decimal point in the output, between 0 and 40.
799 If R represents a negative number and its rounded
800 representation would include at least one nonzero digit,
801 *NEGATIVE is set to true; otherwise, it is set to false. */
803 rounder_width (const struct rounder *r, int decimals,
804 int *integer_digits, bool *negative)
806 /* Calculate base measures. */
807 int width = r->integer_digits;
809 width += decimals + 1;
810 *integer_digits = r->integer_digits;
811 *negative = r->negative;
813 /* Rounding can cause adjustments. */
814 if (should_round_up (r, decimals))
816 /* Rounding up leading 9s adds a new digit (a 1). */
817 if (r->leading_nines >= width)
826 if (r->leading_zeros >= width)
828 /* All digits that remain after rounding are zeros.
829 Therefore we drop the negative sign. */
831 if (r->integer_digits == 0 && decimals == 0)
833 /* No digits at all are left. We need to display
834 at least a single digit (a zero). */
844 /* Formats the magnitude represented by R into OUTPUT, rounding
845 to DECIMALS decimal places. Exactly as many characters as
846 indicated by rounder_width are written. No terminating null
849 rounder_format (const struct rounder *r, int decimals, char *output)
851 int base_width = r->integer_digits + (decimals > 0 ? decimals + 1 : 0);
852 if (should_round_up (r, decimals))
854 if (r->leading_nines < base_width)
856 /* Rounding up. This is the common case where rounding
857 up doesn't add an extra digit. */
859 memcpy (output, r->string, base_width);
860 for (p = output + base_width - 1; ; p--)
862 assert (p >= output);
865 else if (*p >= '0' && *p <= '8')
876 /* Rounding up leading 9s causes the result to be a 1
877 followed by a number of 0s, plus a decimal point. */
880 p = mempset (p, '0', r->integer_digits);
884 p = mempset (p, '0', decimals);
886 assert (p == output + base_width + 1);
892 if (r->integer_digits != 0 || decimals != 0)
894 /* Common case: just copy the digits. */
895 memcpy (output, r->string, base_width);
899 /* No digits remain. The output is just a zero. */
905 /* Helper functions. */
908 static double PURE_FUNCTION
911 static const double p[] =
913 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
914 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
915 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
916 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
919 return x >= 0 && x < sizeof p / sizeof *p ? p[x] : pow (10.0, x);
922 /* Returns 256**X. */
923 static double PURE_FUNCTION
926 static const double p[] =
936 18446744073709551616.0
938 return x >= 0 && x < sizeof p / sizeof *p ? p[x] : pow (256.0, x);
941 /* Formats non-finite NUMBER into OUTPUT according to the width
944 output_infinite (double number, const struct fmt_spec *format, char *output)
946 assert (!isfinite (number));
954 else if (isinf (number))
955 s = number > 0 ? "+Infinity" : "-Infinity";
959 buf_copy_str_lpad (output, format->w, s, ' ');
962 output_overflow (format, output);
965 /* Formats OUTPUT as a missing value for the given FORMAT. */
967 output_missing (const struct fmt_spec *format, char *output)
969 memset (output, ' ', format->w);
971 if (format->type != FMT_N)
973 int dot_ofs = (format->type == FMT_PCT ? 2
974 : format->type == FMT_E ? 5
976 output[MAX (0, format->w - format->d - dot_ofs)] = '.';
979 output[format->w - 1] = '.';
982 /* Formats OUTPUT for overflow given FORMAT. */
984 output_overflow (const struct fmt_spec *format, char *output)
986 memset (output, '*', format->w);
989 /* Converts the integer part of NUMBER to a packed BCD number
990 with the given number of DIGITS in OUTPUT. If DIGITS is odd,
991 the least significant nibble of the final byte in OUTPUT is
992 set to 0. Returns true if successful, false if NUMBER is not
993 representable. On failure, OUTPUT is cleared to all zero
996 output_bcd_integer (double number, int digits, char *output)
1000 assert (digits < sizeof decimal);
1001 if (number != SYSMIS
1003 && number < power10 (digits)
1004 && sprintf (decimal, "%0*.0f", digits, round (number)) == digits)
1006 const char *src = decimal;
1009 for (i = 0; i < digits / 2; i++)
1011 int d0 = *src++ - '0';
1012 int d1 = *src++ - '0';
1013 *output++ = (d0 << 4) + d1;
1016 *output = (*src - '0') << 4;
1022 memset (output, 0, DIV_RND_UP (digits, 2));
1027 /* Writes VALUE to OUTPUT as a BYTES-byte binary integer of the
1028 given INTEGER_FORMAT. */
1030 output_binary_integer (uint64_t value, int bytes,
1031 enum integer_format integer_format, char *output)
1033 integer_put (value, integer_format, output, bytes);
1036 /* Converts the BYTES bytes in DATA to twice as many hexadecimal
1037 digits in OUTPUT. */
1039 output_hex (const void *data_, size_t bytes, char *output)
1041 const uint8_t *data = data_;
1044 for (i = 0; i < bytes; i++)
1046 static const char hex_digits[] = "0123456789ABCDEF";
1047 *output++ = hex_digits[data[i] >> 4];
1048 *output++ = hex_digits[data[i] & 15];