redscript-mc 2.2.1 → 2.3.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.
- package/CHANGELOG.md +20 -0
- package/README.md +18 -2
- package/dist/src/__tests__/tuner/engine.test.d.ts +4 -0
- package/dist/src/__tests__/tuner/engine.test.js +232 -0
- package/dist/src/tuner/adapters/ln-polynomial.d.ts +23 -0
- package/dist/src/tuner/adapters/ln-polynomial.js +142 -0
- package/dist/src/tuner/adapters/sqrt-newton.d.ts +28 -0
- package/dist/src/tuner/adapters/sqrt-newton.js +125 -0
- package/dist/src/tuner/cli.d.ts +5 -0
- package/dist/src/tuner/cli.js +168 -0
- package/dist/src/tuner/engine.d.ts +17 -0
- package/dist/src/tuner/engine.js +215 -0
- package/dist/src/tuner/metrics.d.ts +15 -0
- package/dist/src/tuner/metrics.js +51 -0
- package/dist/src/tuner/simulator.d.ts +35 -0
- package/dist/src/tuner/simulator.js +78 -0
- package/dist/src/tuner/types.d.ts +32 -0
- package/dist/src/tuner/types.js +6 -0
- package/docs/STDLIB_ROADMAP.md +142 -0
- package/editors/vscode/package-lock.json +3 -3
- package/editors/vscode/package.json +1 -1
- package/package.json +1 -1
- package/src/__tests__/tuner/engine.test.ts +260 -0
- package/src/stdlib/bigint.mcrs +155 -192
- package/src/stdlib/bits.mcrs +158 -0
- package/src/stdlib/color.mcrs +160 -0
- package/src/stdlib/geometry.mcrs +124 -0
- package/src/stdlib/list.mcrs +125 -0
- package/src/stdlib/math.mcrs +90 -0
- package/src/stdlib/math_hp.mcrs +65 -0
- package/src/stdlib/random.mcrs +67 -0
- package/src/stdlib/signal.mcrs +112 -0
- package/src/stdlib/vec.mcrs +27 -0
- package/src/tuner/adapters/ln-polynomial.ts +147 -0
- package/src/tuner/adapters/sqrt-newton.ts +135 -0
- package/src/tuner/cli.ts +158 -0
- package/src/tuner/engine.ts +272 -0
- package/src/tuner/metrics.ts +66 -0
- package/src/tuner/simulator.ts +69 -0
- package/src/tuner/types.ts +44 -0
- package/docs/ARCHITECTURE.zh.md +0 -1088
- package/docs/COMPILATION_STATS.md +0 -142
- package/docs/IMPLEMENTATION_GUIDE.md +0 -512
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# RedScript Standard Library Roadmap
|
|
2
|
+
|
|
3
|
+
> 目标:覆盖卡儿数学库(large_number)的所有核心功能,但以 RedScript 语言提供干净的 API。
|
|
4
|
+
> 参考分析:`docs/LARGE_NUMBER_ANALYSIS.md`(本地,不追踪到 git)
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 当前 stdlib 状态(2026-03-17)
|
|
9
|
+
|
|
10
|
+
| 文件 | 内容 | 状态 |
|
|
11
|
+
|------|------|------|
|
|
12
|
+
| `math.mcrs` | abs/sign/clamp/lerp/ln/sqrt_fx/exp_fx/sin_fixed/cos_fixed/isqrt/gcd/lcm... | ✅ |
|
|
13
|
+
| `math_hp.mcrs` | sin_hp/cos_hp(实体旋转,高精度),init_trig | ✅框架/⚠️return值待修 |
|
|
14
|
+
| `random.mcrs` | LCG: next_lcg/random_range/random_bool; PCG: pcg_next/pcg_output | ✅ |
|
|
15
|
+
| `vec.mcrs` | 2D/3D dot/cross/length/distance/normalize/lerp/atan2/rotate/add/sub/scale | ✅ |
|
|
16
|
+
| `color.mcrs` | rgb_pack/unpack, rgb_lerp, hsl_to_r/g/b, rgb_to_h/s/l | ✅ |
|
|
17
|
+
| `bits.mcrs` | bit_and/or/xor/not, bit_shl/shr, bit_get/set/clear/toggle, popcount | ✅ |
|
|
18
|
+
| `list.mcrs` | sort3, min/max/avg (3/5), weighted utilities | ✅ |
|
|
19
|
+
| `geometry.mcrs` | AABB/sphere/cylinder contains, parabola, angle helpers, MC sun angle | ✅ |
|
|
20
|
+
| `signal.mcrs` | uniform, normal_approx12, exp_dist, bernoulli, weighted2/3 | ✅ |
|
|
21
|
+
| `bigint.mcrs` | 96-bit base-10000: add/sub/mul/div/cmp, int32↔bigint3 conversion | ✅ |
|
|
22
|
+
| `combat.mcrs` | damage/kill-check | ✅(原有) |
|
|
23
|
+
| `player.mcrs` | health/alive/range | ✅(原有) |
|
|
24
|
+
| `cooldown.mcrs` | per-player cooldown tracking | ✅(原有) |
|
|
25
|
+
| `timer.mcrs` | Timer static allocation | ✅(原有) |
|
|
26
|
+
| `strings.mcrs` | string utilities | ✅(原有) |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Batch 1 — 纯整数,无需新语言特性(当前可做)
|
|
31
|
+
|
|
32
|
+
### `stdlib/math.mcrs` 补充
|
|
33
|
+
- [x] `abs`, `sign`, `clamp`, `lerp`, `pow2`
|
|
34
|
+
- [x] `ln(x: int): int` — SA-tuned atanh 级数,max_error 0.000557
|
|
35
|
+
- [x] `sqrt_fx(x: int): int` — 基于 isqrt,固定点 ×10000
|
|
36
|
+
- [x] `exp_fx(x: int): int` — Horner-form Taylor + 2^k 缩放,固定点 ×10000
|
|
37
|
+
|
|
38
|
+
### `stdlib/math_hp.mcrs`(新建,框架就绪)
|
|
39
|
+
- [x] `init_trig()` — 初始化 Marker 实体(用户在 `@load` 里调用)
|
|
40
|
+
- [x] `sin_hp`, `cos_hp` — 框架 + `@require_on_load(init_trig)` 就绪
|
|
41
|
+
- [ ] 真正实现 — 需要 `@raw` / `@builtin` 语言特性(emit 层内嵌 mcfunction)
|
|
42
|
+
|
|
43
|
+
### `stdlib/random.mcrs`
|
|
44
|
+
- [x] `next_lcg(seed: int): int`
|
|
45
|
+
- [x] `random_range(seed, lo, hi)`
|
|
46
|
+
- [x] `random_bool(seed: int): int`
|
|
47
|
+
|
|
48
|
+
### `stdlib/random.mcrs`(已完成)
|
|
49
|
+
- [x] `next_lcg(seed: int): int`
|
|
50
|
+
- [x] `random_range(seed, lo, hi)`
|
|
51
|
+
- [x] `random_bool(seed: int): int`
|
|
52
|
+
|
|
53
|
+
### `stdlib/vec.mcrs` 补充
|
|
54
|
+
- [x] `Vec2`, `Vec3`, `dot2`, `dot3`, `dist2_sq`, `dist3_sq`
|
|
55
|
+
- [ ] `add2`, `sub2`, `scale2`(Vec2 加减缩放)
|
|
56
|
+
- [ ] `add3`, `sub3`, `scale3`(Vec3 加减缩放)
|
|
57
|
+
- [ ] `cross3(a, b: Vec3): Vec3` — 叉积
|
|
58
|
+
|
|
59
|
+
### `stdlib/color.mcrs`(新建)
|
|
60
|
+
- [ ] `rgb_to_int(r, g, b: int): int` — 打包成单个 int
|
|
61
|
+
- [ ] `int_to_r/g/b(c: int): int` — 解包
|
|
62
|
+
- [ ] `hsl_to_rgb(h, s, l: int): (int, int, int)` — 需要元组返回值
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Batch 2 — 需要位运算支持(语言特性 PR 先)
|
|
67
|
+
|
|
68
|
+
> 依赖:编译器支持 `^`、`>>`、`<<` 运算符(目前 scoreboard 没有原生位运算,需要编译器层模拟或降级)
|
|
69
|
+
|
|
70
|
+
### `stdlib/random.mcrs` 升级
|
|
71
|
+
- [ ] `next_pcg(state: int): int` — PCG 算法(比 LCG 质量好,需要 `^` 和 `>>` )
|
|
72
|
+
- [ ] `next_xorshift(x: int): int` — Xorshift(仅需 `^`、`>>`、`<<`)
|
|
73
|
+
|
|
74
|
+
### `stdlib/bits.mcrs`(新建)
|
|
75
|
+
- [ ] `bit_and(a, b: int): int` — 用加法模拟(慢但正确)
|
|
76
|
+
- [ ] `bit_or(a, b: int): int`
|
|
77
|
+
- [ ] `bit_xor(a, b: int): int`
|
|
78
|
+
- [ ] `bit_shift_left(x, n: int): int` — 乘以 2^n
|
|
79
|
+
- [ ] `bit_shift_right(x, n: int): int` — 除以 2^n
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Batch 3 — 需要数组完整支持
|
|
84
|
+
|
|
85
|
+
> 依赖:数组 literal 初始化完整实现(目前只有读取,写入走 workaround)
|
|
86
|
+
|
|
87
|
+
### `stdlib/list.mcrs`(新建)
|
|
88
|
+
- [ ] 基于 NBT list 的动态数组
|
|
89
|
+
- [ ] `list_push`, `list_pop`, `list_get`, `list_set`, `list_len`
|
|
90
|
+
- [ ] `list_sort_int` — 冒泡排序(整数)
|
|
91
|
+
- [ ] `list_sum`, `list_min`, `list_max`
|
|
92
|
+
|
|
93
|
+
### `stdlib/math.mcrs` — 查表升级
|
|
94
|
+
- [ ] `ln` 升级为查表 + 插值(需要 `@precompute` 或 `@load` 初始化 NBT list)
|
|
95
|
+
- [ ] `sin`/`cos` 高精度版(查表 + 和角公式)
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Batch 4 — 高级数学(长期)
|
|
100
|
+
|
|
101
|
+
### `stdlib/bigint.mcrs`
|
|
102
|
+
- [ ] 万进制 int 数组大数(基于 NBT int array)
|
|
103
|
+
- [ ] 大数加减乘
|
|
104
|
+
- [ ] 大数除以整数(竖式法)
|
|
105
|
+
|
|
106
|
+
### `stdlib/geometry.mcrs`
|
|
107
|
+
- [ ] `parabola_shoot` — 抛物线弹道(给定目标点和时间计算初速度)
|
|
108
|
+
- [ ] `cone_select` — 圆锥选区
|
|
109
|
+
- [ ] `midpoint3` — 三维中点
|
|
110
|
+
|
|
111
|
+
### `stdlib/signal.mcrs`
|
|
112
|
+
- [ ] `normal_dist_approx` — 正态分布近似(12个均匀分布相加)
|
|
113
|
+
- [ ] `exponential_dist` — 指数分布随机变量
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Tuner 覆盖计划
|
|
118
|
+
|
|
119
|
+
以下函数需要 `redscript tune` 生成最优系数:
|
|
120
|
+
|
|
121
|
+
| 函数 | Adapter | 目标精度 |
|
|
122
|
+
|------|---------|---------|
|
|
123
|
+
| `ln` | `ln-polynomial`(已有) | < 0.001 |
|
|
124
|
+
| `sqrt` | `sqrt-newton`(待写) | < 0.001 |
|
|
125
|
+
| `exp` | `exp-polynomial`(待写) | < 0.001 |
|
|
126
|
+
| `sin`/`cos` | `sincos-table`(待写) | < 0.0001 |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 语言特性依赖清单
|
|
131
|
+
|
|
132
|
+
| 特性 | 依赖的 stdlib | 难度 | 状态 |
|
|
133
|
+
|------|-------------|------|------|
|
|
134
|
+
| `@raw` / `@builtin` 内嵌 mcfunction | `sin_hp`/`cos_hp` 实现 | 中 | ❌ TODO |
|
|
135
|
+
| 位运算 `^>><< ` | random PCG, bits | 中 | ❌ TODO |
|
|
136
|
+
| 数组 literal 初始化 | list, bigint | 中 | ❌ TODO(读取已修,写入待做) |
|
|
137
|
+
| 元组返回值 | color(hsl_to_rgb)| 中 | ❌ TODO |
|
|
138
|
+
| `@precompute` 装饰器 | 高精度 sin/cos/ln | 高 | ❌ 长期 |
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
*生成于 2026-03-17 · 奇尔沙治*
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redscript-vscode",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.26",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "redscript-vscode",
|
|
9
|
-
"version": "1.2.
|
|
9
|
+
"version": "1.2.26",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"redscript": "file:../../",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"../..": {
|
|
26
26
|
"name": "redscript-mc",
|
|
27
|
-
"version": "2.
|
|
27
|
+
"version": "2.3.0",
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"vscode-languageserver": "^9.0.1",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "redscript-vscode",
|
|
3
3
|
"displayName": "RedScript for Minecraft",
|
|
4
4
|
"description": "Syntax highlighting, error diagnostics, and language support for RedScript — a compiler targeting Minecraft Java Edition",
|
|
5
|
-
"version": "1.2.
|
|
5
|
+
"version": "1.2.26",
|
|
6
6
|
"publisher": "bkmashiro",
|
|
7
7
|
"icon": "icon.png",
|
|
8
8
|
"license": "MIT",
|
package/package.json
CHANGED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the redscript tuner engine, simulator, and ln-polynomial adapter.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { search, searchSA } from '../../tuner/engine';
|
|
6
|
+
import { i32, fixedMul, isOverflow } from '../../tuner/simulator';
|
|
7
|
+
import { evaluate } from '../../tuner/metrics';
|
|
8
|
+
import { lnPolynomialAdapter, defaultParams as lnDefaultParams } from '../../tuner/adapters/ln-polynomial';
|
|
9
|
+
import { sqrtNewtonAdapter, defaultParams as sqrtDefaultParams } from '../../tuner/adapters/sqrt-newton';
|
|
10
|
+
import { TunerAdapter, ParamSpec } from '../../tuner/types';
|
|
11
|
+
|
|
12
|
+
// ─── simulator tests ──────────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
describe('simulator', () => {
|
|
15
|
+
test('i32 truncates to int32', () => {
|
|
16
|
+
expect(i32(3.7)).toBe(3);
|
|
17
|
+
expect(i32(-3.7)).toBe(-3);
|
|
18
|
+
expect(i32(2147483648)).toBe(-2147483648); // overflow wraps
|
|
19
|
+
expect(i32(0)).toBe(0);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('fixedMul basic', () => {
|
|
23
|
+
// 10000 * 10000 / 10000 = 10000
|
|
24
|
+
expect(fixedMul(10000, 10000, 10000)).toBe(10000);
|
|
25
|
+
// 5000 * 2 / 10000 = 1
|
|
26
|
+
expect(fixedMul(5000, 2, 10000)).toBe(1);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('fixedMul returns Infinity on overflow', () => {
|
|
30
|
+
expect(fixedMul(2147483647, 2147483647, 1)).toBe(Infinity);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('isOverflow detects out-of-range', () => {
|
|
34
|
+
expect(isOverflow(2147483648)).toBe(true);
|
|
35
|
+
expect(isOverflow(-2147483649)).toBe(true);
|
|
36
|
+
expect(isOverflow(Infinity)).toBe(true);
|
|
37
|
+
expect(isOverflow(NaN)).toBe(true);
|
|
38
|
+
expect(isOverflow(0)).toBe(false);
|
|
39
|
+
expect(isOverflow(2147483647)).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// ─── Nelder-Mead convergence test ────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
describe('Nelder-Mead engine', () => {
|
|
46
|
+
test('converges to minimum of (x-3)^2', () => {
|
|
47
|
+
// Simple 1D minimization: minimize (x-3)^2
|
|
48
|
+
const mockAdapter: TunerAdapter = {
|
|
49
|
+
name: 'test-quadratic',
|
|
50
|
+
description: 'Minimize (x-3)^2',
|
|
51
|
+
params: [
|
|
52
|
+
{ name: 'x', range: [-10, 10], integer: false } as ParamSpec,
|
|
53
|
+
],
|
|
54
|
+
simulate(input: number, params: Record<string, number>): number {
|
|
55
|
+
// Return the residual as a scaled integer
|
|
56
|
+
const x = params['x'];
|
|
57
|
+
return Math.round(x * 10000);
|
|
58
|
+
},
|
|
59
|
+
reference(_input: number): number {
|
|
60
|
+
// Target: x = 3 → value 30000
|
|
61
|
+
return 30000;
|
|
62
|
+
},
|
|
63
|
+
sampleInputs(): number[] {
|
|
64
|
+
return [1]; // single input, target value is 3.0 (×10000 = 30000)
|
|
65
|
+
},
|
|
66
|
+
generateCode(params: Record<string, number>): string {
|
|
67
|
+
return `// x = ${params['x']}`;
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const result = search(mockAdapter, 5000);
|
|
72
|
+
// Should converge close to x=3
|
|
73
|
+
expect(result.params['x']).toBeCloseTo(3.0, 1);
|
|
74
|
+
expect(result.maxError).toBeLessThan(0.1);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('handles integer constraints', () => {
|
|
78
|
+
const mockAdapter: TunerAdapter = {
|
|
79
|
+
name: 'test-integer',
|
|
80
|
+
description: 'Integer parameter test',
|
|
81
|
+
params: [
|
|
82
|
+
{ name: 'n', range: [0, 10], integer: true } as ParamSpec,
|
|
83
|
+
],
|
|
84
|
+
simulate(input: number, params: Record<string, number>): number {
|
|
85
|
+
// Should snap to integer 7
|
|
86
|
+
return Math.round(params['n'] * 10000);
|
|
87
|
+
},
|
|
88
|
+
reference(_input: number): number {
|
|
89
|
+
return 70000; // 7.0 × 10000
|
|
90
|
+
},
|
|
91
|
+
sampleInputs(): number[] {
|
|
92
|
+
return [1];
|
|
93
|
+
},
|
|
94
|
+
generateCode(): string {
|
|
95
|
+
return '';
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const result = search(mockAdapter, 2000);
|
|
100
|
+
// Should find n close to 7
|
|
101
|
+
expect(Math.round(result.params['n'])).toBe(7);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('i32 overflow penalization', () => {
|
|
105
|
+
const mockAdapter: TunerAdapter = {
|
|
106
|
+
name: 'test-overflow',
|
|
107
|
+
description: 'Test overflow penalization',
|
|
108
|
+
params: [
|
|
109
|
+
{ name: 'scale', range: [1, 1000], integer: true } as ParamSpec,
|
|
110
|
+
],
|
|
111
|
+
simulate(_input: number, params: Record<string, number>): number {
|
|
112
|
+
// Always overflow for any scale >= 500
|
|
113
|
+
if (params['scale'] >= 500) return Infinity;
|
|
114
|
+
return params['scale'] * 10000;
|
|
115
|
+
},
|
|
116
|
+
reference(_input: number): number {
|
|
117
|
+
return 2000000; // target: scale=200 → 2000000
|
|
118
|
+
},
|
|
119
|
+
sampleInputs(): number[] {
|
|
120
|
+
return [1];
|
|
121
|
+
},
|
|
122
|
+
generateCode(): string {
|
|
123
|
+
return '';
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const { maxError, mae, rmse } = evaluate(mockAdapter, { scale: 2147483647 });
|
|
128
|
+
expect(maxError).toBe(Infinity);
|
|
129
|
+
expect(mae).toBe(Infinity);
|
|
130
|
+
expect(rmse).toBe(Infinity);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// ─── ln-polynomial adapter tests ─────────────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
describe('ln-polynomial adapter', () => {
|
|
137
|
+
const defaultParams = lnDefaultParams; // { A1: 20000, A3: 6667, A5: 4000 }
|
|
138
|
+
|
|
139
|
+
test('sample inputs cover the valid range', () => {
|
|
140
|
+
const inputs = lnPolynomialAdapter.sampleInputs();
|
|
141
|
+
expect(inputs.length).toBeGreaterThan(50);
|
|
142
|
+
// All inputs should be positive
|
|
143
|
+
expect(inputs.every(x => x > 0)).toBe(true);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test('reference matches Math.log', () => {
|
|
147
|
+
const SCALE = 10000;
|
|
148
|
+
// ln(1.0) = 0
|
|
149
|
+
expect(lnPolynomialAdapter.reference(SCALE)).toBeCloseTo(0, 5);
|
|
150
|
+
// ln(2.0) ≈ 0.6931 → 6931
|
|
151
|
+
expect(lnPolynomialAdapter.reference(2 * SCALE)).toBeCloseTo(6931.47, 0);
|
|
152
|
+
// ln(0.5) ≈ -0.6931 → -6931
|
|
153
|
+
expect(lnPolynomialAdapter.reference(5000)).toBeCloseTo(-6931.47, 0);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test('simulate produces reasonable output for x=1 (no error)', () => {
|
|
157
|
+
const result = lnPolynomialAdapter.simulate(10000, defaultParams);
|
|
158
|
+
// ln(1.0) = 0; allow some approximation error
|
|
159
|
+
expect(Math.abs(result)).toBeLessThan(500); // within 0.05
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test('simulate returns Infinity for invalid input', () => {
|
|
163
|
+
const result = lnPolynomialAdapter.simulate(0, defaultParams);
|
|
164
|
+
expect(result).toBeLessThan(0); // negative sentinel or -MAX_INT
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('max_error < 0.001 with default atanh coefficients', () => {
|
|
168
|
+
const metrics = evaluate(lnPolynomialAdapter, defaultParams);
|
|
169
|
+
expect(metrics.maxError).toBeLessThan(0.001);
|
|
170
|
+
}, 10000);
|
|
171
|
+
|
|
172
|
+
test('search improves over default params', () => {
|
|
173
|
+
// Run a short search and confirm it doesn't get worse
|
|
174
|
+
const baseMetrics = evaluate(lnPolynomialAdapter, defaultParams);
|
|
175
|
+
const result = search(lnPolynomialAdapter, 500); // short budget for test speed
|
|
176
|
+
// Either same or better
|
|
177
|
+
expect(result.maxError).toBeLessThanOrEqual(baseMetrics.maxError * 2);
|
|
178
|
+
expect(result.maxError).toBeLessThan(0.01);
|
|
179
|
+
}, 30000);
|
|
180
|
+
|
|
181
|
+
test('generateCode produces valid output', () => {
|
|
182
|
+
const meta = {
|
|
183
|
+
maxError: 0.00003,
|
|
184
|
+
mae: 0.000012,
|
|
185
|
+
rmse: 0.000015,
|
|
186
|
+
estimatedCmds: 38,
|
|
187
|
+
tuneDate: '2026-03-17',
|
|
188
|
+
budgetUsed: 5000,
|
|
189
|
+
};
|
|
190
|
+
const code = lnPolynomialAdapter.generateCode(defaultParams, meta);
|
|
191
|
+
expect(code).toContain('AUTO-GENERATED');
|
|
192
|
+
expect(code).toContain('ln-polynomial');
|
|
193
|
+
expect(code).toContain('fn ln');
|
|
194
|
+
expect(code).toContain('A1');
|
|
195
|
+
expect(code).toContain('A3');
|
|
196
|
+
expect(code).toContain('A5');
|
|
197
|
+
expect(code).toContain('2026-03-17');
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test('searchSA achieves max_error < 0.001 on ln-polynomial', () => {
|
|
201
|
+
const result = searchSA(lnPolynomialAdapter, 3000);
|
|
202
|
+
expect(result.maxError).toBeLessThan(0.001);
|
|
203
|
+
}, 30000);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// ─── sqrt-newton adapter tests ────────────────────────────────────────────────
|
|
207
|
+
|
|
208
|
+
describe('sqrt-newton adapter', () => {
|
|
209
|
+
test('simulate(10000, defaultParams) ≈ 10000 (sqrt(1.0)=1.0)', () => {
|
|
210
|
+
const result = sqrtNewtonAdapter.simulate(10000, sqrtDefaultParams);
|
|
211
|
+
// sqrt(1.0) * 10000 = 10000
|
|
212
|
+
expect(Math.abs(result - 10000)).toBeLessThan(10);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test('simulate(40000, defaultParams) ≈ 20000 (sqrt(4.0)=2.0)', () => {
|
|
216
|
+
const result = sqrtNewtonAdapter.simulate(40000, sqrtDefaultParams);
|
|
217
|
+
// sqrt(4.0) * 10000 = 20000
|
|
218
|
+
expect(Math.abs(result - 20000)).toBeLessThan(10);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test('simulate(0) returns 0', () => {
|
|
222
|
+
expect(sqrtNewtonAdapter.simulate(0, sqrtDefaultParams)).toBe(0);
|
|
223
|
+
expect(sqrtNewtonAdapter.simulate(-1, sqrtDefaultParams)).toBe(0);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test('simulate(250000, defaultParams) ≈ 50000 (sqrt(25.0)=5.0)', () => {
|
|
227
|
+
const result = sqrtNewtonAdapter.simulate(250000, sqrtDefaultParams);
|
|
228
|
+
expect(Math.abs(result - 50000)).toBeLessThan(10);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test('sample inputs are all positive', () => {
|
|
232
|
+
const inputs = sqrtNewtonAdapter.sampleInputs();
|
|
233
|
+
expect(inputs.length).toBeGreaterThan(50);
|
|
234
|
+
expect(inputs.every(x => x > 0)).toBe(true);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
test('reference matches Math.sqrt', () => {
|
|
238
|
+
const SCALE = 10000;
|
|
239
|
+
expect(sqrtNewtonAdapter.reference(SCALE)).toBe(SCALE); // sqrt(1.0)
|
|
240
|
+
expect(sqrtNewtonAdapter.reference(4 * SCALE)).toBe(2 * SCALE); // sqrt(4.0)
|
|
241
|
+
expect(sqrtNewtonAdapter.reference(9 * SCALE)).toBe(3 * SCALE); // sqrt(9.0)
|
|
242
|
+
expect(sqrtNewtonAdapter.reference(0)).toBe(0);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
test('generateCode contains fn sqrt_fx', () => {
|
|
246
|
+
const meta = {
|
|
247
|
+
maxError: 1.5,
|
|
248
|
+
mae: 0.5,
|
|
249
|
+
rmse: 0.8,
|
|
250
|
+
estimatedCmds: 30,
|
|
251
|
+
tuneDate: '2026-03-17',
|
|
252
|
+
budgetUsed: 3000,
|
|
253
|
+
};
|
|
254
|
+
const code = sqrtNewtonAdapter.generateCode(sqrtDefaultParams, meta);
|
|
255
|
+
expect(code).toContain('AUTO-GENERATED');
|
|
256
|
+
expect(code).toContain('sqrt-newton');
|
|
257
|
+
expect(code).toContain('fn sqrt_fx');
|
|
258
|
+
expect(code).toContain('2026-03-17');
|
|
259
|
+
});
|
|
260
|
+
});
|