@series-inc/rundot-kinetix 0.0.0-bootstrap.0

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.
Files changed (58) hide show
  1. package/README.md +77 -0
  2. package/authoring.d.ts +30 -0
  3. package/index.d.ts +221 -0
  4. package/native/component_runtime.cpp +341 -0
  5. package/native/component_runtime.hpp +112 -0
  6. package/native/deterministic_math.cpp +594 -0
  7. package/native/deterministic_math.hpp +21 -0
  8. package/native/kinetix-f64-native-profile.cpp +406 -0
  9. package/native/kinetix-f64-native-profile.hpp +5 -0
  10. package/native/kinetix-fixed1000-native-profile.cpp +777 -0
  11. package/native/kinetix-fixed1000-native-profile.hpp +58 -0
  12. package/native/kinetix-fixed1000-physics.cpp +887 -0
  13. package/native/kinetix-fixed1000-physics.hpp +28 -0
  14. package/native/kinetix-installed-f64-renderer.cpp +344 -0
  15. package/native/kinetix-installed-f64-renderer.hpp +35 -0
  16. package/native/kinetix-installed-f64-runtime.cpp +1085 -0
  17. package/native/kinetix-installed-f64-runtime.hpp +141 -0
  18. package/native/kinetix-installed-fixed1000-data.hpp +77 -0
  19. package/native/kinetix-native-main.cpp +37 -0
  20. package/native/kinetix-native-runtime.cpp +20 -0
  21. package/native/kinetix-native-runtime.hpp +25 -0
  22. package/native/kinetix-render-projection.cpp +20 -0
  23. package/native/kinetix-render-projection.hpp +14 -0
  24. package/package.json +65 -0
  25. package/runtime.d.ts +76 -0
  26. package/scripts/build-native.mjs +67 -0
  27. package/scripts/emit-product-digests.mjs +33 -0
  28. package/scripts/preflight.mjs +76 -0
  29. package/src/index.mjs +57 -0
  30. package/src/kinetix-authoring.mjs +69 -0
  31. package/src/kinetix-baker.mjs +587 -0
  32. package/src/kinetix-deterministic-math.mjs +1044 -0
  33. package/src/kinetix-fixed1000-runtime-adapter.mjs +33 -0
  34. package/src/kinetix-fixed1000-runtime.mjs +954 -0
  35. package/src/kinetix-installed-f64-reference.mjs +157 -0
  36. package/src/kinetix-installed-f64-render-frames.mjs +53 -0
  37. package/src/kinetix-installed-f64-renderer.mjs +240 -0
  38. package/src/kinetix-installed-f64-runtime-adapter.mjs +68 -0
  39. package/src/kinetix-installed-f64-runtime.mjs +607 -0
  40. package/src/kinetix-installed-mechanics.mjs +377 -0
  41. package/src/kinetix-installed-systems.mjs +181 -0
  42. package/src/kinetix-native-product.mjs +72 -0
  43. package/src/kinetix-product-contract.mjs +121 -0
  44. package/src/kinetix-project-compiler.mjs +1017 -0
  45. package/src/kinetix-render-projection.mjs +28 -0
  46. package/src/kinetix-runtime-adapter-utils.mjs +168 -0
  47. package/src/kinetix-runtime-contract.mjs +54 -0
  48. package/src/kinetix-session-config.mjs +170 -0
  49. package/src/kinetix-source-snapshot.mjs +24 -0
  50. package/src/kinetix-survival-runtime-adapter.mjs +305 -0
  51. package/src/kinetix-survival-runtime.generated.mjs +1 -0
  52. package/src/kinetix-world-kernel.mjs +580 -0
  53. package/src/kinetix-world-runtime.mjs +171 -0
  54. package/src/runtime.mjs +14 -0
  55. package/src/shared/f64-bits.mjs +14 -0
  56. package/src/shared/kinetix-envelope-v1.mjs +589 -0
  57. package/src/shared/render-records-v1.mjs +168 -0
  58. package/src/shared/sha256.mjs +73 -0
@@ -0,0 +1,112 @@
1
+ // Portable C++20 component runtime for the native-compliant R3F proof fork.
2
+ // No browser, JS engine, or platform dependencies: fixed-tick, fixed-point
3
+ // (scale 1e6) int64 simulation over exactly four installed component families.
4
+ // Canonical hash layout must stay byte-identical to
5
+ // component-reference-runtime.mjs.
6
+ #pragma once
7
+
8
+ #include <cstddef>
9
+ #include <cstdint>
10
+ #include <string>
11
+ #include <vector>
12
+
13
+ namespace rundot {
14
+
15
+ enum class ComponentType : std::uint8_t {
16
+ Transform,
17
+ FixedTickMover,
18
+ InputActionState,
19
+ ReplicatedState,
20
+ };
21
+
22
+ struct Vec3i64 {
23
+ std::int64_t x = 0;
24
+ std::int64_t y = 0;
25
+ std::int64_t z = 0;
26
+ };
27
+
28
+ struct TransformState {
29
+ Vec3i64 position;
30
+ Vec3i64 rotation;
31
+ Vec3i64 scale;
32
+ };
33
+
34
+ struct MoverState {
35
+ Vec3i64 velocityPerTick;
36
+ };
37
+
38
+ struct InputState {
39
+ std::string actionId;
40
+ std::string outputField;
41
+ bool pressed = false;
42
+ std::int64_t lastEdgeTick = -1;
43
+ };
44
+
45
+ struct ReplicatedSpec {
46
+ std::string authority;
47
+ std::vector<std::string> fields;
48
+ };
49
+
50
+ struct ComponentRecord {
51
+ ComponentType type;
52
+ std::size_t index;
53
+ };
54
+
55
+ struct EntityState {
56
+ std::string id;
57
+ std::vector<ComponentRecord> components;
58
+ bool hasTransform = false;
59
+ TransformState transform;
60
+ std::vector<MoverState> movers;
61
+ std::vector<InputState> inputs;
62
+ bool hasReplicated = false;
63
+ ReplicatedSpec replicated;
64
+ };
65
+
66
+ struct ReplayAction {
67
+ std::int64_t tick = 0;
68
+ std::string actionId;
69
+ bool pressed = false;
70
+ };
71
+
72
+ struct CorrectionField {
73
+ std::string field;
74
+ bool isVec3 = false;
75
+ Vec3i64 vec;
76
+ bool boolValue = false;
77
+ };
78
+
79
+ struct ReplayCorrection {
80
+ std::int64_t tick = 0;
81
+ std::string entityId;
82
+ std::vector<CorrectionField> fields;
83
+ };
84
+
85
+ struct Replay {
86
+ std::int64_t tickCount = 0;
87
+ std::vector<ReplayAction> actions;
88
+ std::vector<ReplayCorrection> corrections;
89
+ };
90
+
91
+ struct RuntimeFault {
92
+ std::string code;
93
+ std::int64_t tick = -1;
94
+ std::string entityId;
95
+ };
96
+
97
+ struct RunResult {
98
+ std::vector<std::string> tickHashes;
99
+ std::string finalDigest;
100
+ bool faulted = false;
101
+ RuntimeFault fault;
102
+ std::int64_t completedTicks = 0;
103
+ };
104
+
105
+ std::string sha256Hex(const std::uint8_t* data, std::size_t size);
106
+
107
+ // Executes the replay against the entity set (declared pack order). All
108
+ // simulation state lives in the packed EntityState vector; the only
109
+ // allocations after activation are the bounded hash buffers.
110
+ RunResult runReplay(std::vector<EntityState>& entities, const Replay& replay, bool hashEveryTick);
111
+
112
+ } // namespace rundot
@@ -0,0 +1,594 @@
1
+ // Transliteration of the deterministic fdlibm-style JS math shim
2
+ // (kinetix-deterministic-math.mjs, DETERMINISTIC_MATH_SOURCE) into C++.
3
+ // Every floating-point expression is kept in EXACTLY the shape the
4
+ // JS source writes it — same operation order, same intermediates — so that
5
+ // with -ffp-contract=off the results are bit-identical to the JS shim for all
6
+ // finite inputs. JS bitwise semantics (`| 0` → ToInt32, `>>> 0` → ToUint32)
7
+ // are mirrored with explicit std::int32_t / std::uint32_t casts.
8
+
9
+ #include "deterministic_math.hpp"
10
+
11
+ #include <array>
12
+ #include <bit>
13
+ #include <cmath>
14
+ #include <cstdint>
15
+
16
+ namespace rundot::detmath {
17
+
18
+ namespace {
19
+
20
+ // ---- word access helpers (JS: Float64Array/Uint32Array views) --------------
21
+ inline std::int32_t HI(double x) {
22
+ return static_cast<std::int32_t>(
23
+ static_cast<std::uint32_t>(std::bit_cast<std::uint64_t>(x) >> 32));
24
+ }
25
+ inline std::int32_t LO(double x) {
26
+ return static_cast<std::int32_t>(
27
+ static_cast<std::uint32_t>(std::bit_cast<std::uint64_t>(x)));
28
+ }
29
+ inline double fromWords(std::uint32_t hi, std::uint32_t lo) {
30
+ return std::bit_cast<double>((static_cast<std::uint64_t>(hi) << 32) |
31
+ static_cast<std::uint64_t>(lo));
32
+ }
33
+ inline double setHi(double x, std::uint32_t hi) {
34
+ const std::uint64_t bits = std::bit_cast<std::uint64_t>(x);
35
+ return std::bit_cast<double>((static_cast<std::uint64_t>(hi) << 32) |
36
+ (bits & 0xffffffffull));
37
+ }
38
+ inline double setLo(double x, std::uint32_t lo) {
39
+ const std::uint64_t bits = std::bit_cast<std::uint64_t>(x);
40
+ return std::bit_cast<double>((bits & 0xffffffff00000000ull) |
41
+ static_cast<std::uint64_t>(lo));
42
+ }
43
+
44
+ // ECMAScript ToInt32 (JS `value | 0` on a double).
45
+ inline std::int32_t toInt32(double v) {
46
+ if (std::isnan(v) || std::isinf(v)) return 0;
47
+ double d = std::trunc(v);
48
+ d = std::fmod(d, 4294967296.0);
49
+ if (d < 0.0) d += 4294967296.0;
50
+ return static_cast<std::int32_t>(static_cast<std::uint32_t>(d));
51
+ }
52
+
53
+ // ---- scalbn2 ----------------------------------------------------------------
54
+ double scalbn2(double x, int n) {
55
+ std::int32_t hx = HI(x), lx = LO(x);
56
+ std::int32_t k = (hx & 0x7ff00000) >> 20;
57
+ if (k == 0) {
58
+ if ((lx | (hx & 0x7fffffff)) == 0) return x;
59
+ x *= 18014398509481984.0;
60
+ hx = HI(x);
61
+ k = ((hx & 0x7ff00000) >> 20) - 54;
62
+ if (n < -50000) return 1e-300 * x;
63
+ }
64
+ if (k == 0x7ff) return x + x;
65
+ k = k + n;
66
+ if (k > 0x7fe) return 1e300 * (x > 0 ? 1e300 : -1e300);
67
+ if (k > 0) return setHi(x, static_cast<std::uint32_t>((hx & 0x800fffff) | (k << 20)));
68
+ if (k <= -54) {
69
+ if (n > 50000) return 1e300 * (x > 0 ? 1e300 : -1e300);
70
+ return 1e-300 * (x > 0 ? 1e-300 : -1e-300);
71
+ }
72
+ k += 54;
73
+ x = setHi(x, static_cast<std::uint32_t>((hx & 0x800fffff) | (k << 20)));
74
+ return x * 5.55112312578270211816e-17; // 2^-54
75
+ }
76
+
77
+ // ---- __kernel_sin / __kernel_cos (fdlibm) -----------------------------------
78
+ constexpr double S1 = -1.66666666666666324348e-01, S2 = 8.33333333332248946124e-03,
79
+ S3 = -1.98412698298579493134e-04, S4 = 2.75573137070700676789e-06,
80
+ S5 = -2.50507602534068634195e-08, S6 = 1.58969099521155010221e-10;
81
+ double kernelSin(double x, double y, int iy) {
82
+ const double z = x * x;
83
+ const double v = z * x;
84
+ const double r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6)));
85
+ if (iy == 0) return x + v * (S1 + z * r);
86
+ return x - ((z * (0.5 * y - v * r) - y) - v * S1);
87
+ }
88
+ constexpr double C1 = 4.16666666666666019037e-02, C2 = -1.38888888888741095749e-03,
89
+ C3 = 2.48015872894767294178e-05, C4 = -2.75573143513906633035e-07,
90
+ C5 = 2.08757232129817482790e-09, C6 = -1.13596475577881948265e-11;
91
+ double kernelCos(double x, double y) {
92
+ const double z = x * x;
93
+ const double r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6)))));
94
+ const double hz = 0.5 * z;
95
+ const double w = 1.0 - hz;
96
+ return w + (((1.0 - w) - hz) + (z * r - x * y));
97
+ }
98
+
99
+ // ---- __rem_pio2 (fdlibm, incl. Payne-Hanek for large args) -------------------
100
+ constexpr std::int32_t twoOverPi[] = {
101
+ 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041,
102
+ 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C,
103
+ 0xFE1DEB, 0x1CB129, 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
104
+ 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F,
105
+ 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D,
106
+ 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
107
+ 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 0x91615E, 0xE61B08,
108
+ 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9,
109
+ 0x60E27B, 0xC08C6B,
110
+ };
111
+ constexpr double PIo2[] = {
112
+ 1.57079625129699707031e+00, 7.54978941586159635335e-08, 5.39030252995776476554e-15,
113
+ 3.28200341580791294123e-22, 1.27065575308067607349e-29, 1.22933308981111328932e-36,
114
+ 2.73370053816464559624e-44, 2.16741683877804819444e-51,
115
+ };
116
+ constexpr double two24 = 1.67772160000000000000e+07, twon24 = 5.96046447753906250000e-08;
117
+ int kernelRemPio2(const double* x, double* y, int e0, int nx) {
118
+ // prec = 2 (double), jk = 4
119
+ const int jk = 4, jp = 4;
120
+ const int jx = nx - 1;
121
+ int jv = (e0 - 3) / 24; // JS: ((e0 - 3) / 24) | 0 — truncation toward zero
122
+ if (jv < 0) jv = 0;
123
+ int q0 = e0 - 24 * (jv + 1);
124
+ double f[20] = {0};
125
+ double q[20] = {0};
126
+ std::int32_t iq[20] = {0};
127
+ double fw0[20] = {0};
128
+ int i, j, k, n = 0, ih, carry;
129
+ double z, fw;
130
+ for (i = 0, j = jv - jx; i <= jx + jk; i++, j++) f[i] = j < 0 ? 0 : static_cast<double>(twoOverPi[j]);
131
+ for (i = 0; i <= jk; i++) {
132
+ fw = 0;
133
+ for (j = 0; j <= jx; j++) fw += x[j] * f[jx + i - j];
134
+ q[i] = fw;
135
+ }
136
+ int jz = jk;
137
+ bool recomputeNeeded = true;
138
+ while (recomputeNeeded) {
139
+ recomputeNeeded = false;
140
+ // distill q[] into iq[] reversingly
141
+ for (i = 0, j = jz, z = q[jz]; j > 0; i++, j--) {
142
+ fw = std::floor(twon24 * z);
143
+ iq[i] = toInt32(z - two24 * fw);
144
+ z = q[j - 1] + fw;
145
+ }
146
+ z = scalbn2(z, q0);
147
+ z -= 8.0 * std::floor(z * 0.125);
148
+ n = toInt32(z);
149
+ z -= n;
150
+ ih = 0;
151
+ if (q0 > 0) {
152
+ i = (iq[jz - 1] >> (24 - q0));
153
+ n += i;
154
+ iq[jz - 1] -= i << (24 - q0);
155
+ ih = iq[jz - 1] >> (23 - q0);
156
+ } else if (q0 == 0) ih = iq[jz - 1] >> 23;
157
+ else if (z >= 0.5) ih = 2;
158
+ if (ih > 0) {
159
+ n += 1;
160
+ carry = 0;
161
+ for (i = 0; i < jz; i++) {
162
+ j = iq[i];
163
+ if (carry == 0) {
164
+ if (j != 0) { carry = 1; iq[i] = 0x1000000 - j; }
165
+ } else iq[i] = 0xffffff - j;
166
+ }
167
+ if (q0 > 0) {
168
+ switch (q0) {
169
+ case 1: iq[jz - 1] &= 0x7fffff; break;
170
+ case 2: iq[jz - 1] &= 0x3fffff; break;
171
+ }
172
+ }
173
+ if (ih == 2) {
174
+ z = 1.0 - z;
175
+ if (carry != 0) z -= scalbn2(1.0, q0);
176
+ }
177
+ }
178
+ if (z == 0) {
179
+ j = 0;
180
+ for (i = jz - 1; i >= jk; i--) j |= iq[i];
181
+ if (j == 0) {
182
+ for (k = 1; iq[jk - k] == 0; k++) { }
183
+ for (i = jz + 1; i <= jz + k; i++) {
184
+ f[jx + i] = static_cast<double>(twoOverPi[jv + i]);
185
+ for (j = 0, fw = 0; j <= jx; j++) fw += x[j] * f[jx + i - j];
186
+ q[i] = fw;
187
+ }
188
+ jz += k;
189
+ recomputeNeeded = true;
190
+ continue;
191
+ }
192
+ }
193
+ if (z == 0) {
194
+ jz -= 1;
195
+ q0 -= 24;
196
+ while (iq[jz] == 0) { jz--; q0 -= 24; }
197
+ } else {
198
+ z = scalbn2(z, -q0);
199
+ if (z >= two24) {
200
+ fw = std::floor(twon24 * z);
201
+ iq[jz] = toInt32(z - two24 * fw);
202
+ jz += 1;
203
+ q0 += 24;
204
+ iq[jz] = toInt32(fw);
205
+ } else iq[jz] = toInt32(z);
206
+ }
207
+ fw = scalbn2(1.0, q0);
208
+ for (i = jz; i >= 0; i--) { q[i] = fw * iq[i]; fw *= twon24; }
209
+ for (i = jz; i >= 0; i--) {
210
+ for (fw = 0, k = 0; k <= jp && k <= jz - i; k++) fw += PIo2[k] * q[i + k];
211
+ fw0[jz - i] = fw;
212
+ }
213
+ // compress fw0 into y[] (prec 2)
214
+ fw = 0;
215
+ for (i = jz; i >= 0; i--) fw += fw0[i];
216
+ y[0] = ih == 0 ? fw : -fw;
217
+ fw = fw0[0] - fw;
218
+ for (i = 1; i <= jz; i++) fw += fw0[i];
219
+ y[1] = ih == 0 ? fw : -fw;
220
+ }
221
+ return n & 7;
222
+ }
223
+
224
+ constexpr double invpio2 = 6.36619772367581382433e-01;
225
+ constexpr double pio2_1 = 1.57079632673412561417e+00, pio2_1t = 6.07710050650619224932e-11;
226
+ constexpr double pio2_2 = 6.07710050630396597660e-11, pio2_2t = 2.02226624879595063154e-21;
227
+ constexpr double pio2_3 = 2.02226624871116645580e-21, pio2_3t = 8.47842766036889956997e-32;
228
+ constexpr std::int32_t npio2_hw[] = {
229
+ 0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
230
+ 0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
231
+ 0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
232
+ 0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
233
+ 0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
234
+ 0x404858EB, 0x404921FB,
235
+ };
236
+ int remPio2(double x, double* y) {
237
+ const std::int32_t hx = HI(x);
238
+ const std::int32_t ix = hx & 0x7fffffff;
239
+ if (ix <= 0x3fe921fb) { y[0] = x; y[1] = 0; return 0; }
240
+ if (ix < 0x4002d97c) { // |x| < 3pi/4
241
+ if (hx > 0) {
242
+ double z = x - pio2_1;
243
+ if (ix != 0x3ff921fb) { y[0] = z - pio2_1t; y[1] = (z - y[0]) - pio2_1t; }
244
+ else { z -= pio2_2; y[0] = z - pio2_2t; y[1] = (z - y[0]) - pio2_2t; }
245
+ return 1;
246
+ }
247
+ double z = x + pio2_1;
248
+ if (ix != 0x3ff921fb) { y[0] = z + pio2_1t; y[1] = (z - y[0]) + pio2_1t; }
249
+ else { z += pio2_2; y[0] = z + pio2_2t; y[1] = (z - y[0]) + pio2_2t; }
250
+ return -1;
251
+ }
252
+ if (ix <= 0x413921fb) { // |x| <= 2^19 pi/2
253
+ const double t = std::fabs(x);
254
+ const int n = toInt32(t * invpio2 + 0.5);
255
+ const double fn = n;
256
+ double r = t - fn * pio2_1;
257
+ double w = fn * pio2_1t;
258
+ if (n < 32 && ix != npio2_hw[n - 1]) {
259
+ y[0] = r - w;
260
+ } else {
261
+ const std::int32_t j = ix >> 20;
262
+ y[0] = r - w;
263
+ std::int32_t i = j - ((HI(y[0]) >> 20) & 0x7ff);
264
+ if (i > 16) {
265
+ const double t2 = r;
266
+ w = fn * pio2_2;
267
+ r = t2 - w;
268
+ w = fn * pio2_2t - ((t2 - r) - w);
269
+ y[0] = r - w;
270
+ i = j - ((HI(y[0]) >> 20) & 0x7ff);
271
+ if (i > 49) {
272
+ const double t3 = r;
273
+ w = fn * pio2_3;
274
+ r = t3 - w;
275
+ w = fn * pio2_3t - ((t3 - r) - w);
276
+ y[0] = r - w;
277
+ }
278
+ }
279
+ }
280
+ y[1] = (r - y[0]) - w;
281
+ if (hx < 0) { y[0] = -y[0]; y[1] = -y[1]; return -n; }
282
+ return n;
283
+ }
284
+ if (ix >= 0x7ff00000) { y[0] = y[1] = x - x; return 0; }
285
+ // Payne-Hanek
286
+ const std::int32_t lx = LO(x);
287
+ const int e0 = (ix >> 20) - 1046;
288
+ double z = setHi(0, static_cast<std::uint32_t>(ix - (e0 << 20)));
289
+ z = setLo(z, static_cast<std::uint32_t>(lx));
290
+ double tx[3] = {0, 0, 0};
291
+ for (int i = 0; i < 2; i++) { tx[i] = toInt32(z); z = (z - tx[i]) * two24; }
292
+ tx[2] = z;
293
+ int nx = 3;
294
+ while (nx > 0 && tx[nx - 1] == 0) nx--;
295
+ const int n = kernelRemPio2(tx, y, e0, nx);
296
+ if (hx < 0) { y[0] = -y[0]; y[1] = -y[1]; return -n; }
297
+ return n;
298
+ }
299
+
300
+ // ---- log (fdlibm e_log) ------------------------------------------------------
301
+ constexpr double ln2_hi = 6.93147180369123816490e-01, ln2_lo = 1.90821492927058770002e-10;
302
+ constexpr double Lg1 = 6.666666666666735130e-01, Lg2 = 3.999999999940941908e-01,
303
+ Lg3 = 2.857142874366239149e-01, Lg4 = 2.222219843214978396e-01,
304
+ Lg5 = 1.818357216161805012e-01, Lg6 = 1.531383769920937332e-01,
305
+ Lg7 = 1.479819860511658591e-01;
306
+ constexpr double two54 = 1.80143985094819840000e+16;
307
+
308
+ // ---- exp (fdlibm e_exp) --------------------------------------------------------
309
+ constexpr double halF[] = {0.5, -0.5};
310
+ constexpr double o_threshold = 7.09782712893383973096e+02;
311
+ constexpr double u_threshold = -7.45133219101941108420e+02;
312
+ constexpr double invln2 = 1.44269504088896338700e+00;
313
+ constexpr double ln2HI[] = {6.93147180369123816490e-01, -6.93147180369123816490e-01};
314
+ constexpr double ln2LO[] = {1.90821492927058770002e-10, -1.90821492927058770002e-10};
315
+ constexpr double P1 = 1.66666666666666019037e-01, P2 = -2.77777777770155933842e-03,
316
+ P3 = 6.61375632143793436117e-05, P4 = -1.65339022054652515390e-06,
317
+ P5 = 4.13813679705723846039e-08;
318
+ constexpr double twom1000 = 9.33263618503218878990e-302;
319
+
320
+ // ---- atan / atan2 (fdlibm s_atan / e_atan2) -----------------------------------
321
+ constexpr double atanhi[] = {
322
+ 4.63647609000806093515e-01, 7.85398163397448278999e-01,
323
+ 9.82793723247329054082e-01, 1.57079632679489655800e+00,
324
+ };
325
+ constexpr double atanlo[] = {
326
+ 2.26987774529616870924e-17, 3.06161699786838301793e-17,
327
+ 1.39033110312309984516e-17, 6.12323399573676603587e-17,
328
+ };
329
+ constexpr double aT[] = {
330
+ 3.33333333333329318027e-01, -1.99999999998764832476e-01, 1.42857142725034663711e-01,
331
+ -1.11111104054623557880e-01, 9.09088713343650656196e-02, -7.69187620504482999495e-02,
332
+ 6.66107313738753120669e-02, -5.83357013379057348645e-02, 4.97687799461593236017e-02,
333
+ -3.65315727442169155270e-02, 1.62858201153657823623e-02,
334
+ };
335
+ constexpr double tiny_atan2 = 1.0e-300;
336
+ constexpr double pi_o_4 = 7.8539816339744827900e-01, pi_o_2 = 1.5707963267948965580e+00;
337
+ constexpr double detPi = 3.1415926535897931160e+00, pi_lo = 1.2246467991473531772e-16;
338
+
339
+ // JS: (lx | -lx) >>> 31 — computed unsigned to avoid the INT32_MIN negation UB.
340
+ inline std::int32_t nonZeroBit(std::int32_t lx) {
341
+ const std::uint32_t ulx = static_cast<std::uint32_t>(lx);
342
+ return static_cast<std::int32_t>((ulx | (0u - ulx)) >> 31);
343
+ }
344
+
345
+ } // namespace
346
+
347
+ double det_sin(double x) {
348
+ const std::int32_t ix = HI(x) & 0x7fffffff;
349
+ if (ix <= 0x3fe921fb) {
350
+ if (ix < 0x3e400000) { if (toInt32(x) == 0 && x == x) return x; }
351
+ return kernelSin(x, 0, 0);
352
+ }
353
+ if (ix >= 0x7ff00000) return x - x;
354
+ double y[2] = {0, 0};
355
+ const int n = remPio2(x, y);
356
+ switch (n & 3) {
357
+ case 0: return kernelSin(y[0], y[1], 1);
358
+ case 1: return kernelCos(y[0], y[1]);
359
+ case 2: return -kernelSin(y[0], y[1], 1);
360
+ default: return -kernelCos(y[0], y[1]);
361
+ }
362
+ }
363
+
364
+ double det_cos(double x) {
365
+ const std::int32_t ix = HI(x) & 0x7fffffff;
366
+ if (ix <= 0x3fe921fb) {
367
+ if (ix < 0x3e400000) return 1.0;
368
+ return kernelCos(x, 0);
369
+ }
370
+ if (ix >= 0x7ff00000) return x - x;
371
+ double y[2] = {0, 0};
372
+ const int n = remPio2(x, y);
373
+ switch (n & 3) {
374
+ case 0: return kernelCos(y[0], y[1]);
375
+ case 1: return -kernelSin(y[0], y[1], 1);
376
+ case 2: return -kernelCos(y[0], y[1]);
377
+ default: return kernelSin(y[0], y[1], 1);
378
+ }
379
+ }
380
+
381
+ double det_log(double x) {
382
+ std::int32_t hx = HI(x);
383
+ const std::int32_t lx = LO(x);
384
+ std::int32_t k = 0;
385
+ if (hx < 0x00100000) {
386
+ if (((hx & 0x7fffffff) | lx) == 0) return -HUGE_VAL;
387
+ if (hx < 0) return (x - x) / 0.0;
388
+ k -= 54;
389
+ x *= two54;
390
+ hx = HI(x);
391
+ }
392
+ if (hx >= 0x7ff00000) return x + x;
393
+ k += (hx >> 20) - 1023;
394
+ hx &= 0x000fffff;
395
+ const std::int32_t i = (hx + 0x95f64) & 0x100000;
396
+ x = setHi(x, static_cast<std::uint32_t>(hx | (i ^ 0x3ff00000)));
397
+ k += i >> 20;
398
+ const double f = x - 1.0;
399
+ if ((0x000fffff & (2 + hx)) < 3) {
400
+ if (f == 0) { if (k == 0) return 0; return k * ln2_hi + k * ln2_lo; }
401
+ const double R = f * f * (0.5 - 0.33333333333333333 * f);
402
+ if (k == 0) return f - R;
403
+ return k * ln2_hi - ((R - k * ln2_lo) - f);
404
+ }
405
+ const double s = f / (2.0 + f);
406
+ const double dk = k;
407
+ const double z = s * s;
408
+ const std::int32_t ii = hx - 0x6147a;
409
+ const double w = z * z;
410
+ const std::int32_t jj = 0x6b851 - hx;
411
+ const double t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
412
+ const double t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
413
+ const std::int32_t ij = ii | jj;
414
+ const double R = t2 + t1;
415
+ if (ij > 0) {
416
+ const double hfsq = 0.5 * f * f;
417
+ if (k == 0) return f - (hfsq - s * (hfsq + R));
418
+ return dk * ln2_hi - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f);
419
+ }
420
+ if (k == 0) return f - s * (f - R);
421
+ return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f);
422
+ }
423
+
424
+ double det_exp(double x) {
425
+ std::int32_t hx = HI(x);
426
+ const std::int32_t xsb = (hx >> 31) & 1;
427
+ hx &= 0x7fffffff;
428
+ if (hx >= 0x40862E42) {
429
+ if (hx >= 0x7ff00000) {
430
+ if (((hx & 0xfffff) | LO(x)) != 0) return x + x;
431
+ return xsb == 0 ? x : 0.0;
432
+ }
433
+ if (x > o_threshold) return HUGE_VAL;
434
+ if (x < u_threshold) return 0;
435
+ }
436
+ std::int32_t k = 0;
437
+ double hi = 0, lo = 0, t;
438
+ if (hx > 0x3fd62e42) {
439
+ if (hx < 0x3FF0A2B2) { hi = x - ln2HI[xsb]; lo = ln2LO[xsb]; k = 1 - xsb - xsb; }
440
+ else {
441
+ k = toInt32(invln2 * x + halF[xsb]);
442
+ t = k;
443
+ hi = x - t * ln2HI[0];
444
+ lo = t * ln2LO[0];
445
+ }
446
+ x = hi - lo;
447
+ } else if (hx < 0x3e300000) {
448
+ return 1.0 + x;
449
+ }
450
+ t = x * x;
451
+ const double c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
452
+ if (k == 0) return 1.0 - ((x * c) / (c - 2.0) - x);
453
+ double y = 1.0 - ((lo - (x * c) / (2.0 - c)) - hi);
454
+ if (k >= -1021) return setHi(y, static_cast<std::uint32_t>(HI(y) + (k << 20)));
455
+ y = setHi(y, static_cast<std::uint32_t>(HI(y) + ((k + 1000) << 20)));
456
+ return y * twom1000;
457
+ }
458
+
459
+ double det_atan(double x) {
460
+ const std::int32_t hx = HI(x);
461
+ const std::int32_t ix = hx & 0x7fffffff;
462
+ if (ix >= 0x44100000) {
463
+ if (ix > 0x7ff00000 || (ix == 0x7ff00000 && LO(x) != 0)) return x + x;
464
+ return hx > 0 ? atanhi[3] + atanlo[3] : -atanhi[3] - atanlo[3];
465
+ }
466
+ std::int32_t id;
467
+ if (ix < 0x3fdc0000) {
468
+ if (ix < 0x3e200000) return x;
469
+ id = -1;
470
+ } else {
471
+ x = std::fabs(x);
472
+ if (ix < 0x3ff30000) {
473
+ if (ix < 0x3fe60000) { id = 0; x = (2.0 * x - 1.0) / (2.0 + x); }
474
+ else { id = 1; x = (x - 1.0) / (x + 1.0); }
475
+ } else {
476
+ if (ix < 0x40038000) { id = 2; x = (x - 1.5) / (1.0 + 1.5 * x); }
477
+ else { id = 3; x = -1.0 / x; }
478
+ }
479
+ }
480
+ const double z = x * x;
481
+ const double w = z * z;
482
+ const double s1 = z * (aT[0] + w * (aT[2] + w * (aT[4] + w * (aT[6] + w * (aT[8] + w * aT[10])))));
483
+ const double s2 = w * (aT[1] + w * (aT[3] + w * (aT[5] + w * (aT[7] + w * aT[9]))));
484
+ if (id < 0) return x - x * (s1 + s2);
485
+ const double zz = atanhi[id] - ((x * (s1 + s2) - atanlo[id]) - x);
486
+ return hx < 0 ? -zz : zz;
487
+ }
488
+
489
+ double det_atan2(double y, double x) {
490
+ const std::int32_t hx = HI(x), lx = LO(x), hy = HI(y), ly = LO(y);
491
+ const std::int32_t ix = hx & 0x7fffffff, iy = hy & 0x7fffffff;
492
+ if ((ix | nonZeroBit(lx)) > 0x7ff00000 || (iy | nonZeroBit(ly)) > 0x7ff00000) return x + y;
493
+ if (hx == 0x3ff00000 && lx == 0) return det_atan(y);
494
+ const std::int32_t m = ((hy >> 31) & 1) | ((hx >> 30) & 2);
495
+ if ((iy | ly) == 0) {
496
+ switch (m) {
497
+ case 0: case 1: return y;
498
+ case 2: return detPi + tiny_atan2;
499
+ default: return -detPi - tiny_atan2;
500
+ }
501
+ }
502
+ if ((ix | lx) == 0) return hy < 0 ? -pi_o_2 - tiny_atan2 : pi_o_2 + tiny_atan2;
503
+ if (ix == 0x7ff00000) {
504
+ if (iy == 0x7ff00000) {
505
+ switch (m) {
506
+ case 0: return pi_o_4 + tiny_atan2;
507
+ case 1: return -pi_o_4 - tiny_atan2;
508
+ case 2: return 3.0 * pi_o_4 + tiny_atan2;
509
+ default: return -3.0 * pi_o_4 - tiny_atan2;
510
+ }
511
+ } else {
512
+ switch (m) {
513
+ case 0: return 0.0;
514
+ case 1: return -0.0;
515
+ case 2: return detPi + tiny_atan2;
516
+ default: return -detPi - tiny_atan2;
517
+ }
518
+ }
519
+ }
520
+ if (iy == 0x7ff00000) return hy < 0 ? -pi_o_2 - tiny_atan2 : pi_o_2 + tiny_atan2;
521
+ const std::int32_t k = (iy - ix) >> 20;
522
+ double z;
523
+ if (k > 60) z = pi_o_2 + 0.5 * pi_lo;
524
+ else if (hx < 0 && k < -60) z = 0.0;
525
+ else z = det_atan(std::fabs(y / x));
526
+ switch (m) {
527
+ case 0: return z;
528
+ case 1: return -z;
529
+ case 2: return detPi - (z - pi_lo);
530
+ default: return (z - pi_lo) - detPi;
531
+ }
532
+ }
533
+
534
+ double det_hypot2(double x, double y) {
535
+ std::int32_t ha = HI(x) & 0x7fffffff;
536
+ std::int32_t hb = HI(y) & 0x7fffffff;
537
+ double a, b;
538
+ if (hb > ha) { a = y; b = x; const std::int32_t j = ha; ha = hb; hb = j; }
539
+ else { a = x; b = y; }
540
+ a = std::fabs(a);
541
+ b = std::fabs(b);
542
+ if (ha - hb > 0x3c00000) return a + b;
543
+ std::int32_t k = 0;
544
+ if (ha > 0x5f300000) {
545
+ if (ha >= 0x7ff00000) {
546
+ double w = std::fabs(x + 0.0) - std::fabs(y + 0.0);
547
+ if (((ha & 0xfffff) | LO(a)) == 0) w = a;
548
+ if (((hb ^ 0x7ff00000) | LO(b)) == 0) w = b;
549
+ return w;
550
+ }
551
+ ha -= 0x25800000;
552
+ hb -= 0x25800000;
553
+ k += 600;
554
+ a = setHi(a, static_cast<std::uint32_t>(ha));
555
+ b = setHi(b, static_cast<std::uint32_t>(hb));
556
+ }
557
+ if (hb < 0x20b00000) {
558
+ if (hb <= 0x000fffff) {
559
+ if ((hb | LO(b)) == 0) return a;
560
+ const double scale = fromWords(0x7fd00000u, 0u);
561
+ b *= scale;
562
+ a *= scale;
563
+ k -= 1022;
564
+ ha = HI(a);
565
+ hb = HI(b);
566
+ } else {
567
+ ha += 0x25800000;
568
+ hb += 0x25800000;
569
+ k -= 600;
570
+ a = setHi(a, static_cast<std::uint32_t>(ha));
571
+ b = setHi(b, static_cast<std::uint32_t>(hb));
572
+ }
573
+ }
574
+ double w = a - b;
575
+ if (w > b) {
576
+ const double t1 = fromWords(static_cast<std::uint32_t>(ha), 0u);
577
+ const double t2 = a - t1;
578
+ w = std::sqrt(t1 * t1 - (b * (-b) - t2 * (a + t1)));
579
+ } else {
580
+ a = a + a;
581
+ const double y1 = fromWords(static_cast<std::uint32_t>(hb), 0u);
582
+ const double y2 = b - y1;
583
+ const double t1 = fromWords(static_cast<std::uint32_t>(ha + 0x00100000), 0u);
584
+ const double t2 = a - t1;
585
+ w = std::sqrt(t1 * y1 - (w * (-w) - (t1 * y2 + t2 * b)));
586
+ }
587
+ if (k != 0) {
588
+ const double scale = setHi(1.0, static_cast<std::uint32_t>(HI(1.0) + (k << 20)));
589
+ return scale * w;
590
+ }
591
+ return w;
592
+ }
593
+
594
+ } // namespace rundot::detmath