Skip to content

onnx: re-land #89 — Pad (4 modes), Cast, Shrink, OneHot (merge-order casualty) - #90

Merged
sbryngelson merged 1 commit into
mainfrom
onnx/tier2-ops
Jul 22, 2026
Merged

onnx: re-land #89 — Pad (4 modes), Cast, Shrink, OneHot (merge-order casualty)#90
sbryngelson merged 1 commit into
mainfrom
onnx/tier2-ops

Conversation

@sbryngelson

Copy link
Copy Markdown
Owner

#89 shows as merged but its diff never reached main: it was merged into the onnx/tier1-coverage branch 42 seconds after #88 had already squash-merged that branch to main, and the branch was then deleted — the classic stacked-PR ordering trap (the stack needed #88's branch deletion to retarget #89 before merging it). This PR re-lands the identical commit, rebased onto current main.

Content is exactly #89's (see its description for the full write-up): Pad (constant/edge/reflect/wrap, with the nested-2-part-concat workaround for the Espresso lowering quirk), import-level Cast, Shrink, OneHot, and the documented boolean/IsNaN hardware boundary in docs/onnx.md. Registered op names 100 → 104.

Re-verified after rebase, on-device (M5): pytest tests/test_onnx.py — 154 passed.

…rdware wall

Pad lowers each padded axis to concats: const border blocks (constant),
repeated edge slices (edge), reversed interior slices (reflect), or the
opposite end (wrap); constants fold via np.pad. Probing on-device found an
Espresso quirk: a 3-part concat with two const borders fails to lower once
a second padded axis stacks on top, while nested 2-part concats compile
and are bit-exact - constant mode builds pairwise concats for that reason.

Cast folds constants, treats float->float on an activation as identity
(the engine computes fp16 regardless), and lowers float->int as
sign(x)*floor(|x|) (toward-zero, exact in fp16 integer range). Shrink is
a nested select against baked thresholds. OneHot compares the index
tensor against a baked arange along the inserted axis and selects on/off
values; the constant path implements full ONNX wrap/out-of-range
semantics.

And/Or/Xor and IsNaN are deliberately NOT added, with evidence: the MIL
vocabulary sweep shows logical_and/or/xor and general cast are not
implemented on the ANE backend (probed again today - the type system
rejects arithmetic on bool and select requires same-dtype branches), and
an fp16 NaN fed on-device reads x != x as false, so IsNaN would be
silently wrong. docs/onnx.md now records this boundary.

154 tests pass on-device (M5); Pad checks all four modes against
onnxruntime, Cast/Shrink/OneHot likewise (OneHot feeds int64 to ORT,
fp16-encoded indices to the engine).
@sbryngelson
sbryngelson merged commit 6e1697b into main Jul 22, 2026
13 checks passed
@sbryngelson
sbryngelson deleted the onnx/tier2-ops branch July 22, 2026 22:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant