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