|
| 1 | +# Writes src/codecs/jxl/fdct.ts: the forward 8- to 64-point DCTs of src/codecs/jxl/dct.ts's recursion as |
| 2 | +# straight-line code (the same operations in the same order, on locals instead of scratch arrays): |
| 3 | +# python scripts/jxl-fdct.py > src/codecs/jxl/fdct.ts |
| 4 | +counter = [0] |
| 5 | +lines = [] |
| 6 | +def tmp(expr): |
| 7 | + counter[0] += 1 |
| 8 | + name = f't{counter[0]}' |
| 9 | + lines.append(f' const {name} = {expr};') |
| 10 | + return name |
| 11 | + |
| 12 | +def fdct(vals, n): |
| 13 | + # vals: list of expressions (locals) of length n; returns list of result names |
| 14 | + if n == 4: |
| 15 | + i0, i1, i2, i3 = vals |
| 16 | + s03 = tmp(f'{i0} + {i3}'); s12 = tmp(f'{i1} + {i2}') |
| 17 | + t0 = tmp(f'({i0} - {i3}) * SEC0'); t1 = tmp(f'({i1} - {i2}) * SEC1') |
| 18 | + o0 = tmp(f'({t0} + {t1}) / 4'); o1 = tmp(f'({t0} - {t1}) / 4') |
| 19 | + return [tmp(f'({s03} + {s12}) / 4'), tmp(f'{o0} * Math.SQRT2 + {o1}'), tmp(f'({s03} - {s12}) / 4'), o1] |
| 20 | + half = n // 2 |
| 21 | + a = [tmp(f'({vals[i]} + {vals[n - i - 1]}) / 2') for i in range(half)] |
| 22 | + b = [tmp(f'({vals[i]} - {vals[n - i - 1]}) / 2 * SEC{n}[{i}]') for i in range(half)] |
| 23 | + a = fdct(a, half) |
| 24 | + b = fdct(b, half) |
| 25 | + # b[0] *= sqrt 2, then b[i] += b[i + 1] (ascending: each adds the original) |
| 26 | + b = list(b) |
| 27 | + b[0] = tmp(f'{b[0]} * Math.SQRT2') |
| 28 | + b = [tmp(f'{b[i]} + {b[i + 1]}') for i in range(half - 1)] + [b[half - 1]] |
| 29 | + out = [None] * n |
| 30 | + for i in range(half): |
| 31 | + out[2 * i] = a[i] |
| 32 | + out[2 * i + 1] = b[i] |
| 33 | + return out |
| 34 | + |
| 35 | +print('''/*! |
| 36 | + * Generated by scripts/jxl-fdct.py: the forward 8- to 64-point DCTs of dct.ts, unrolled (its recursion is ported |
| 37 | + * from jxl-oxide, crates/jxl-render/src/vardct/generic/dct.rs; Copyright (c) Wonwoo Choi, MIT License, see |
| 38 | + * THIRD_PARTY_NOTICES.md) |
| 39 | + */ |
| 40 | +
|
| 41 | +const SEC0 = 0.5411961, SEC1 = 1.306563; |
| 42 | +// 1 / (2 cos((2k + 1) pi / 2n)) |
| 43 | +const secants = (n: number): Float64Array => Float64Array.from({ length: n / 2 }, (_, k) => 1 / Math.cos((2 * k + 1) / (2 * n) * Math.PI) / 2); |
| 44 | +const SEC8 = secants(8), SEC16 = secants(16), SEC32 = secants(32), SEC64 = secants(64); |
| 45 | +''') |
| 46 | +for n in (8, 16, 32, 64): |
| 47 | + counter[0] = 0; lines.clear() |
| 48 | + vals = [f'v{i}' for i in range(n)] |
| 49 | + out = fdct(vals, n) |
| 50 | + print(f'// the forward {n}-point DCT of buf[o + k * step] in place (generated: dct\'s recursion, unrolled)') |
| 51 | + print(f'export function fdct{n}(buf: Float32Array | Float64Array, o: number, step: number): void {{') |
| 52 | + for i in range(n): |
| 53 | + print(f' const v{i} = buf[o + {i} * step];' if i else ' const v0 = buf[o];') |
| 54 | + for l in lines: print(l) |
| 55 | + for i in range(n): |
| 56 | + print(f' buf[o + {i} * step] = {out[i]};' if i else f' buf[o] = {out[0]};') |
| 57 | + print('}') |
| 58 | + print() |
0 commit comments