1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
/********************************************
makebits.c
copyright 2024, Thomas E. Dickey
This is a source file for mawk, an implementation of
the AWK programming language.
Mawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
********************************************/
/*
* $MawkId: makebits.c,v 1.1 2024/11/17 20:33:16 tom Exp $
*/
#include "config.h"
#include <stdio.h>
#include <limits.h>
#include <sys/types.h>
#define my_name "_MAKEBITS_H"
static int
digits_of(double value)
{
int result = 0;
while (value >= 1.0) {
value /= 10.0;
++result;
}
return result;
}
static void
header(void)
{
printf("/* this file was generated by makebits */\n");
printf("\n");
printf("#ifndef %s\n", my_name);
printf("#define %s 1\n", my_name);
}
static void
section(const char *msg)
{
printf("\n");
printf("/* %s */\n", msg);
}
static void
footer(void)
{
printf("\n");
printf("#endif /* %s */\n", my_name);
}
int main(void)
{
double unsigned_limits;
double integers_limits;
int unsigned_digits;
int integers_digits;
int n;
#ifdef HAVE_LONG_LONG
union {
double dd;
unsigned long long ll;
} samebits;
unsigned len_significand;
double max_significand;
header();
section("significand size");
/*
* Assume IEEE floating point, which means that "1.0" has all 0's to the
* right of the exponent (which happens to be an odd number for "1.0").
*
* The maximum number of bits in the significand should be 53 for 32-bit
* and 64-bit double format, provided that we have long long.
*/
samebits.dd = 1.0;
for (len_significand = 1; (samebits.ll & 1) == 0; ++len_significand) {
samebits.ll /= 2;
}
printf("#define LEN_SIGNIFICAND %d\n", len_significand);
/*
* When converting to/from double, we are limited by the significand's
* number of bits.
*/
max_significand = 1.0;
for (n = 0; n < (int) len_significand; ++n) {
max_significand *= 2.0;
}
printf("#define MAX_SIGNIFICAND %.30g\n", max_significand);
#else
header();
#endif
section("limits for integer/floating conversion");
/*
* For maximum precision, use integer arithmetic (e.g., 2^32 - 1 for
* unsigned values), plus the special case of the first power-of-two value
* past the integer range.
*/
unsigned_limits = 1.0;
for (n = 0; n < (int) (CHAR_BIT * sizeof(double)); ++n) {
unsigned_limits *= 2.0;
}
integers_limits = unsigned_limits / 2.0;
printf("#define UNSIGNED_LIMITS %.30g.0\n", unsigned_limits);
printf("#define INTEGERS_LIMITS %.30g.0\n", integers_limits);
section("number of digits for integer/floating special case");
unsigned_digits = digits_of(unsigned_limits);
integers_digits = digits_of(integers_limits);
printf("#define UNSIGNED_DIGITS %d\n", unsigned_digits);
printf("#define INTEGERS_DIGITS %d\n", integers_digits);
section("format for integer/floating special case");
printf("#define UNSIGNED_FORMAT \"%%.%dg\"\n", unsigned_digits);
printf("#define INTEGERS_FORMAT \"%%.%dg\"\n", integers_digits);
footer();
return 0;
}
|