tensor: elementwise operations with broadcasting (slice 2 of #82) #772

Closed
opened 2026-11-13 23:03:08 +00:00 by orion · 7 comments
Collaborator

Context

Slice 2 of the std/tensor epic #82, from TENSOR.md section 11. Slice 1 (#691, PR #695) is on main: Tensor<Scalar> over a Buffer with shape, strides, construction, indexing, Iterate, Show, Equals.

Goal

Elementwise operations with broadcasting on Tensor<Scalar>: Add, Subtract, Multiply<Scalar>, Divide<Scalar>, Negate, scaled, divided, shifted, mapped, broadcast(to:), the shape errors (decision 13: a mismatch panics with the extents named) and the predicates canBroadcastWith and Tensor.broadcastShape. Broadcasting is NumPy's rule (decision 12), no operand is materialised for the view.

Design record

  • TENSOR.md sections 5 and 6 (decisions 10, 12, 13, 14), the cost table (section 10) rows tensor-add and tensor-add-broadcast.

Acceptance criteria

  • Every member above exists with the signature of TENSOR.md section 8; a + b of shapes that do not broadcast panics with the message form of decision 13; canBroadcastWith and Tensor.broadcastShape answer the same question without the stop.
  • A zero extent broadcasts with 1 and 0 only (invariant I3 and the example in section 4 hold); a broadcast(to:) view is the one place a stride 0 on a longer axis appears.
  • Tests in both back ends: accept and reject cases for ranks 0 to 3, Float64, Int and Fixed scalars, the shape-error text.
  • Gates tensor-add (within 1.10 of the hand-written loop) and tensor-add-broadcast (within 1.25) are added and green in forge CI; the TENSOR.md cost table filled in; docs page of std/tensor updated and skills/ regenerated.
  • sh tools/gates.sh a green in forge CI, tools/check-commits.sh clean.

Seed impact

None expected (ordinary TorbScript); the worker confirms against CLAUDE.md "Seed and breaking changes" first.

Size

One PR, one Conventional Commit (feat(tensor): elementwise operations with broadcasting). Part of #82 (epic; do not close it).

## Context Slice 2 of the `std/tensor` epic #82, from [TENSOR.md section 11](https://git.torb.dev/torbscript/language/src/branch/main/docs/design/TENSOR.md). Slice 1 (#691, PR #695) is on `main`: `Tensor<Scalar>` over a `Buffer` with shape, strides, construction, indexing, `Iterate`, `Show`, `Equals`. ## Goal Elementwise operations with broadcasting on `Tensor<Scalar>`: `Add`, `Subtract`, `Multiply<Scalar>`, `Divide<Scalar>`, `Negate`, `scaled`, `divided`, `shifted`, `mapped`, `broadcast(to:)`, the shape errors (decision 13: a mismatch panics with the extents named) and the predicates `canBroadcastWith` and `Tensor.broadcastShape`. Broadcasting is NumPy's rule (decision 12), no operand is materialised for the view. ## Design record - TENSOR.md sections 5 and 6 (decisions 10, 12, 13, 14), the cost table (section 10) rows `tensor-add` and `tensor-add-broadcast`. ## Acceptance criteria - [ ] Every member above exists with the signature of TENSOR.md section 8; `a + b` of shapes that do not broadcast panics with the message form of decision 13; `canBroadcastWith` and `Tensor.broadcastShape` answer the same question without the stop. - [ ] A zero extent broadcasts with 1 and 0 only (invariant I3 and the example in section 4 hold); a `broadcast(to:)` view is the one place a stride 0 on a longer axis appears. - [ ] Tests in both back ends: accept and reject cases for ranks 0 to 3, `Float64`, `Int` and `Fixed` scalars, the shape-error text. - [ ] Gates `tensor-add` (within 1.10 of the hand-written loop) and `tensor-add-broadcast` (within 1.25) are added and green in forge CI; the TENSOR.md cost table filled in; docs page of `std/tensor` updated and `skills/` regenerated. - [ ] `sh tools/gates.sh a` green in forge CI, `tools/check-commits.sh` clean. ## Seed impact None expected (ordinary TorbScript); the worker confirms against `CLAUDE.md` "Seed and breaking changes" first. ## Size One PR, one Conventional Commit (`feat(tensor): elementwise operations with broadcasting`). Part of #82 (epic; do not close it).
Author
Collaborator

[loop:torbscript] claim implement by session:loop-torbscript-20261114 until 2026-11-14T06:00:00Z

[loop:torbscript] claim implement by session:loop-torbscript-20261114 until 2026-11-14T06:00:00Z
Author
Collaborator

[loop:torbscript] implement: claim released (worker run timed out). PR #773 is open at c12079f5, CI jobs still pending (runner queue). next: review (argus) once CI is green; a red CI is repaired on the same branch by the next tick.

[loop:torbscript] implement: claim released (worker run timed out). PR #773 is open at c12079f5, CI jobs still pending (runner queue). next: review (argus) once CI is green; a red CI is repaired on the same branch by the next tick.
Author
Collaborator

[loop:torbscript] claim implement by session:loop-torbscript-20261114 until 2026-11-14T06:56:00Z

[loop:torbscript] claim implement by session:loop-torbscript-20261114 until 2026-11-14T06:56:00Z
Author
Collaborator

[loop:torbscript] implement: PR #773 is on head 8636dab2. The pdisc / pdisc check failed because benchmarks/README.md changed (the tensor-add rows) without a restamp; stamped it in 9957eb06 and the check is green now. Reading the diff against the acceptance criteria found three more things, fixed in 8636dab2: the tensor-broadcast-panic.stderr named line 10 (the canBroadcastWith line) while the panic is raised on line 11, the TENSOR.md cost-table row for tensor-add said Float64 while the measurement uses Int, and ranks 0 to 2 had tests but rank 3 had none (added "shapes of rank 3 broadcast on every axis" for Float64, Int and Fixed). CI state: pdisc, commit messages and what the change touches are green; ci / gates, tier A/B, bootstrap, conformance and the other jobs were still queued behind the runner backlog after ~30 min, so nothing has compiled yet. Unverified: no torb binary exists locally, so the std code, the tests, the benchmarks, the 1.10/1.25 ratios, the panic column (8, taken from the precedent that a panic names the start of the binary expression) and the doc examples are all untested; the ratios are recorded by tools/tensor-cost.sh (a measurement, like the slice-1 pairs), not enforced as gates. next: waiting (forge CI running on 8636dab2; fix round if a job goes red, otherwise merge gate argus, who is the requested reviewer on #773).

[loop:torbscript] implement: PR #773 is on head 8636dab2. The `pdisc / pdisc` check failed because `benchmarks/README.md` changed (the tensor-add rows) without a restamp; stamped it in 9957eb06 and the check is green now. Reading the diff against the acceptance criteria found three more things, fixed in 8636dab2: the `tensor-broadcast-panic.stderr` named line 10 (the `canBroadcastWith` line) while the panic is raised on line 11, the TENSOR.md cost-table row for `tensor-add` said `Float64` while the measurement uses `Int`, and ranks 0 to 2 had tests but rank 3 had none (added "shapes of rank 3 broadcast on every axis" for Float64, Int and Fixed). CI state: `pdisc`, `commit messages` and `what the change touches` are green; `ci / gates`, tier A/B, bootstrap, conformance and the other jobs were still queued behind the runner backlog after ~30 min, so nothing has compiled yet. Unverified: no `torb` binary exists locally, so the std code, the tests, the benchmarks, the 1.10/1.25 ratios, the panic column (8, taken from the precedent that a panic names the start of the binary expression) and the doc examples are all untested; the ratios are recorded by `tools/tensor-cost.sh` (a measurement, like the slice-1 pairs), not enforced as gates. next: waiting (forge CI running on 8636dab2; fix round if a job goes red, otherwise merge gate argus, who is the requested reviewer on #773).
Author
Collaborator

[loop:torbscript] claim review-fix by session:loop-torbscript-20261114 until 2026-11-14T05:49:00Z

[loop:torbscript] claim review-fix by session:loop-torbscript-20261114 until 2026-11-14T05:49:00Z
Author
Collaborator

[loop:torbscript] review-fix: PR #773 head e5095968 shows pdisc / pdisc failing (12 s, 03:27Z). next: a worker reads the check output, restamps or fixes the doc front matter on the branch.

[loop:torbscript] review-fix: PR #773 head e5095968 shows `pdisc / pdisc` failing (12 s, 03:27Z). next: a worker reads the check output, restamps or fixes the doc front matter on the branch.
Author
Collaborator

[loop:torbscript] review-fix: new head a85e22a0. pdisc failed because .pdisc-sidecar.yaml had entries for docs/standard-library/tensor.md and its skills mirror, which .pdisc.yaml excludes (docs/, skills/), so "entry has no file". Removed both entries in docs(pdisc): drop sidecar entries for the excluded std/tensor pages; python3 -I tools/pdisc/scripts/pdisc.py check passes and check-commits.sh passes. next: wait for CI, then review (argus)

[loop:torbscript] review-fix: new head a85e22a0. pdisc failed because .pdisc-sidecar.yaml had entries for docs/standard-library/tensor.md and its skills mirror, which .pdisc.yaml excludes (docs/*, skills/*), so "entry has no file". Removed both entries in `docs(pdisc): drop sidecar entries for the excluded std/tensor pages`; python3 -I tools/pdisc/scripts/pdisc.py check passes and check-commits.sh passes. next: wait for CI, then review (argus)
argus closed this issue 2026-11-14 09:38:28 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language#772
No description provided.