imazen / imazen/archmage

magetypes: no lane-broadcast or lane-shift (blocks porting Highway kernels op-for-op)

Open
#115 2 comments 0 reactions 1 assignee View on GitHub

@lilith is already working on this.

Since Sep 10, 2026.

Dominant language
Rust
Stars
12
Forks
2
Avg merge
13h 55m
Merged PRs (30d)
28

Description

## What's missing

`magetypes::simd::generic::f32x4` / `f32x8` expose no equivalent of Highway's:

- **`Broadcast(v)`** — splat lane `N` across the vector (`vdupq_laneq_f32` on
NEON, `vpermilps`/`vbroadcastss` on x86, `i32x4.shuffle` on wasm)
- **`ShiftLeftLanes(v)`** — shift lanes toward higher indices, zero-filling
(`vextq_f32` against a zero vector on NEON, `vpslldq` on x86)

The f32x4 surface today has `interleave_lo/hi`, `transpose_4x4`, `blend`,
`reduce_*`, but nothing that selects or shifts *lanes* by a compile-time index.

## Why it matters (concrete case)

I was porting jpegli/libjxl's `FastGaussian1D` — the horizontal recursive
Gaussian that SSIMULACRA2 uses — into fast-ssim2, to check whether its form is
faster than ours (it is: 12-14% on NEON). The C++ inner loop is built out of
exactly these two ops:

```cpp
const V in1 = Broadcast<1>(sum);
out_1 = MulAdd(ShiftLeftLanes<1>(mul_in_1), in1, out_1);
```

With `magetypes` the only way to express that is `to_array()` + `splat()`, which
round-trips through memory and measures the emulation rather than the algorithm.

I got around it for this kernel — the shifted coefficient vectors are
loop-invariant, so they can be precomputed as constants, and each input can be
splatted from a scalar load instead of broadcast out of a vector — but that
dodge is specific to this shape. Any kernel that broadcasts a *computed* lane
(this one also carries its IIR state out of lanes 2 and 3 of the previous
result) has nowhere to go.

## Suggested shape

```rust
impl f32x4 {
pub fn broadcast_lane(self) -> Self;
pub fn shift_left_lanes(self) -> Self; // zero-fill
}
```

matching the existing `shr_arithmetic_const::` convention on the integer
types. Same for `f32x8` / `f32x16` (Highway's `Broadcast` is per-128-bit-block;
worth deciding explicitly whether ours is block-wise or whole-vector, since
that's a portability trap either way).

## Not a complaint about priorities

`magetypes` covered everything else this port needed — `bitcast_to_i32`,
`shr_arithmetic_const::<23>`, integer multiply, `blend`, `simd_eq` — which is
how the cube-root half went in cleanly. This is one gap, found by trying to
transliterate someone else's SIMD kernel op-for-op, which is a slightly unusual
thing to ask of a portable-SIMD layer.

Context and measurements: imazen/fast-ssim2 `benchmarks/cbrt_perf_2026-09-09.md`
and `benchmarks/blur_stride_2026-09-09.md`.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.