| Question | Choice here | Where | |||
|---|---|---|---|---|---|
| Accumulation order and width | sequential from index 0, saturate per step, accumulator at data width (v1); attributes of the target, read by the reference | _linalg.py, _device.Device | |||
sum(axis=None) order | C order over the flattened array, sequential | _array.sum_ | |||
addmm(a, b, d) | the @ chain first, then one saturating add of d (not d as the initial accumulator; the two differ under saturation). Confirm against __sf16_mat_fma | _array.addmm | |||
| Event order on arrays | catalogue order: invalid, divide, overflow, underflow; the first in that order with a raise policy is raised. dot (single output) reports the first event in time, like the scalar chain | _array._handle_events, _array.dot | |||
a * b + c vs sf.fma on arrays | same bits always; the fused form may report an overflow before an underflow elsewhere in the array, the two-step form the reverse | _vectorized.fma | |||
sf.ones | 1 is not representable, so it follows the literal rule: raises by default, saturates under over="ignore"; the message points at sf.full(shape, sf.info(dt).max, dt) | _functions.ones | |||
sf.div(a, b, where=mask) | elements where the mask is False are 0 and raise nothing | _functions.div | |||
Strings in sf.array([...]) | accepted (constructor rule), rejected as operator literals | _array._to_codes | |||
| Heavy-op underflow | not reported on v1 (no flags); only saturation, div0 and invalid (from inputs) | _array._run_heavy | |||
status.saturated | exact when the bound proved safety, when the target returns flags, or under sf.config(status="replay"); otherwise an upper bound (scan of ±max) for elementwise ops and None (unknown) for reductions, with outputs_at_max always reported | _array._run_heavy, _status.py | |||
| Probe hit | suspected, never certain; `sf.config(suspect=“warn”\ | “raise”\ | “verify”\ | “ignore”)decides. Only a host proof (range bound, or exact replay underverify) can refuse a launch as certain` | _preflight.decide |
Device.run contract | returns (codes, flags); flags is None for v1 and a dict of event masks for a target with sticky flags; trusted only when sticky_flags is True | _device.Device | |||
Masked sf.div on device arrays | heavy: masked-out elements become 0 / 1 (exact 0, no event) and the gate sees only the live elements | _functions.div, _preflight._live | |||
| Selection ops on device arrays | maximum, minimum, clip, where, cast, indexing run on the host and return device-labelled arrays with no status (data movement, not kernels) | _functions.py | |||
Mixed placement (host @ device) | heavy; the host operand is sent along. Two different devices is an error | _array._device_of | |||
| Probe policy | the matmul probe samples random rows and columns plus the largest-magnitude ones; elementwise probes sample elements plus the extremes. sf.config(probe=False) disables it | _preflight.probe | |||
| 0-d results | host ops that produce a 0-d result return an SF scalar; heavy ops always return an array (it carries the status) | _array._result |
Design decisions
Stage 1.1 decisions
Decision log: stage 1.1 decisions