-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Expand file tree
/
Copy pathmkfptab.c
More file actions
238 lines (224 loc) · 6.21 KB
/
Copy pathmkfptab.c
File metadata and controls
238 lines (224 loc) · 6.21 KB
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/*
** This program generates C code for the tables used to generate powers
** of 10 in the powerOfTen() subroutine in util.c.
**
** The objective of the powerOfTen() subroutine is to provide the most
** significant 96 bits of any power of 10 between -348 and +347. Rather
** than generate a massive 8K table, three much smaller tables are constructed,
** which can then generate the requested power of 10 using a single
** 160-bit multiple.
**
** This program works by internally generating a table of powers of
** 10 accurate to 256 bits each. It then that full-sized, high-accuracy
** table to construct the three smaller tables needed by powerOfTen().
**
** LIMITATION:
**
** This program uses the __uint128_t datatype, available in gcc/clang.
** It won't build using other compilers.
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
typedef unsigned __int128 u128; /* 128-bit unsigned integer */
typedef unsigned long long int u64; /* 64-bit unsigned integer */
/* There is no native 256-bit unsigned integer type, so synthesize one
** using four 64-bit unsigned integers. Must significant first. */
struct u256 {
u64 a[4]; /* big-endian */
};
typedef struct u256 u256;
/*
** Return a u64 with the N-th bit set.
*/
#define U64_BIT(N) (((u64)1)<<(N))
/* Multiple *pX by 10, in-place */
static void u256_times_10(u256 *pX){
u64 carry = 0;
int i;
for(i=3; i>=0; i--){
u128 y = (10 * (u128)pX->a[i]) + carry;
pX->a[i] = (u64)y;
carry = (u64)(y>>64);
}
}
/* Multiple *pX by 2, in-place. AKA, left-shift */
static void u256_times_2(u256 *pX){
u64 carry = 0;
int i;
for(i=3; i>=0; i--){
u64 y = pX->a[i];
pX->a[i] = (y<<1) | carry;
carry = y>>63;
}
}
/* Divide *pX by 10, in-place */
static void u256_div_10(u256 *pX){
u64 rem = 0;
int i;
for(i=0; i<4; i++){
u128 acc = (((u128)rem)<<64) | pX->a[i];
pX->a[i] = acc/10;
rem = (u64)(acc%10);
}
}
/* Divide *pX by 2, in-place, AKA, right-shift */
static void u256_div_2(u256 *pX){
u64 rem = 0;
int i;
for(i=0; i<4; i++){
u64 y = pX->a[i];
pX->a[i] = (y>>1) | (rem<<63);
rem = y&1;
}
}
/* Note: The main table is a little larger on the low end than the required
** range of -348..+347, since we need the -351 value for the reduced tables.
*/
#define SCALE_FIRST (-351) /* Least power-of-10 */
#define SCALE_LAST (+347) /* Largest power-of-10 */
#define SCALE_COUNT (SCALE_LAST - SCALE_FIRST + 1) /* Size of main table */
#define SCALE_ZERO (351)
int main(int argc, char **argv){
int i, j, iNext;
int e;
int bRound = 0;
int bTruth = 0;
const u64 top = ((u64)1)<<63;
u256 v;
u64 aHi[SCALE_COUNT];
u64 aLo[SCALE_COUNT];
int aE[SCALE_COUNT];
for(i=1; i<argc; i++){
const char *z = argv[i];
if( z[0]=='-' && z[1]=='-' && z[2]!=0 ) z++;
if( strcmp(z,"-round")==0 ){
bRound = 1;
}else
if( strcmp(z,"-truth")==0 ){
bTruth = 1;
}else
{
fprintf(stderr, "unknown option: \"%s\"\n", argv[i]);
exit(1);
}
}
/* Generate the master 256-bit power-of-10 table */
v.a[0] = top;
v.a[1] = 0;
v.a[2] = 0;
v.a[3] = 0;
for(i=SCALE_ZERO, e=63; i>=0; i--){
aHi[i] = v.a[0];
aLo[i] = v.a[1];
aE[i] = e;
u256_div_10(&v);
while( v.a[0] < top ){
e++;
u256_times_2(&v);
}
}
v.a[0] = 0;
v.a[1] = top;
v.a[2] = 0;
v.a[3] = 0;
for(i=SCALE_ZERO+1, e=63; i<SCALE_COUNT; i++){
u256_times_10(&v);
while( v.a[0]>0 ){
e--;
u256_div_2(&v);
}
aHi[i] = v.a[1];
aLo[i] = v.a[2];
aE[i] = e;
}
if( bTruth ){
/* With the --truth flag, also output the aTruth[] table that
** contains 128 bits of every power-of-two in the range */
printf(" /* Powers of ten, accurate to 128 bits each */\n");
printf(" static const struct {u64 hi; u64 lo;} aTruth[] = {\n");
for(i=0; i<SCALE_COUNT; i++){
u64 x = aHi[i];
u64 y = aLo[i];
int e = aE[i];
char *zOp;
if( e>0 ){
zOp = "<<";
}else{
e = -e;
zOp = ">>";
}
printf(" {0x%016llx, 0x%016llx}, /* %2d: 1.0e%+d %s %d */\n",
x, y, i, i+SCALE_FIRST, zOp, e);
}
printf(" };\n");
}
/* The aBase[] table contains powers of 10 between 0 and 26. These
** all fit in a single 64-bit integer.
*/
printf(" static const u64 aBase[] = {\n");
for(i=SCALE_ZERO, j=0; i<SCALE_ZERO+27; i++, j++){
u64 x = aHi[i];
int e = aE[i];
char *zOp;
if( e>0 ){
zOp = "<<";
}else{
e = -e;
zOp = ">>";
}
printf(" UINT64_C(0x%016llx), /* %2d: 1.0e%+d %s %d */\n",
x, j, i+SCALE_FIRST, zOp, e);
}
printf(" };\n");
/* For powers of 10 outside the range [0..26], we have to multiple
** on of the aBase[] entries by a scaling factor to get the true
** power of ten. The scaling factors are all approximates accurate
** to 96 bytes, represented by a 64-bit integer in aScale[] for the
** most significant bits and a 32-bit integer in aScaleLo[] for the
** next 32 bites.
**
** The scale factors are at increments of 27. Except, the entry for 0
** is replaced by the -1 value as a special case.
*/
printf(" static const u64 aScale[] = {\n");
for(i=j=0; i<SCALE_COUNT; i=iNext, j++){
const char *zExtra = "";
iNext = i+27;
if( i==SCALE_ZERO ){ i--; zExtra = " (special case)"; }
u64 x = aHi[i];
int e = aE[i];
char *zOp;
if( e>0 ){
zOp = "<<";
}else{
e = -e;
zOp = ">>";
}
printf(" UINT64_C(0x%016llx), /* %2d: 1.0e%+d %s %d%s */\n",
x, j, i+SCALE_FIRST, zOp, e, zExtra);
}
printf(" };\n");
printf(" static const unsigned int aScaleLo[] = {\n");
for(i=j=0; i<SCALE_COUNT; i=iNext, j++){
const char *zExtra = "";
iNext = i+27;
if( i==SCALE_ZERO ){ i--; zExtra = " (special case)"; }
u64 x = aLo[i];
int e = aE[i];
char *zOp;
if( bRound && (x & U64_BIT(31))!=0 && i!=SCALE_ZERO-1 ) x += U64_BIT(32);
if( e>0 ){
zOp = "<<";
}else{
e = -e;
zOp = ">>";
}
printf(" 0x%08llx, /* %2d: 1.0e%+d %s %d%s */\n",
x>>32, j, i+SCALE_FIRST, zOp, e, zExtra);
}
printf(" };\n");
return 0;
}