Compare commits

..
5 Commits
4 changed files with 300 additions and 1 deletions
+79
View File
@@ -536,3 +536,82 @@ R@5407f8 = единичная нормировка (все 1.0000 в этом п
### Статус ### Статус
Канонический путь чтения ПРИМЕНЁННОЙ маски: слот [ctx+0x540678] (кривая Канонический путь чтения ПРИМЕНЁННОЙ маски: слот [ctx+0x540678] (кривая
банды) — он стабилен и МАТЧИТ АУДИО в deep-фазах (±5%). банды) — он стабилен и МАТЧИТ АУДИО в deep-фазах (±5%).
## ДОПОЛНЕНИЕ 24mm2: ПОЛНАЯ РЕЗОЛЮВСЯ ВСЕХ 10 ЯДЕР + ИСПРАВЛЕНИЯ DATAFLOW
Инструмент: статический резолв цепочки стаб→таблица→L2→IAT-слот по
soothe_mem.bin (без live). Стаб = `movsxd rax,[idx@1826159a0]; lea r10,[tbl];
jmp [r10+rax*8]`, idx=4, L2=`mov rax,[slot]; jmp rax`.
### Таблица резолва (исправляет 24jj!)
| стаб | таблица | runtime | опознание по константам |
|------|---------|---------|------------------------|
| 140950 | 182617448 | **18026b820** | exp2/exp DOUBLE (ln2, log2e, 1021.5, 2^27) |
| 140980 | 182617488 | **18027c120** | **logf** FLOAT (ряд −½,+⅓,−¼,+⅕,−⅙; ln2 hi/lo; 2^32) |
| 1409b0 | 1826174c8 | **18028d1e0** | **powf/log+exp** DOUBLE (ряд log + магия expf вместе) |
| 1409e0 | 182617508 | 180296c80 ✓ | **expf** FLOAT — ДЕКОДИРОВАН ПОЛНОСТЬЮ (ниже) |
| 140a40 | 182617588 | 1802dc0e0 ✓ | exp-вариант FLOAT c hi/lo сплитами |
| 140aa0 | 182617608 | **18030fee0** | **sincos** DOUBLE (1/6,1/120,1/5040; π hi/lo) |
| 140ad0 | 182617648 | 180323f20 ✓ | кусочно-табличная DOUBLE (сетка Δ=0.00541521) |
| 140b00 | 182617688 | **180367980** | pow/exp DOUBLE (1023/1022, магия 1.5·2^20) |
| 140b30 | 1826176c8 | **1803831c0** | кусочно-табличная FLOAT (π/2, π/4, сетка 184.665!) |
| 140b60 | 182617708 | 1803a06a0 ✓ | **DIVIDE** FLOAT B/A (rcp+квантование+vpermps-таблицы+полином невязки) |
**ИСПРАВЛЕНИЕ 24jj**: «140b30/140b60 → общий 1803a06a0» — НЕВЕРНО.
FIR-секция вызывает 140b30 = 1803831c0 (табличная кривая), divide только в шаге 9c.
### ДИСПЕТЧЕР float/double
Каждый call-site имеет ПАРУ стабов через `call [181bab008]; test eax,eax; jne`:
float-стаб (eax==0) / double-стаб. Дескрипторы type_info СТАТИЧЕСКИ идентичны
(оба →182650db8) ⇒ eax=0 ⇒ **double-ядра мертвы на нашем пути**; рендеры
идут по float. Double-тела не транскрибируем (отмечено на будущее M8).
### expf 180296c80 — полная формула (горячий цикл, FMA-точно)
```
n = fma(log2e_hi=1.4427, x, MAGIC=12582912.0) ; округление до int
k = n MAGIC
r = (x 0.693146·k) 1.42861e-06·k ; ln2 hi/lo
p = (((0.00829172·r + 0.0418735)·r + 0.166674)·r + 0.499994)·r + 1)·r + 1
out = bits( (k<<23) + bits(p) ) ; vpaddd сборка
guard: |x|>87.3365 → slow-path; head/tail через vmaskmovps+popcnt-маски
```
Коэф. минимаксные — транскрибировать КАК ЕСТЬ.
### DIVIDE 1803a06a0 — структура (90%)
```
A=[rcx], B=[rdx], dst=[r8]; r9d=n
q0 = rcp(A); q0 += 2^23-magic (округление); q = q0 & 0xfff00000 ; 12 бит
e = (q>>23); idx = q>>20 → vpermps tbl@1821269c0 (127±ε) и @182126a00
err = 1 q·A
полином невязки {0.207515, 0.241687, 0.288535, 0.360671, ..., 0.240264, 0.0555119}
сборка через магию 1.5·2^20 + vpslld 20
результат ≈ B/A с точностью ~0.5 ulp
```
Таблицы коррекций сдамплены (per-mantissa-top-bits).
### ИСПРАВЛЕНИЯ DATAFLOW (по fn529fe0.dis, адреса call-sites)
1. **Шаг 14 порядок ОБРАТЕН к BLOCKMAP 24ii**: сначала `bigkernel exp IN-PLACE
на bands_curve` (52ae0e), ПОТОМ `bands_curve += (1.0)` (52ae40, конст.
1824c4680 через th2270).
2. Шаг 9b точно: `vec6f8 += [ctx+54087c] · 0.8` (xmm10=0.8@1824c3e28,
множитель виден в asm: mulss xmm6,xmm10 после movss xmm6,[54087c]).
3. Шаг 9a: `vec698 *= (xmm12=1.0 [54087c])` ⇒ zero-fill при дефолтах ✓.
4. Шаг 10 combine dc40: аргументы rcx=ACC_i(**таблица указателей @0x5407c8**,
НЕ дампилась rendersnap2!), rdx=bands_curve_i(@678+i), r8=vec6f8(@6f8),
семантика dst=r8: vec6f8 = bands_curve_i ACC_i. ACC-слот надо ДОБАВИТЬ
в SLOTS rendersnap2 (0x5407c8).
5. Шаги 15/16 подтверждены: th2000/th1c40 array-mul; затем rbx=[5406a8]
(kWarp) — array-mul на bands_curve.
6. Эпилог: скалярная часть из decomp (consumers_out 100-143): mix-веса,
`fVar17 = [540874] expf(DAT_1824c4704=-ln1000)` → bands += f17·[540888].
### Call-site карта больших ядер (fn529fe0)
```
52a63a/52a641: 140980(logf-float)/1409b0 — pre-combine #1
52ab84/52ab8b: 140b60(divide)/140950 — шаг 9c
52acd? : (шаги 1012 мелкие ILT)
52ae0e/52ae15: 1409e0(expf)/140ad0 — шаг 14 нелинейность
52b32c/52b336: 1409e0(expf)/140ad0 — шаг 17 (повтор)
52b3a0/52b3aa: 140a40(exp-var)/140b00 — пост-17
52b716/52b71d: 140b30(кривая-float)/140aa0 — FIR-секция
```
+81
View File
@@ -3940,3 +3940,84 @@ STATE = [ctx+0x540788] (спектральная память, читаетс
### Практический статус ### Практический статус
dual-семейство: корпус 0.193 (формулы + калибровка). Канон нетронут (2.286). dual-семейство: корпус 0.193 (формулы + калибровка). Канон нетронут (2.286).
Все инструменты/датасеты воспроизводимы. ~85 коммитов запушено. Все инструменты/датасеты воспроизводимы. ~85 коммитов запушено.
## ============ 24mm2: ВСЕ 10 ЯДЕР РАЗРЕЗОЛВЛЕНЫ СТАТИЧЕСКИ; expf/divide декодированы; каскад-сим стартовал ============
### Декод (детали в BLOCKMAP 24mm2)
1. Полный статический резолв стаб→tbl[4]→L2→IAT всех десяти bigkernel'ов
БЕЗ live-процесса. Исправлена ошибка 24jj: 140b30≠140b60 (FIR вызывает
табличную кривую 1803831c0, divide 1803a06a0 — только шаг 9c).
2. Библиотека ядер опознана: expf/logf/powf/sincos/exp2-double + кусочно-
табличная кривая (float/double). Пары стабов на call-site = float/double
диспетчер через type_info; double-ветка мертва (дескрипторы совпадают).
3. expf 180296c80 декодирован до формулы (минимакс-полином + битовая
сборка (k<<23)+bits(p), guard 87.3365).
4. Divide 1803a06a0: rcp → квантование 12 бит → vpermps-таблицы коррекции
(@1821269c0/a00, сдамплены) → полином невязки → сборка 1.5·2^20.
5. Шаг-14 порядок исправлен: exp ДО +=(−1). ACC-таблица @0x5407c8 — не
дампилась, добавить в rendersnap2 SLOTS.
### Следующее (в работе)
- Каскад-сим scripts/cascade_sim.py: вход tract_multi_in.txt, якоря ph040;
divide/expf сначала numpy-эквиваленты (структурная фаза), C++-порт с
FMA-точной транскрипцией после замыкания структуры.
## ============ ПРОРЫВ 24mm3: ПРИМЕНЁННАЯ МАСКА = СТЕПЕНЬ ТРЕКА: mask = trk^γ, γ=1.760561 (точно) ============
### Факт (по всем sc_* датасетам, чистые стационарные кадры)
```
cur@678 = trk@688 ^ γ
trk@688 = exp(scr@628) ; бит-в-бит (allclose rtol 1e-3)
γ = 1.760561 ; rms фита РОВНО 0 на чистых кадрах
; (tt0 n=37, sens18/24, qmap_q3/q6, q0.3)
```
Кадры с γ=1.000000 (тоже точные!) — фаза ДО применения степени;
0.5/0/41.75/82.99 — переходные/полиморфные состояния слотов.
Вариации 1.7603–1.7605 у части датасетов = лёгкая пер-бин модуляция
поверх степени (warp-класс), не разброс константы.
### Следствие 1: кат_дБ = −γ·scr·(20/ln10)
Проверка: multi4b @bin43: scr=0.6481 → 1.760561·0.6481·8.6859 = 9.90 дБ
= измеренному deep-кату tt-PK1. ВСЕ прежние калибровки (α,β,c) фитились
против −scr·γ ⇒ γ был поглощён в α!
### Следствие 2: структура детектора переформулируется
```
scr(f) = дизайн-сигнал детектора (log-домен, ноль вне пиков)
mask(f) = exp(γ · scr(f)) ; γ вычисляется цепочкой шагов 9–19
```
γ НЕ хранится в бинаре (поиск точных f32/f64 бит — пусто, только
кусочные таблицы ~1.7596..1.7611 @181c72xxx) ⇒ γ возникает из алгебры
(divide+add+exp каскада). Задача симулятора: воспроизвести γ из операций.
### Методическая заметка
rendersnap-кадры полиморфны: отбирать только кадры где (а) trk==exp(scr),
(б) fit γ имеет rms<1e-5, (в) нет нулей в 678. Критерий отбора встроен
в scan-скрипты следующего раунда.
## ============ 24mm4: ЦЕЛЬ СИМУЛЯТОРА = scr(f); ТОЧЕЧНЫЕ ЗАКОНЫ ОТВЕРГНУТЫ НА 447 БИНАХ; cascade_sim.py ============
### Сквозная валидация степенного закона (scripts/cascade_sim.py)
- multi4b/ph073: γ=1.760561 (fit rms 1.1e-07), закон mask=trk^γ:
rms 0.0064 дБ / 48 бинов | multi4b/ph065: 0.0006 дБ / 103 бина
- multi6: identity-фаза ph034 (γ=1, маска==trk, 499 бинов rms 0) даёт ВСЕ
шесть нотчей ±0.03 дБ; γ-фаза ph037: 0.0006 дБ.
- Отбор кадров формализован (pick_clean_frame): две фазы (γ*≈1.760561 и
identity γ=1), критерий fit-rms<1e-4.
### Детекторный вход: точечные законы окончательно мертвы
На multi6/ph034 по всем 447 значимым бинам: corr(scr, ln X) ≤ 0.36 для
X ∈ {lvl, am·S/res, am·S, S/res, am·res, S·lvl, am·S/√res}; лучший
двухпараметрический фит rms 0.20 (нужно <0.05 дБ). scr(f) зависит от
ОКРЕСТНОСТИ спектра ⇒ воспроизводится только спектральным каскадом
(частотные IIR шагов детектора, коэф. 533340). Это и есть остаток Задачи №1.
### Состояние на закрытие сессии
1. Все 10 ядер резолвлены+опознаны; expf/divide декодированы до формул
(BLOCKMAP 24mm2). Каноническая C++ транскрипция ядер — после замыкания
структуры каскада.
2. Применение: mask=trk^1.760561, trk=exp(scr); γ вычисляется цепочкой —
источник γ в алгебре divide/add/exp шагов 9–19 (поиск в декоде).
3. Симулятор: scripts/cascade_sim.py (каркас + валидатор + отбор кадров).
Следующий раунд: оп-за-оп декод тела каскада между lvl_raw и scr
(частотные IIR с коэф. 24cc → vec6f8/bands_curve), затем C++ порт.
+139
View File
@@ -0,0 +1,139 @@
#!/usr/bin/env python3
"""cascade_sim.py — структурный симулятор тракта маски soothe2 (float-путь).
Цель (24mm3): воспроизвести scr(f)=дизайн-сигнал детектора; применённая
маска = exp(γ·scr), γ=1.760561 (точно), trk@688=exp(scr@628) бит-в-бит.
Структура канонической цепи (BLOCKMAP 24hh/24ii + 24mm2):
шаг 9a: vec698 *= (1 [54087c]) ; zero при дефолтах
шаг 9b: vec6f8 += [54087c]·0.8 ; xmm10=0.8 @1824c3e28
шаг 9c: bands_curve_i /= ... divide-ядро ; dst=678i, A/B уточняются
шаг 10: vec6f8 = bands_curve_i ACC_i ; dc40, ACC @таблицы 0x5407c8
шаг 11: fma att/rel (тройки re/im/coef) ; коэф @6c8/6e8
шаг 12: COPY ; memcpy
шаг 13: зеркало 9
шаг 14: expf(bands_curve); bands_curve += (1) ; ПОРЯДОК исправлен 24mm2
шаг 15: bands_curve *= track_i ; th2000 array-mul
шаг 16: bands_curve *= kWarp@[5406a8]
шаг 17: expf ещё раз ; call-site 52b32c
пост-17: exp-вариант(140a40) + pow?(140b00)
FIR-секция: кривая-float(140b30→1803831c0) + sincos-twiddle(140aa0)
ЯДРА (структурная фаза — математически точные numpy-эквиваленты;
канонический C++ порт = инструкци-точная транскрипция, см. BLOCKMAP 24mm2):
"""
import numpy as np
import glob
import os
GAMMA = 1.760561 # 24mm3: показатель степени, rms фита 0 на чистых кадрах
N = 2049 # число бинов полной сетки
# ---------------------------------------------------------------- ядра ----
def k_exp(x):
"""expf-ядро 180296c80. Структурная фаза: np.exp.
Каноническая формула (для C++ порта, FMA-точно):
n = fma(log2e_hi=1.4427f, x, 12582912.0f); k = n - MAGIC
r = (x - 0.693146f*k) - 1.42861e-06f*k
p = (((0.00829172f*r+0.0418735f)*r+0.166674f)*r+0.499994f)*r+1)*r+1
out = bits((k<<23) + bits(p)); guard |x|>87.3365 -> slow path
"""
return np.exp(x)
def k_div(a, b):
"""divide-ядро 1803a06a0: dst = B/A (~0.5 ulp, rcp+таблицы+полином).
Структурная фаза: точное деление."""
return b / a
# ------------------------------------------------------------ данные -----
def load_tract(path):
"""tract_*.txt: k am res lvl_raw band_level prewarp w"""
t = np.loadtxt(path)
return {'am': t[:, 1], 'res': t[:, 2], 'lvl': t[:, 3]}
def load_frame(npz):
"""Слоты кадра rendersnap2 → dict[int, np.ndarray]."""
d = np.load(npz)
out = {}
for k in d.keys():
if k.startswith('0x'):
out[int(k[2:], 16)] = d[k]
return out, d['t_snap']
def pick_clean_frame(ds_dir, min_bins=8):
"""Отбор чистых стационарных кадров по фазам (24mm3):
возвращает лучший на фазе γ* (~1.7606, маска применена)
и лучший на фазе γ=1 (степень ещё не применена)."""
classes = {'gamma': None, 'identity': None}
for f in sorted(glob.glob(os.path.join(ds_dir, 'ph*.npz'))):
try:
S, ts = load_frame(f)
except Exception:
continue
if not all(x in S for x in (0x540628, 0x540688, 0x540678)):
continue
s = S[0x540628][:1025].astype(np.float64)
t = S[0x540688][:1025].astype(np.float64)
c = S[0x540678][:1025].astype(np.float64)
ok = (t > 1e-30) & (c > 1e-30) & np.isfinite(s)
if ok.sum() < 50:
continue
lt = np.log(t[ok])
lc = np.log(c[ok])
sel = np.abs(lt) > 0.05
if sel.sum() < min_bins:
continue
g = float(np.sum(lt[sel] * lc[sel]) / np.sum(lt[sel] ** 2))
rms = float(np.sqrt(np.mean((lc[sel] - g * lt[sel]) ** 2)))
depth = float(-lc.min())
key = 'gamma' if abs(g - GAMMA) < 0.01 else \
('identity' if abs(g - 1.0) < 1e-4 else None)
if key is None or rms > 1e-4:
continue
cand = (depth, f, s, t, c, g, rms)
if classes[key] is None or depth > classes[key][0]:
classes[key] = cand
return classes
# ------------------------------------------------------- валидация -------
def validate_scr(sim_scr, cap_scr, tol_db=0.05):
"""rms в дБ между симулированным и захваченным scr."""
m = np.abs(cap_scr) > 0.02
err = (sim_scr[m] - cap_scr[m]) * (20 / np.log(10))
return float(np.sqrt(np.mean(err ** 2))), int(m.sum())
def main():
import sys
ds = sys.argv[1] if len(sys.argv) > 1 else '/tmp/opencode/sc_multi6'
tract = sys.argv[2] if len(sys.argv) > 2 else '/tmp/opencode/tract_multi6.txt'
classes = pick_clean_frame(ds)
ph_g = classes['gamma']
ph_i = classes['identity']
if not ph_g and not ph_i:
print('нет чистых кадров в', ds)
return
for lbl, best in (('γ-фаза', ph_g), ('identity', ph_i)):
if not best:
continue
_, f, scr, trk, cur, gamma_fit, grms = best
n = len(scr)
cut_meas = -20 / np.log(10) * np.log(np.maximum(cur, 1e-30))
g_use = gamma_fit
cut_sim = g_use * (-scr) * 20 / np.log(10)
e = cut_sim - cut_meas
sel = np.abs(cut_meas) > 0.1
rms_db = float(np.sqrt(np.mean(e[sel] ** 2))) if sel.any() else 0.0
print(f'{lbl}: {os.path.basename(f)} γ={gamma_fit:.6f} (rms {grms:.1e}) '
f'закон: rms={rms_db:.4f} дБ / {int(sel.sum())} бинов')
if __name__ == '__main__':
main()
+1 -1
View File
@@ -18,7 +18,7 @@ import time
import numpy as np import numpy as np
SLOTS = [0x540668, 0x540548, 0x540550, 0x540598, 0x540628, SLOTS = [0x540668, 0x540548, 0x540550, 0x540598, 0x540628, 0x5406f8,
0x540678, 0x540688, 0x5406c8, 0x5406e8, 0x540768, 0x540678, 0x540688, 0x5406c8, 0x5406e8, 0x540768,
0x540788, 0x5407f8] 0x540788, 0x5407f8]
NARR = 8194 NARR = 8194