mawk/makebits.c
2024-11-18 09:26:11 +00:00

133 lines
3.2 KiB
C

/********************************************
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;
}