-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmakebits.c
132 lines (110 loc) · 3.15 KB
/
makebits.c
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;
}