mirror of
https://github.com/ThomasDickey/mawk-snapshots.git
synced 2026-01-26 11:04:34 +00:00
133 lines
3.2 KiB
C
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;
|
|
}
|