yeptris 0.6.18.2-arm-linux-eabihf
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.adoc +141 -0
- data/ext/build_windows_native.rb +41 -0
- data/ext/libyeptris/extconf.rb +57 -0
- data/ext/yeptris_native/cbor_ruby.c +193 -0
- data/ext/yeptris_native/extconf.rb +47 -0
- data/ext/yeptris_native/json_ruby.c +354 -0
- data/ext/yeptris_native/yeptris_native.c +497 -0
- data/lib/yeptris/cbor.rb +130 -0
- data/lib/yeptris/document.rb +255 -0
- data/lib/yeptris/ffi.rb +426 -0
- data/lib/yeptris/json/descriptor.rb +266 -0
- data/lib/yeptris/json.rb +394 -0
- data/lib/yeptris/materializer.rb +354 -0
- data/lib/yeptris/native-3.4.so +0 -0
- data/lib/yeptris/node.rb +453 -0
- data/lib/yeptris/psych/class_loader.rb +24 -0
- data/lib/yeptris/psych/coder_shim.rb +55 -0
- data/lib/yeptris/psych/drop_in.rb +63 -0
- data/lib/yeptris/psych/encodable.rb +14 -0
- data/lib/yeptris/psych/handler.rb +90 -0
- data/lib/yeptris/psych/parser.rb +105 -0
- data/lib/yeptris/psych/scalar_scanner.rb +149 -0
- data/lib/yeptris/psych/visitors.rb +545 -0
- data/lib/yeptris/psych.rb +622 -0
- data/lib/yeptris/schema.rb +253 -0
- data/lib/yeptris/valueml.rb +455 -0
- data/lib/yeptris/yaml/descriptor.rb +56 -0
- data/lib/yeptris/yaml.rb +422 -0
- data/lib/yeptris.rb +113 -0
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +254 -0
- data/vendor/libyeptris/cmake/yeptris-config.cmake.in +5 -0
- data/vendor/libyeptris/cmake/yeptris.pc.in +11 -0
- data/vendor/libyeptris/src/CMakeLists.txt +167 -0
- data/vendor/libyeptris/src/include/yeptris/api.h +32 -0
- data/vendor/libyeptris/src/include/yeptris/cbor.h +101 -0
- data/vendor/libyeptris/src/include/yeptris/dom.h +190 -0
- data/vendor/libyeptris/src/include/yeptris/emit.h +81 -0
- data/vendor/libyeptris/src/include/yeptris/error.h +41 -0
- data/vendor/libyeptris/src/include/yeptris/events.h +157 -0
- data/vendor/libyeptris/src/include/yeptris/json.h +45 -0
- data/vendor/libyeptris/src/include/yeptris/json.hpp +258 -0
- data/vendor/libyeptris/src/include/yeptris/jsonc_compat.h +115 -0
- data/vendor/libyeptris/src/include/yeptris/marshal.h +52 -0
- data/vendor/libyeptris/src/include/yeptris/parse.h +48 -0
- data/vendor/libyeptris/src/include/yeptris/plan.h +100 -0
- data/vendor/libyeptris/src/include/yeptris/resolve.h +71 -0
- data/vendor/libyeptris/src/include/yeptris/schema.h +121 -0
- data/vendor/libyeptris/src/include/yeptris/tape.h +123 -0
- data/vendor/libyeptris/src/include/yeptris/types.h +38 -0
- data/vendor/libyeptris/src/include/yeptris/values.h +102 -0
- data/vendor/libyeptris/src/include/yeptris/version.h.in +29 -0
- data/vendor/libyeptris/src/include/yeptris/visit.h +77 -0
- data/vendor/libyeptris/src/include/yeptris/yajl_compat.h +135 -0
- data/vendor/libyeptris/src/include/yeptris.h +23 -0
- data/vendor/libyeptris/src/yeptris/build.c +376 -0
- data/vendor/libyeptris/src/yeptris/cbor/cbor.h +25 -0
- data/vendor/libyeptris/src/yeptris/cbor/decode.c +981 -0
- data/vendor/libyeptris/src/yeptris/cbor/encode.c +835 -0
- data/vendor/libyeptris/src/yeptris/cbor/sink.h +58 -0
- data/vendor/libyeptris/src/yeptris/common/chartype.c +41 -0
- data/vendor/libyeptris/src/yeptris/common/chartype.h +77 -0
- data/vendor/libyeptris/src/yeptris/common/cpu.c +81 -0
- data/vendor/libyeptris/src/yeptris/common/cpu.h +40 -0
- data/vendor/libyeptris/src/yeptris/common/error.c +65 -0
- data/vendor/libyeptris/src/yeptris/common/error.h +79 -0
- data/vendor/libyeptris/src/yeptris/common/mutex.h +45 -0
- data/vendor/libyeptris/src/yeptris/common/nametab.c +275 -0
- data/vendor/libyeptris/src/yeptris/common/nametab.h +68 -0
- data/vendor/libyeptris/src/yeptris/common/port.h +74 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text.c +49 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text.h +295 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text_avx2.c +534 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text_neon.c +662 -0
- data/vendor/libyeptris/src/yeptris/common/simd_text_scalar.c +298 -0
- data/vendor/libyeptris/src/yeptris/common/string_view.c +34 -0
- data/vendor/libyeptris/src/yeptris/common/string_view.h +93 -0
- data/vendor/libyeptris/src/yeptris/doc.h +56 -0
- data/vendor/libyeptris/src/yeptris/dom/dom.c +1192 -0
- data/vendor/libyeptris/src/yeptris/dom/dom.h +312 -0
- data/vendor/libyeptris/src/yeptris/dom/hpool.c +107 -0
- data/vendor/libyeptris/src/yeptris/dom/mapindex.c +173 -0
- data/vendor/libyeptris/src/yeptris/dom/mapindex.h +61 -0
- data/vendor/libyeptris/src/yeptris/dom/mutate.c +431 -0
- data/vendor/libyeptris/src/yeptris/emit/emit.c +434 -0
- data/vendor/libyeptris/src/yeptris/emit/float/api.h +38 -0
- data/vendor/libyeptris/src/yeptris/emit/float/dragon.c +405 -0
- data/vendor/libyeptris/src/yeptris/emit/float/floatint.h +231 -0
- data/vendor/libyeptris/src/yeptris/emit/float/print.c +396 -0
- data/vendor/libyeptris/src/yeptris/emit/style.c +81 -0
- data/vendor/libyeptris/src/yeptris/emit/style.h +24 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.c +816 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.h +76 -0
- data/vendor/libyeptris/src/yeptris/encoding/bom.c +31 -0
- data/vendor/libyeptris/src/yeptris/encoding/encoding.h +63 -0
- data/vendor/libyeptris/src/yeptris/encoding/transcode.c +148 -0
- data/vendor/libyeptris/src/yeptris/encoding/utf8_validate.c +178 -0
- data/vendor/libyeptris/src/yeptris/events/capture.c +150 -0
- data/vendor/libyeptris/src/yeptris/events/capture.h +39 -0
- data/vendor/libyeptris/src/yeptris/events/iterparse.c +208 -0
- data/vendor/libyeptris/src/yeptris/events/pull.c +97 -0
- data/vendor/libyeptris/src/yeptris/events/push.c +104 -0
- data/vendor/libyeptris/src/yeptris/events/recorder.c +107 -0
- data/vendor/libyeptris/src/yeptris/events/values.c +527 -0
- data/vendor/libyeptris/src/yeptris/events/values_priv.h +51 -0
- data/vendor/libyeptris/src/yeptris/events/yaml_compat.c +86 -0
- data/vendor/libyeptris/src/yeptris/events/yaml_compat.h +90 -0
- data/vendor/libyeptris/src/yeptris/jsonapi/jsonc_compat.c +687 -0
- data/vendor/libyeptris/src/yeptris/jsonapi/yajl_compat.c +728 -0
- data/vendor/libyeptris/src/yeptris/marshal.c +782 -0
- data/vendor/libyeptris/src/yeptris/memory/allocator.c +20 -0
- data/vendor/libyeptris/src/yeptris/memory/allocator.h +43 -0
- data/vendor/libyeptris/src/yeptris/memory/arena.c +134 -0
- data/vendor/libyeptris/src/yeptris/memory/arena.h +52 -0
- data/vendor/libyeptris/src/yeptris/memory/pool.c +122 -0
- data/vendor/libyeptris/src/yeptris/memory/pool.h +36 -0
- data/vendor/libyeptris/src/yeptris/parse/engine.c +3698 -0
- data/vendor/libyeptris/src/yeptris/parse/engine.h +65 -0
- data/vendor/libyeptris/src/yeptris/parse/events.h +124 -0
- data/vendor/libyeptris/src/yeptris/parse/numbers.c +349 -0
- data/vendor/libyeptris/src/yeptris/parse/numbers.h +33 -0
- data/vendor/libyeptris/src/yeptris/parse/scalars.c +416 -0
- data/vendor/libyeptris/src/yeptris/parse/scalars.h +75 -0
- data/vendor/libyeptris/src/yeptris/parse.c +737 -0
- data/vendor/libyeptris/src/yeptris/plan.c +824 -0
- data/vendor/libyeptris/src/yeptris/resolve/compat11.c +334 -0
- data/vendor/libyeptris/src/yeptris/resolve/core12.c +143 -0
- data/vendor/libyeptris/src/yeptris/resolve/resolver.h +56 -0
- data/vendor/libyeptris/src/yeptris/resolve/tags.c +58 -0
- data/vendor/libyeptris/src/yeptris/scan/json.c +792 -0
- data/vendor/libyeptris/src/yeptris/scan/json.h +109 -0
- data/vendor/libyeptris/src/yeptris/scan/scan.c +463 -0
- data/vendor/libyeptris/src/yeptris/scan/scan.h +150 -0
- data/vendor/libyeptris/src/yeptris/schema.c +308 -0
- data/vendor/libyeptris/src/yeptris/tape.c +1308 -0
- data/vendor/libyeptris/src/yeptris/tape_in.h +19 -0
- data/vendor/libyeptris/src/yeptris/version.c +7 -0
- data/vendor/libyeptris/src/yeptris/visit/dom_visit.c +115 -0
- data/vendor/libyeptris/src/yeptris/visit/json_visit.c +293 -0
- data/vendor/libyeptris/src/yeptris/visit/yaml_visit.c +127 -0
- metadata +199 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
/* dragon.c — tier B: exact shortest/fixed output via the interval
|
|
2
|
+
* method over a fixed-capacity limb vector (TODO.impl/14, clean room).
|
|
3
|
+
*
|
|
4
|
+
* v = r/s exactly with r, s, mm, mp integers: value r/s, round-trip
|
|
5
|
+
* interval ((r - mm)/s, (r + mp)/s). Each digit step advances r, mm,
|
|
6
|
+
* mp by 10 (s fixed) so the boundaries stay in the remaining-value
|
|
7
|
+
* space. A position can stop iff truncating (error r/s <= mm/s) or
|
|
8
|
+
* rounding up (error (s-r)/s <= mp/s) stays inside; when both are
|
|
9
|
+
* legal the nearer wins, ties to the even digit (reparse is
|
|
10
|
+
* round-to-nearest-even). When neither is legal, another digit is
|
|
11
|
+
* required — IEEE-754 guarantees termination by 17 digits (double) /
|
|
12
|
+
* 9 (float).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
#include <string.h>
|
|
16
|
+
|
|
17
|
+
#include "emit/float/floatint.h"
|
|
18
|
+
|
|
19
|
+
/* ---- tiny limb vector: 32-bit limbs, little-endian ---- */
|
|
20
|
+
|
|
21
|
+
#define LIMBS 44 /* < 1080 binary digits + decimal scaling headroom */
|
|
22
|
+
|
|
23
|
+
typedef struct {
|
|
24
|
+
uint32_t d[LIMBS];
|
|
25
|
+
int n;
|
|
26
|
+
} num;
|
|
27
|
+
|
|
28
|
+
static void num_zero(num* a) {
|
|
29
|
+
memset(a, 0, sizeof(*a));
|
|
30
|
+
a->n = 1;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static void num_set_u64(num* a, uint64_t v) {
|
|
34
|
+
num_zero(a);
|
|
35
|
+
a->d[0] = (uint32_t)v;
|
|
36
|
+
a->d[1] = (uint32_t)(v >> 32);
|
|
37
|
+
a->n = a->d[1] ? 2 : 1;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static int num_cmp(const num* a, const num* b) {
|
|
41
|
+
if (a->n != b->n) {
|
|
42
|
+
return a->n < b->n ? -1 : 1;
|
|
43
|
+
}
|
|
44
|
+
for (int i = a->n - 1; i >= 0; i--) {
|
|
45
|
+
if (a->d[i] != b->d[i]) {
|
|
46
|
+
return a->d[i] < b->d[i] ? -1 : 1;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static void num_trim(num* a) {
|
|
53
|
+
while (a->n > 1 && a->d[a->n - 1] == 0) {
|
|
54
|
+
a->n--;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static int num_add(num* a, const num* b) {
|
|
59
|
+
uint64_t carry = 0;
|
|
60
|
+
int n = a->n > b->n ? a->n : b->n;
|
|
61
|
+
for (int i = 0; i < n; i++) {
|
|
62
|
+
uint64_t s = (uint64_t)a->d[i] + (uint64_t)(i < b->n ? b->d[i] : 0) + carry;
|
|
63
|
+
a->d[i] = (uint32_t)s;
|
|
64
|
+
carry = s >> 32;
|
|
65
|
+
}
|
|
66
|
+
a->n = n;
|
|
67
|
+
if (carry) {
|
|
68
|
+
if (a->n >= LIMBS) {
|
|
69
|
+
return -1;
|
|
70
|
+
}
|
|
71
|
+
a->d[a->n++] = (uint32_t)carry;
|
|
72
|
+
}
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static void num_sub(num* a, const num* b) {
|
|
77
|
+
int64_t borrow = 0;
|
|
78
|
+
for (int i = 0; i < a->n; i++) {
|
|
79
|
+
int64_t s = (int64_t)a->d[i] - (int64_t)(i < b->n ? b->d[i] : 0) - borrow;
|
|
80
|
+
if (s < 0) {
|
|
81
|
+
s += ((int64_t)1 << 32);
|
|
82
|
+
borrow = 1;
|
|
83
|
+
} else {
|
|
84
|
+
borrow = 0;
|
|
85
|
+
}
|
|
86
|
+
a->d[i] = (uint32_t)s;
|
|
87
|
+
}
|
|
88
|
+
num_trim(a);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static int num_shl(num* a, int bits) {
|
|
92
|
+
for (; bits >= 32; bits -= 32) {
|
|
93
|
+
for (int i = a->n; i > 0; i--) {
|
|
94
|
+
a->d[i] = a->d[i - 1];
|
|
95
|
+
}
|
|
96
|
+
a->d[0] = 0;
|
|
97
|
+
a->n++;
|
|
98
|
+
if (a->n > LIMBS) {
|
|
99
|
+
return -1;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (bits > 0) {
|
|
103
|
+
uint32_t carry = 0;
|
|
104
|
+
for (int i = 0; i < a->n; i++) {
|
|
105
|
+
uint32_t nc = a->d[i] >> (32 - bits);
|
|
106
|
+
a->d[i] = (a->d[i] << bits) | carry;
|
|
107
|
+
carry = nc;
|
|
108
|
+
}
|
|
109
|
+
if (carry) {
|
|
110
|
+
if (a->n >= LIMBS) {
|
|
111
|
+
return -1;
|
|
112
|
+
}
|
|
113
|
+
a->d[a->n++] = carry;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return 0;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
static void num_shr(num* a, int bits) {
|
|
120
|
+
int limbs = bits / 32;
|
|
121
|
+
int rem = bits % 32;
|
|
122
|
+
if (limbs >= a->n) {
|
|
123
|
+
memset(a->d, 0, sizeof(uint32_t) * (size_t)a->n);
|
|
124
|
+
a->n = 1;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
for (int i = 0; i + limbs < a->n; i++) {
|
|
128
|
+
/* rem == 0 would shift by 32 (UB on uint32_t) — the hi limb
|
|
129
|
+
* is only meaningful when there IS a fractional shift */
|
|
130
|
+
if (rem == 0) {
|
|
131
|
+
a->d[i] = a->d[i + limbs];
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
uint32_t lo = a->d[i + limbs] >> rem;
|
|
135
|
+
uint32_t hi = (i + limbs + 1 < a->n) ? a->d[i + limbs + 1] << (32 - rem) : 0;
|
|
136
|
+
a->d[i] = lo | hi;
|
|
137
|
+
}
|
|
138
|
+
for (int i = a->n - limbs; i < a->n; i++) {
|
|
139
|
+
a->d[i] = 0;
|
|
140
|
+
}
|
|
141
|
+
a->n -= limbs;
|
|
142
|
+
num_trim(a);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
static int num_mul10(num* a) {
|
|
146
|
+
uint64_t carry = 0;
|
|
147
|
+
for (int i = 0; i < a->n; i++) {
|
|
148
|
+
uint64_t p = (uint64_t)a->d[i] * 10 + carry;
|
|
149
|
+
a->d[i] = (uint32_t)p;
|
|
150
|
+
carry = p >> 32;
|
|
151
|
+
}
|
|
152
|
+
if (carry) {
|
|
153
|
+
if (a->n >= LIMBS) {
|
|
154
|
+
return -1;
|
|
155
|
+
}
|
|
156
|
+
a->d[a->n++] = (uint32_t)carry;
|
|
157
|
+
}
|
|
158
|
+
return 0;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
static int num_is_zero(const num* a) {
|
|
162
|
+
return a->n == 1 && a->d[0] == 0;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* Decimal digits of a (a >= 0) into dst[cap]; a == 0 yields "0".
|
|
166
|
+
* Returns the length, or -1 on overflow of cap. */
|
|
167
|
+
static int num_to_digits(const num* a, char* dst, int cap) {
|
|
168
|
+
char rev[400];
|
|
169
|
+
int n = 0;
|
|
170
|
+
if (num_is_zero(a)) {
|
|
171
|
+
if (cap < 1) {
|
|
172
|
+
return -1;
|
|
173
|
+
}
|
|
174
|
+
dst[0] = '0';
|
|
175
|
+
return 1;
|
|
176
|
+
}
|
|
177
|
+
num t = *a;
|
|
178
|
+
while (!num_is_zero(&t)) {
|
|
179
|
+
uint64_t rem = 0;
|
|
180
|
+
for (int i = t.n - 1; i >= 0; i--) {
|
|
181
|
+
uint64_t cur = (rem << 32) | t.d[i];
|
|
182
|
+
t.d[i] = (uint32_t)(cur / 1000000000u);
|
|
183
|
+
rem = cur % 1000000000u;
|
|
184
|
+
}
|
|
185
|
+
num_trim(&t);
|
|
186
|
+
for (int k = 0; k < 9; k++) {
|
|
187
|
+
rev[n++] = (char)('0' + (int)(rem % 10));
|
|
188
|
+
rem /= 10;
|
|
189
|
+
if (rem == 0 && num_is_zero(&t)) {
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (n >= (int)sizeof(rev)) {
|
|
194
|
+
return -1;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (n > cap) {
|
|
198
|
+
return -1;
|
|
199
|
+
}
|
|
200
|
+
for (int i = 0; i < n; i++) {
|
|
201
|
+
dst[i] = rev[n - 1 - i];
|
|
202
|
+
}
|
|
203
|
+
return n;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* ---- exact shortest ---- */
|
|
207
|
+
|
|
208
|
+
int yep_dragon_shortest(uint64_t m2, int e2, int mb, int pow2_low, int tie_even, yep_dsplit* out) {
|
|
209
|
+
num r, s, mm, mp;
|
|
210
|
+
num_set_u64(&r, m2);
|
|
211
|
+
num_zero(&s);
|
|
212
|
+
s.d[0] = 1;
|
|
213
|
+
num_set_u64(&mm, 1);
|
|
214
|
+
num_set_u64(&mp, 1);
|
|
215
|
+
if (e2 >= 0) {
|
|
216
|
+
if (num_shl(&r, e2) != 0 || num_shl(&mm, e2 - 1) != 0) {
|
|
217
|
+
return -1;
|
|
218
|
+
}
|
|
219
|
+
mp = mm;
|
|
220
|
+
} else {
|
|
221
|
+
/* v = m2 / 2^-e2 with HALF-ulp boundaries: express with r = 2*m2
|
|
222
|
+
* over s = 2^(1-e2) so mm = mp = 1 is exactly the half-ulp */
|
|
223
|
+
if (num_shl(&r, 1) != 0 || num_shl(&s, 1 - e2) != 0) {
|
|
224
|
+
return -1;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (pow2_low) {
|
|
228
|
+
/* power of two: the lower neighbor is one binade down, so the
|
|
229
|
+
* lower half-ulp is half the upper — widen by scaling r, s, mp
|
|
230
|
+
* by 2 (mm untouched halves relative to mp) */
|
|
231
|
+
if (num_shl(&r, 1) != 0 || num_shl(&s, 1) != 0 || num_shl(&mp, 1) != 0) {
|
|
232
|
+
return -1;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/* normalize the remaining value into [1/10, 1): v = 0.<digits> x 10^k */
|
|
237
|
+
int k = 0;
|
|
238
|
+
{
|
|
239
|
+
num rmp = r;
|
|
240
|
+
if (num_add(&rmp, &mp) != 0) {
|
|
241
|
+
return -1;
|
|
242
|
+
}
|
|
243
|
+
while (num_cmp(&rmp, &s) <= 0) {
|
|
244
|
+
num_mul10(&r);
|
|
245
|
+
num_mul10(&mm);
|
|
246
|
+
num_mul10(&mp);
|
|
247
|
+
rmp = r;
|
|
248
|
+
if (num_add(&rmp, &mp) != 0) {
|
|
249
|
+
return -1;
|
|
250
|
+
}
|
|
251
|
+
k--;
|
|
252
|
+
}
|
|
253
|
+
while (num_cmp(&r, &s) >= 0) {
|
|
254
|
+
if (num_mul10(&s) != 0) {
|
|
255
|
+
return -1;
|
|
256
|
+
}
|
|
257
|
+
k++;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const int max_digits = (mb >= 52) ? 17 : 9;
|
|
262
|
+
char digits[24];
|
|
263
|
+
int n = 0;
|
|
264
|
+
for (;;) {
|
|
265
|
+
num_mul10(&r);
|
|
266
|
+
num_mul10(&mm);
|
|
267
|
+
num_mul10(&mp);
|
|
268
|
+
int d = 0;
|
|
269
|
+
while (num_cmp(&r, &s) >= 0) {
|
|
270
|
+
num_sub(&r, &s);
|
|
271
|
+
d++;
|
|
272
|
+
}
|
|
273
|
+
digits[n] = (char)('0' + d);
|
|
274
|
+
n++;
|
|
275
|
+
/* can truncation stay inside? error r <= mm */
|
|
276
|
+
num rmm = mm;
|
|
277
|
+
int eq_down = num_cmp(&r, &rmm) == 0;
|
|
278
|
+
int can_down = num_cmp(&r, &rmm) < 0 || (tie_even && eq_down);
|
|
279
|
+
/* can rounding up stay inside? error (s - r) <= mp */
|
|
280
|
+
num sr = s;
|
|
281
|
+
num_sub(&sr, &r);
|
|
282
|
+
int eq_up = num_cmp(&sr, &mp) == 0;
|
|
283
|
+
int can_up = num_cmp(&sr, &mp) < 0 || (tie_even && eq_up);
|
|
284
|
+
if (can_down || can_up) {
|
|
285
|
+
int up;
|
|
286
|
+
if (can_down && can_up) {
|
|
287
|
+
num t = r;
|
|
288
|
+
if (num_add(&t, &r) != 0) {
|
|
289
|
+
return -1;
|
|
290
|
+
}
|
|
291
|
+
int c = num_cmp(&t, &s);
|
|
292
|
+
if (c > 0) {
|
|
293
|
+
up = 1;
|
|
294
|
+
} else if (c < 0) {
|
|
295
|
+
up = 0;
|
|
296
|
+
} else {
|
|
297
|
+
up = (d % 2) != 0; /* tie to the even digit */
|
|
298
|
+
}
|
|
299
|
+
} else {
|
|
300
|
+
up = can_up;
|
|
301
|
+
}
|
|
302
|
+
if (up) {
|
|
303
|
+
int i = n - 1;
|
|
304
|
+
for (;;) {
|
|
305
|
+
if (digits[i] != '9') {
|
|
306
|
+
digits[i]++;
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
digits[i] = '0';
|
|
310
|
+
if (i == 0) {
|
|
311
|
+
for (int j = n; j > 0; j--) {
|
|
312
|
+
digits[j] = digits[j - 1];
|
|
313
|
+
}
|
|
314
|
+
digits[0] = '1';
|
|
315
|
+
n++;
|
|
316
|
+
k++;
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
i--;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
if (n >= max_digits) {
|
|
325
|
+
/* safety net: 17 (9) significant digits always round-trip */
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
328
|
+
if (n >= 23) {
|
|
329
|
+
return -1;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
memcpy(out->digits, digits, (size_t)n);
|
|
333
|
+
out->len = n;
|
|
334
|
+
out->k = k;
|
|
335
|
+
return 0;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* ---- exact fixed notation: digits of round_half_even(v x 10^p) ---- */
|
|
339
|
+
|
|
340
|
+
int yep_dragon_fixed(uint64_t m2, int e2, uint32_t precision, char* buf) {
|
|
341
|
+
num q;
|
|
342
|
+
num_set_u64(&q, m2);
|
|
343
|
+
if (e2 >= 0) {
|
|
344
|
+
if (num_shl(&q, e2) != 0) {
|
|
345
|
+
return -1;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
for (uint32_t i = 0; i < precision; i++) {
|
|
349
|
+
if (num_mul10(&q) != 0) {
|
|
350
|
+
return -1;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
if (e2 < 0) {
|
|
354
|
+
/* digits = round_half_even(N / 2^-e2): the remainder against
|
|
355
|
+
* the exact half decides; ties round to the even quotient */
|
|
356
|
+
int bits = -e2;
|
|
357
|
+
num half;
|
|
358
|
+
num_set_u64(&half, 1);
|
|
359
|
+
if (num_shl(&half, bits - 1) != 0) {
|
|
360
|
+
return -1;
|
|
361
|
+
}
|
|
362
|
+
num qshift = q;
|
|
363
|
+
num_shr(&qshift, bits);
|
|
364
|
+
num back = qshift;
|
|
365
|
+
if (num_shl(&back, bits) != 0) {
|
|
366
|
+
return -1;
|
|
367
|
+
}
|
|
368
|
+
num rem = q;
|
|
369
|
+
num_sub(&rem, &back);
|
|
370
|
+
int cmp = num_cmp(&rem, &half);
|
|
371
|
+
if (cmp > 0 || (cmp == 0 && (qshift.d[0] & 1))) {
|
|
372
|
+
num one;
|
|
373
|
+
num_set_u64(&one, 1);
|
|
374
|
+
if (num_add(&qshift, &one) != 0) {
|
|
375
|
+
return -1;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
q = qshift;
|
|
379
|
+
}
|
|
380
|
+
char digits[400];
|
|
381
|
+
int len = num_to_digits(&q, digits, (int)sizeof(digits));
|
|
382
|
+
if (len < 0) {
|
|
383
|
+
return -1;
|
|
384
|
+
}
|
|
385
|
+
const char* tmp = digits;
|
|
386
|
+
if (precision == 0) {
|
|
387
|
+
memcpy(buf, tmp, (size_t)len);
|
|
388
|
+
return len;
|
|
389
|
+
}
|
|
390
|
+
if ((uint32_t)len <= precision) {
|
|
391
|
+
int pad = (int)precision - len;
|
|
392
|
+
int o = 0;
|
|
393
|
+
buf[o++] = '0';
|
|
394
|
+
buf[o++] = '.';
|
|
395
|
+
for (int i = 0; i < pad; i++) {
|
|
396
|
+
buf[o++] = '0';
|
|
397
|
+
}
|
|
398
|
+
memcpy(buf + o, tmp, (size_t)len);
|
|
399
|
+
return o + len;
|
|
400
|
+
}
|
|
401
|
+
memcpy(buf, tmp, (size_t)(len - (int)precision));
|
|
402
|
+
buf[len - (int)precision] = '.';
|
|
403
|
+
memcpy(buf + len - (int)precision + 1, tmp + (len - (int)precision), (size_t)precision);
|
|
404
|
+
return len + 1;
|
|
405
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/* floatint.h — internal float-printing declarations (TODO.impl/14).
|
|
2
|
+
*
|
|
3
|
+
* CLEAN-ROOM IMPLEMENTATION: no third-party code is vendored (licensing
|
|
4
|
+
* decision 2026-09-01). What follows implements the published interval
|
|
5
|
+
* method for shortest round-trip decimal output (the Dragon4/Steele-
|
|
6
|
+
* White family, described in the literature) entirely from the math:
|
|
7
|
+
* find the shortest decimal that lies strictly inside the rounding
|
|
8
|
+
* interval (v - w_low, v + w_high) of the binary value.
|
|
9
|
+
*
|
|
10
|
+
* Two tiers, one algorithm:
|
|
11
|
+
* - tier A (print.c): the same digit loop over exact 128-bit
|
|
12
|
+
* integers — covers every value whose scaled representation fits
|
|
13
|
+
* (doubles with E in [-32, 75], floats with E in [-32, 104]);
|
|
14
|
+
* - tier B (dragon.c): the same loop over a fixed-capacity limb
|
|
15
|
+
* vector — exact for everything else (extreme exponents), and the
|
|
16
|
+
* correctness oracle for tier A in tests.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
#ifndef YEP_FLOATINT_H
|
|
20
|
+
#define YEP_FLOATINT_H
|
|
21
|
+
|
|
22
|
+
#include <stdint.h>
|
|
23
|
+
|
|
24
|
+
#include "emit/float/api.h"
|
|
25
|
+
|
|
26
|
+
/* YEP_FLOAT_FORCE_LIMBS: test hook — exercises the portable lo/hi
|
|
27
|
+
* tier on hosts that also have __int128 (the limbs math is otherwise
|
|
28
|
+
* only compiled on 32-bit targets). */
|
|
29
|
+
#if defined(__SIZEOF_INT128__) && !defined(YEP_FLOAT_FORCE_LIMBS) && !defined(YEP_FLOAT_FORCE_LIMBS)
|
|
30
|
+
typedef unsigned __int128 yep_u128;
|
|
31
|
+
#define YEP_MUL64(a, b) ((yep_u128)(uint64_t)(a) * (uint64_t)(b))
|
|
32
|
+
#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
|
|
33
|
+
#include <intrin.h>
|
|
34
|
+
/* MSVC has no __int128: the lo/hi pair behind the SAME helper surface
|
|
35
|
+
* (print.c's interval loop rides only these — no operator arithmetic
|
|
36
|
+
* anywhere, so both branches share one source shape). */
|
|
37
|
+
typedef struct {
|
|
38
|
+
uint64_t lo, hi;
|
|
39
|
+
} yep_u128;
|
|
40
|
+
#define YEP_MUL64(a, b) yep_u128_mul64(a, b)
|
|
41
|
+
#else
|
|
42
|
+
/* Any compiler without __int128 (32-bit GCC/Clang, MSVC x86-32): the
|
|
43
|
+
* same lo/hi pair; multiplication via 32-bit limbs (below). */
|
|
44
|
+
typedef struct {
|
|
45
|
+
uint64_t lo, hi;
|
|
46
|
+
} yep_u128;
|
|
47
|
+
#define YEP_MUL64(a, b) yep_u128_mul64(a, b)
|
|
48
|
+
#endif
|
|
49
|
+
|
|
50
|
+
static inline yep_u128 yep_u128_of(uint64_t v) {
|
|
51
|
+
#if defined(__SIZEOF_INT128__) && !defined(YEP_FLOAT_FORCE_LIMBS)
|
|
52
|
+
return (yep_u128)v;
|
|
53
|
+
#else
|
|
54
|
+
yep_u128 r = {v, 0};
|
|
55
|
+
return r;
|
|
56
|
+
#endif
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static inline yep_u128 yep_u128_max(void) {
|
|
60
|
+
#if defined(__SIZEOF_INT128__) && !defined(YEP_FLOAT_FORCE_LIMBS)
|
|
61
|
+
return ~(yep_u128)0;
|
|
62
|
+
#else
|
|
63
|
+
yep_u128 r = {~(uint64_t)0, ~(uint64_t)0};
|
|
64
|
+
return r;
|
|
65
|
+
#endif
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static inline yep_u128 yep_u128_add(yep_u128 a, yep_u128 b) {
|
|
69
|
+
#if defined(__SIZEOF_INT128__) && !defined(YEP_FLOAT_FORCE_LIMBS)
|
|
70
|
+
return a + b;
|
|
71
|
+
#else
|
|
72
|
+
yep_u128 r;
|
|
73
|
+
r.lo = a.lo + b.lo;
|
|
74
|
+
r.hi = a.hi + b.hi + (r.lo < a.lo ? 1u : 0u);
|
|
75
|
+
return r;
|
|
76
|
+
#endif
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static inline yep_u128 yep_u128_sub(yep_u128 a, yep_u128 b) {
|
|
80
|
+
#if defined(__SIZEOF_INT128__) && !defined(YEP_FLOAT_FORCE_LIMBS)
|
|
81
|
+
return a - b;
|
|
82
|
+
#else
|
|
83
|
+
yep_u128 r;
|
|
84
|
+
r.lo = a.lo - b.lo;
|
|
85
|
+
r.hi = a.hi - b.hi - (a.lo < b.lo ? 1u : 0u);
|
|
86
|
+
return r;
|
|
87
|
+
#endif
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* n < 128 */
|
|
91
|
+
static inline yep_u128 yep_u128_shl(yep_u128 a, unsigned n) {
|
|
92
|
+
#if defined(__SIZEOF_INT128__) && !defined(YEP_FLOAT_FORCE_LIMBS)
|
|
93
|
+
return a << n;
|
|
94
|
+
#else
|
|
95
|
+
yep_u128 r = {0, 0};
|
|
96
|
+
if (n == 0) {
|
|
97
|
+
return a;
|
|
98
|
+
}
|
|
99
|
+
if (n < 64) {
|
|
100
|
+
r.hi = (a.hi << n) | (a.lo >> (64 - n));
|
|
101
|
+
r.lo = a.lo << n;
|
|
102
|
+
} else {
|
|
103
|
+
r.hi = a.lo << (n - 64);
|
|
104
|
+
}
|
|
105
|
+
return r;
|
|
106
|
+
#endif
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* n < 128 */
|
|
110
|
+
static inline yep_u128 yep_u128_shr(yep_u128 a, unsigned n) {
|
|
111
|
+
#if defined(__SIZEOF_INT128__) && !defined(YEP_FLOAT_FORCE_LIMBS)
|
|
112
|
+
return a >> n;
|
|
113
|
+
#else
|
|
114
|
+
yep_u128 r = {0, 0};
|
|
115
|
+
if (n == 0) {
|
|
116
|
+
return a;
|
|
117
|
+
}
|
|
118
|
+
if (n < 64) {
|
|
119
|
+
r.lo = (a.lo >> n) | (a.hi << (64 - n));
|
|
120
|
+
r.hi = a.hi >> n;
|
|
121
|
+
} else {
|
|
122
|
+
r.lo = a.hi >> (n - 64);
|
|
123
|
+
}
|
|
124
|
+
return r;
|
|
125
|
+
#endif
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
static inline int yep_u128_cmp(yep_u128 a, yep_u128 b) {
|
|
129
|
+
#if defined(__SIZEOF_INT128__) && !defined(YEP_FLOAT_FORCE_LIMBS)
|
|
130
|
+
return a < b ? -1 : (a > b ? 1 : 0);
|
|
131
|
+
#else
|
|
132
|
+
if (a.hi != b.hi) {
|
|
133
|
+
return a.hi < b.hi ? -1 : 1;
|
|
134
|
+
}
|
|
135
|
+
if (a.lo != b.lo) {
|
|
136
|
+
return a.lo < b.lo ? -1 : 1;
|
|
137
|
+
}
|
|
138
|
+
return 0;
|
|
139
|
+
#endif
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
#if defined(_MSC_VER) && defined(_M_X64)
|
|
143
|
+
static inline yep_u128 yep_u128_mul64(uint64_t a, uint64_t b) {
|
|
144
|
+
yep_u128 r;
|
|
145
|
+
r.lo = _umul128(a, b, &r.hi);
|
|
146
|
+
return r;
|
|
147
|
+
}
|
|
148
|
+
#elif defined(_MSC_VER) && defined(_M_ARM64)
|
|
149
|
+
static inline yep_u128 yep_u128_mul64(uint64_t a, uint64_t b) {
|
|
150
|
+
yep_u128 r;
|
|
151
|
+
r.hi = __umulh(a, b);
|
|
152
|
+
r.lo = a * b;
|
|
153
|
+
return r;
|
|
154
|
+
}
|
|
155
|
+
#elif !defined(__SIZEOF_INT128__) || defined(YEP_FLOAT_FORCE_LIMBS)
|
|
156
|
+
/* portable: 32-bit limbs, exact (the struct tier only) */
|
|
157
|
+
static inline yep_u128 yep_u128_mul64(uint64_t a, uint64_t b) {
|
|
158
|
+
uint64_t a0 = (uint32_t)a, a1 = a >> 32;
|
|
159
|
+
uint64_t b0 = (uint32_t)b, b1 = b >> 32;
|
|
160
|
+
uint64_t ll = a0 * b0;
|
|
161
|
+
uint64_t lh = a0 * b1;
|
|
162
|
+
uint64_t hl = a1 * b0;
|
|
163
|
+
uint64_t mid = (ll >> 32) + (uint32_t)lh + (uint32_t)hl;
|
|
164
|
+
yep_u128 r;
|
|
165
|
+
r.lo = (mid << 32) | (uint32_t)ll;
|
|
166
|
+
r.hi = (a1 * b1) + (lh >> 32) + (hl >> 32) + (mid >> 32);
|
|
167
|
+
return r;
|
|
168
|
+
}
|
|
169
|
+
#endif
|
|
170
|
+
|
|
171
|
+
/* x * 10 stays in range */
|
|
172
|
+
static inline int yep_u128_fits10(yep_u128 x) {
|
|
173
|
+
#if defined(__SIZEOF_INT128__) && !defined(YEP_FLOAT_FORCE_LIMBS)
|
|
174
|
+
return x <= (~(yep_u128)0) / 10;
|
|
175
|
+
#else
|
|
176
|
+
/* exact: x*10 = (hi*10 << 64) + lo*10 — overflow iff hi*10
|
|
177
|
+
* escapes 64 bits or the lo-carry wraps the sum */
|
|
178
|
+
yep_u128 hp = YEP_MUL64(x.hi, 10u);
|
|
179
|
+
if (hp.hi != 0) {
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
yep_u128 lp = YEP_MUL64(x.lo, 10u);
|
|
183
|
+
return hp.lo + lp.hi >= hp.lo;
|
|
184
|
+
#endif
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* m small (< 2^32); caller guarantees no overflow (fits10 guarded) */
|
|
188
|
+
static inline yep_u128 yep_u128_mul_small(yep_u128 a, uint32_t m) {
|
|
189
|
+
#if defined(__SIZEOF_INT128__) && !defined(YEP_FLOAT_FORCE_LIMBS)
|
|
190
|
+
return a * m;
|
|
191
|
+
#else
|
|
192
|
+
yep_u128 r;
|
|
193
|
+
yep_u128 lp = YEP_MUL64(a.lo, m);
|
|
194
|
+
r.lo = lp.lo;
|
|
195
|
+
r.hi = a.hi * m + lp.hi;
|
|
196
|
+
return r;
|
|
197
|
+
#endif
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* The shortest-roundtrip result both tiers produce. digits[] is the
|
|
201
|
+
* rounded digit sequence (no leading zero, trailing zeros kept only
|
|
202
|
+
* when significant), len its length; k is the decimal exponent so the
|
|
203
|
+
* value is 0.<digits> * 10^k (i.e. in [10^(k-1), 10^k)). */
|
|
204
|
+
typedef struct {
|
|
205
|
+
char digits[24];
|
|
206
|
+
int len;
|
|
207
|
+
int k;
|
|
208
|
+
} yep_dsplit;
|
|
209
|
+
|
|
210
|
+
/* Tier B (dragon.c): exact shortest for any finite double/float bits.
|
|
211
|
+
* m2/e2 is the (unified) significand/exponent: v = m2 * 2^e2 with
|
|
212
|
+
* 2^mb <= m2 < 2^(mb+1) for normals, m2 < 2^mb for subnormals. */
|
|
213
|
+
int yep_dragon_shortest(uint64_t m2, int e2, int mb, int pow2_low, int tie_even, yep_dsplit* out);
|
|
214
|
+
|
|
215
|
+
/* Tier B exact fixed notation: digits of round_half_even(v * 10^p). */
|
|
216
|
+
int yep_dragon_fixed(uint64_t m2, int e2, uint32_t precision, char* buf);
|
|
217
|
+
|
|
218
|
+
/* Tier A (print.c): u128 fast tier; returns 0 when the value is out
|
|
219
|
+
* of the exact-128 range and tier B must be used. */
|
|
220
|
+
int yep_u128_shortest(uint64_t m2, int e2, int mb, int pow2_low, int tie_even, yep_dsplit* out);
|
|
221
|
+
|
|
222
|
+
/* tie_even: whether a decimal landing exactly on a round-trip boundary
|
|
223
|
+
* may be accepted — reparse ties to the even float, which is v only
|
|
224
|
+
* when v's significand is even (callers pass m2 % 2 == 0). */
|
|
225
|
+
|
|
226
|
+
/* Shared rendering of a digit split into the canonical YAML form:
|
|
227
|
+
* plain notation for 10^-4 <= |v| < 10^16, else d.dddde[+-]XX with a
|
|
228
|
+
* leading "1.0e+20"-style fraction so the value re-parses as float. */
|
|
229
|
+
int yep_float_render(const yep_dsplit* ds, int negative, char* buf);
|
|
230
|
+
|
|
231
|
+
#endif /* YEP_FLOATINT_H */
|