Closes#1244
## Summary
- Bake the scalar `alpha` multiplier into `AddFwdKernel` /
`SubFwdKernel` at construction time so `AddFwdOp(alpha=k)` and
`SubFwdOp(alpha=k)` for `k != 1` dispatch to a real kernel instead of
raising `NotImplementedError`.
- Scalar multiply runs in fp32 (per code-style: no narrow-type literal
casts) and casts back to storage dtype at the boundary; `alpha == 1`
keeps the original `op_func` to preserve the integer-dtype fast path
byte-identically.
- Removes the `NotImplementedError` raise in
`tileops/ops/elementwise/arithmetic.py` for the `alpha != 1` path.
## Scope (kernel-only PR)
Per [`docs/design/trust-model.md`](docs/design/trust-model.md), this PR
touches only `tileops/kernels/` and `tileops/ops/elementwise/`. Test and
benchmark additions for the new `alpha != 1` path are deferred to a
sibling PR owned by the `tests/` and `benchmarks/` layers respectively.
- AC-1 / AC-2 (kernel correctness): verified in this PR.
- AC-3 (per-dtype correctness tests for `alpha != 1`): deferred to a
sibling test-layer PR.
- AC-4 (benchmark entry at LLaMA workload): deferred to a sibling
benchmark-layer PR.
## Test plan
- [x] AC-1: `pytest tests/ops/test_binary_arith.py` — 120 passed
(existing `alpha=1` fast path, no regression).
- [x] AC-1: `pytest tests/test_validate_manifest.py` — 218 passed.
- [x] AC-2: `AddFwdOp` / `SubFwdOp` × {fp32, fp16, bf16} × `alpha ∈ {1,
2, -1, 0.5}` — 24/24 cases match `torch.add` / `torch.sub` with `max_err
= 0.0` (kernel compile log confirms TileLang dispatch per `(op, dtype,
alpha)` specialization, no `NotImplementedError`, no torch passthrough).
- [ ] AC-3: per-dtype correctness tests for `alpha != 1` — deferred to
sibling tests-layer PR.
- [ ] AC-4: benchmark entry at LLaMA workload for `alpha != 1` —
deferred to sibling benchmarks-layer PR.
---------
Co-authored-by: Ibuki 🍃 — a wind born from GPTs <Ibuki-wind@users.noreply.github.com>
Closes#1378
## Summary
- Replaced 3415-line monolith `tileops/ops/elementwise.py` with a
`tileops/ops/elementwise/` package, one module per cluster (16 cluster
modules + `_base.py`).
- Umbrella classes `UnaryOp`, `BinaryOp`, `FusedGatedOp` moved to
`_base.py`; `__init__.py` re-exports every previously-public symbol via
explicit `__all__`.
- Pure file-layout move: no class signature, docstring, or
kernel-binding changes; all 295 elementwise tests pass; no file-level
lint suppressions introduced.
- Pyright shows pre-existing typing issues in the relocated code that
were carried over verbatim from the original file — out of scope to fix
in this refactor.
## Test plan
- [x] AC-1: Modified files pass unit tests (pytest tests/ops/).
- [x] AC-2: tileops/ops/elementwise.py no longer exists;
tileops/ops/elementwise/ is a package with __init__.py.
- [x] AC-3: python -c "from tileops.ops.elementwise import UnaryOp,
BinaryOp, FusedGatedOp" succeeds.
- [x] AC-4: python -c "from tileops.ops.elementwise import
SiluAndMulFwdOp, ReluFwdOp, AddFwdOp, ExpFwdOp, DivFwdOp" succeeds.
- [x] AC-5: tests/ops/test_elementwise_fp8.py passes without
modification to its imports.
- [x] AC-6: grep -nE '^# ruff:|^# flake8:' tileops/ops/elementwise/
returns nothing.
- [x] AC-7: External tracker flip — out of scope.
---------
Co-authored-by: Ibuki 🍃 — a wind born from GPTs <Ibuki-wind@users.noreply.github.com>