Switch / Router

Shipping
switch

Element-wise IF/ELSE data router: forward A or B per sample based on a control criteria

Signature

Inputs

  • aScalar|SignalBranch forwarded where the criteria holds (falls back to the `a` params when unwired).
  • controlScalar|SignalSelector tested against `threshold` each sample (falls back to 0 when unwired).
  • bScalar|SignalBranch forwarded where the criteria fails (falls back to the `b` params when unwired).

Outputs

  • resultScalar|SignalSignal if any input is a Signal, else Scalar. Expressed in A's unit (B's when A is unitless).

Parameters

KeyTypeDefaultNotes
criteriaenumgtone of: gt, ge, lt, le, nonzero
thresholdfloat0.5(unit of control)Control level the criteria compares against. Ignored for the `nonzero` (control ≠ 0) criteria.
align_modeenumautoone of: auto, elementwise, timewise
time_baseenumunionone of: union, finest, first
interp_methodenumlinearone of: linear, nearest, previous, cubic
afloat1.0Value forwarded as branch A when its port has no wire.
a_unitunitUnit of the A fallback. The output is expressed in this unit.
a_sigmafloat0.0Standard uncertainty of the A fallback.
bfloat0.0Value forwarded as branch B when its port has no wire.
b_unitunitUnit of the B fallback (converted into A's unit for the output).
b_sigmafloat0.0Standard uncertainty of the B fallback.
controlfloat0.0Control value used when the control port has no wire.

Description

Switch is the dataflow-idiomatic conditional: for every sample it forwards either the A branch or the B branch depending on whether the control input satisfies a criteria against a threshold. It is the consumer half of the conditional toolkit — the boolean/analog control stream is usually produced upstream by a comparator, logic_gate, or schmitt_trigger, and Switch turns that control into a routed value: .

The output is a Signal when any of A / control / B is a Signal, otherwise a plain Scalar. Scalars broadcast over the signal length; when two or more inputs are signals on the same grid they pair by index and truncate to the shortest (the math_operator default). When signals live on different time grids, the align_mode decides: Auto resamples by time only when grids differ, Time-wise always resamples onto a common grid — so the selection is by time, not by sample index.

Units are handled physically: the output is expressed in A's unit (or B's when A is unitless), and the other branch is affinely converted into that unit, so a / or / mix routes the correct magnitudes. A dimensionally incompatible (or logarithmic dB) branch raises a node warning and is mixed at raw magnitude — never a silent wrong physics.

Uncertainty propagation is honest. With an exact control (the common comparator/logic case) the result at sample is exactly the chosen branch's sample, so its variance is exactly that branch's variance (scaled by the unit conversion factor²) — a bit-identical hard pick. With an uncertain control, a pick near the threshold is no longer a sharp choice: it is a Bernoulli mixture of the two branches, so Switch collapses it to its first two moments — the mean is a soft blend by the selection probability , and the variance gains the between-branch spread a hard pick would drop. Being a non-affine gate, the σ-lineage is re-entered as a fresh source (like FFT / IIR) while the per-sample σ² is carried faithfully.

Unwired ports fall back to their scalar params (a / a_unit / a_sigma, b / …, control), so a Switch fed only a control still routes between two configured constants.

Mathematics

Examples

Boolean-controlled routing per sample

A comparator emits a 1.0/0.0 control stream. Wire it into control, signal A into a, signal B into b, leave criteria = gt and threshold = 0.5.

a       = [10, 11, 12]
control = [ 1,  0,  1]   (> 0.5 ⇒ pick A)
b       = [-1, -2, -3]
result  = [10, -2, 12]

Mixed-unit branches route correct magnitudes

Branch A is in , branch B in . At a sample where the control selects B, the value is affinely converted into A's unit and read as . The output unit is .

Soft blend under an uncertain control

Control sits exactly at the threshold () with , so . Branches are exact at and . The moment-matched mean is , and the variance is — capturing the between-branch spread a hard pick would have discarded.

Applications

  • Routing between a nominal and a fallback signal path based on a fault flag or comparator output.
  • Building setpoint / mode logic: select between two control references depending on an operating-region test.
  • Gating a signal on/off by wiring a boolean control and a zero (or hold) constant into the two branches.
  • Bumpless switchover between two estimators or filters where the control carries measurement uncertainty (soft blend avoids a hard discontinuity).

Neat

The same `select_mask` rule that Switch consumes is shared with the comparator/logic family, so producer and consumer can never disagree on what a criteria means.

An exact control takes a bit-identical hard path (verbatim branch value AND variance), while an uncertain control automatically upgrades to Level-1 moment-matching — the node adapts its own physics to whether the decision is sharp.

Unit alignment reuses the affine `(factor, offset)` map, so temperature offsets (°C↔K) route correctly, not just linear scale factors — and a logarithmic dB unit is refused rather than silently linearised.

Time-wise alignment lets you route between signals sampled at different rates over the same span, selecting by wall-clock time instead of by sample index.

Known issues

Element-wise combination truncates all signal operands to the shortest; a longer branch's tail is silently dropped unless time-wise alignment is used.

A dimensionally incompatible branch unit is not converted — it is routed at raw magnitude with only a warning, so a mis-typed unit yields numerically plausible but physically wrong output.

The selection gate is non-affine, so the output re-enters its uncertainty as a fresh source (the σ-lineage across the node is not preserved for downstream correlation tracking).

See also

control-flowrouterconditionalselectmultiplexerif-elsestateless