Skip to content

sgnts.transforms.matmul

Matmul dataclass

Bases: TSTransform


              flowchart TD
              sgnts.transforms.matmul.Matmul[Matmul]
              sgnts.base.base.TSTransform[TSTransform]
              sgnts.base.base.TimeSeriesMixin[TimeSeriesMixin]

                              sgnts.base.base.TSTransform --> sgnts.transforms.matmul.Matmul
                                sgnts.base.base.TimeSeriesMixin --> sgnts.base.base.TSTransform
                



              click sgnts.transforms.matmul.Matmul href "" "sgnts.transforms.matmul.Matmul"
              click sgnts.base.base.TSTransform href "" "sgnts.base.base.TSTransform"
              click sgnts.base.base.TimeSeriesMixin href "" "sgnts.base.base.TimeSeriesMixin"
            

Performs matrix multiplication with provided matrix.

Parameters:

Name Type Description Default
matrix Array

Array, the matrix to multiply the data with, out = matrix x data

required
Notes

Thread safety: Marked thread_safe = True. With Pipeline.run(threaded=N) the pad callbacks for this element are dispatched onto worker threads.

Pad layout: 1 sink + 1 source pad
(enforced by ``@transform.one_to_one``). No same-element
``pull``/``new`` concurrency. ``internal`` runs alone.

Where the GIL-releasing work lives: ``internal()`` →
``process()`` performs the matrix multiply via ``xp.matmul``
(NumPy/BLAS or Torch), which releases the GIL during the BLAS call.
Significant speedup expected for large matrices in
multi-branch graphs.

State touched per call:

- ``pull`` (inherited): per-pad-keyed dict writes; OR's
  ``self.at_EOS``.
- ``new`` (inherited): read-only lookup in ``self.outframes``.
- ``process``: reads ``self.matrix`` and ``self.shape`` (set
  in ``configure()``, read-only afterwards); writes only
  the local output buffer.

**Future editors MUST preserve thread safety**: do not
relax the one-to-one constraint without re-auditing
``self.matrix`` access. Keep ``process`` purely functional
on its inputs.
Source code in src/sgnts/transforms/matmul.py
@dataclass(kw_only=True)
class Matmul(TSTransform):
    """Performs matrix multiplication with provided matrix.

    Args:
        matrix:
            Array, the matrix to multiply the data with, out = matrix x data

    Notes:
        Thread safety:
            Marked ``thread_safe = True``. With
            ``Pipeline.run(threaded=N)`` the pad callbacks for this
            element are dispatched onto worker threads.

            Pad layout: 1 sink + 1 source pad
            (enforced by ``@transform.one_to_one``). No same-element
            ``pull``/``new`` concurrency. ``internal`` runs alone.

            Where the GIL-releasing work lives: ``internal()`` →
            ``process()`` performs the matrix multiply via ``xp.matmul``
            (NumPy/BLAS or Torch), which releases the GIL during the BLAS call.
            Significant speedup expected for large matrices in
            multi-branch graphs.

            State touched per call:

            - ``pull`` (inherited): per-pad-keyed dict writes; OR's
              ``self.at_EOS``.
            - ``new`` (inherited): read-only lookup in ``self.outframes``.
            - ``process``: reads ``self.matrix`` and ``self.shape`` (set
              in ``configure()``, read-only afterwards); writes only
              the local output buffer.

            **Future editors MUST preserve thread safety**: do not
            relax the one-to-one constraint without re-auditing
            ``self.matrix`` access. Keep ``process`` purely functional
            on its inputs.
    """

    thread_safe = True

    # matmul is a standard-xp op; works in any namespace.
    backends = ANY_BACKEND

    matrix: Array

    def configure(self) -> None:
        self.shape = self.matrix.shape

    @validator.one_to_one
    def validate(self) -> None:
        pass

    def output_prototype(self, pad: SourcePad) -> Array:
        # out = matrix @ data promotes dtypes (result_type(matrix, input));
        # multiplying zero-length examples promotes identically, so even
        # all-gap output frames carry the promoted dtype.
        xp = array_namespace(self.matrix)
        assert xp is not None
        matrix_proto = xp.reshape(self.matrix, (-1,))[:0]
        return matrix_proto * self.input_prototype(self.sink_pads[0].pad_name)

    @transform.one_to_one
    def process(self, input_frame: TSFrame, output_frame: TSCollectFrame) -> None:
        """Perform matrix multiplication on non-gap data."""
        for buf in input_frame:
            if buf.is_gap:
                data = None
                shape = self.shape[:-1] + (buf.samples,)
            else:
                xp = array_namespace(buf.data)
                assert xp is not None
                data = xp.matmul(self.matrix, buf.data)
                shape = data.shape

            buf = buf.copy(data=data, shape=shape)
            output_frame.append(buf)

process(input_frame, output_frame)

Perform matrix multiplication on non-gap data.

Source code in src/sgnts/transforms/matmul.py
@transform.one_to_one
def process(self, input_frame: TSFrame, output_frame: TSCollectFrame) -> None:
    """Perform matrix multiplication on non-gap data."""
    for buf in input_frame:
        if buf.is_gap:
            data = None
            shape = self.shape[:-1] + (buf.samples,)
        else:
            xp = array_namespace(buf.data)
            assert xp is not None
            data = xp.matmul(self.matrix, buf.data)
            shape = data.shape

        buf = buf.copy(data=data, shape=shape)
        output_frame.append(buf)