code: def _gemm_canonicalize(fgraph, r, scale, rval, maxclients):
      # Tries to interpret node as a sum of scalars * (vectors or matrices)
      def scaled(thing):
          if scale == 1:
              return thing
          if scale == -1 and thing.type.dtype != "bool":
              return -thing
          else:
              return scale * thing
  
      if not isinstance(r.type, TensorType):
          return None
  
      if (r.type.ndim not in (1, 2)) or r.type.dtype not in (
          "float16",
          "float32",
          "float64",
          "complex64",
          "complex128",
      ):
          rval.append(scaled(r))
          return rval
  
      if maxclients and len(fgraph.clients[r]) > maxclients:
          rval.append((scale, r))
          return rval
  
      if r.owner and r.owner.op == sub:
          _gemm_canonicalize(fgraph, r.owner.inputs[0], scale, rval, 1)
          _gemm_canonicalize(fgraph, r.owner.inputs[1], -scale, rval, 1)
  
      elif r.owner and r.owner.op == add:
          for i in r.owner.inputs:
              _gemm_canonicalize(fgraph, i, scale, rval, 1)
  
      elif r.owner and r.owner.op == neg:
          _gemm_canonicalize(fgraph, r.owner.inputs[0], -scale, rval, 1)
  
      elif r.owner and r.owner.op == mul:
          scalars = []
          vectors = []
          matrices = []
          for i in r.owner.inputs:
              if all(s == 1 for s in i.type.shape):
                  while i.owner and isinstance(i.owner.op, DimShuffle):
                      i = i.owner.inputs[0]
                  if i.type.ndim > 0:
                      scalars.append(i.dimshuffle())
                  else:
                      scalars.append(i)
              elif _is_real_vector(i):
                  vectors.append(i)
              elif _is_real_matrix(i):
                  matrices.append(i)
              else:
                  # just put the original arguments as in the base case
                  rval.append((scale, r))
                  return rval
          if len(matrices) == 1:
              assert len(vectors) == 0
              m = matrices[0]
              if len(scalars) == 0:
                  _gemm_canonicalize(fgraph, m, scale, rval, 1)
              elif len(scalars) == 1:
                  _gemm_canonicalize(
                      fgraph, m, scaled(scalars[0]), rval, 1
                  )
              else:
                  _gemm_canonicalize(
                      fgraph,
                      m,
                      mul(scaled(scalars[0]), *scalars[1:]),
                      rval,
                      1,
                  )
          elif len(vectors) == 1:
              assert len(matrices) == 0
              v = vectors[0]
              if len(scalars) == 0:
                  _gemm_canonicalize(fgraph, v, scale, rval, 1)
              elif len(scalars) == 1:
                  _gemm_canonicalize(
                      fgraph, v, scaled(scalars[0]), rval, 1
                  )
              else:
                  _gemm_canonicalize(
                      fgraph,
                      v,
                      mul(scaled(scalars[0]), *scalars[1:]),
                      rval,
                      1,
                  )
          else:  # lets not open this up
              rval.append((scale, r))
      else:
          rval.append((scale, r))
      return rval
  
imports: import copy
  import logging
  import time
  import numpy
  from pytensor.tensor.rewriting.basic import register_specialize
  import pytensor.scalar
  from pytensor.compile.mode import optdb
  from pytensor.configdefaults import config
  from pytensor.graph.features import ReplacementDidNotRemoveError, ReplaceValidate
  from pytensor.graph.rewriting.basic import EquilibriumGraphRewriter, GraphRewriter, copy_stack_trace, in2out, node_rewriter
  from pytensor.graph.rewriting.db import SequenceDB
  from pytensor.graph.utils import InconsistencyError
  from pytensor.tensor import basic
  from pytensor.tensor.blas import Dot22, _dot22, _dot22scalar, batched_dot, gemm_inplace, gemm_no_inplace, gemv_inplace, gemv_no_inplace, ger, ger_destructive
  from pytensor.tensor.elemwise import DimShuffle, Elemwise
  from pytensor.tensor.exceptions import NotScalarConstantError
  from pytensor.tensor.math import Dot, _matrix_matrix_matmul, add, mul, neg, sub
  from pytensor.tensor.rewriting.elemwise import local_dimshuffle_lift
  from pytensor.tensor.type import DenseTensorType, TensorType, integer_dtypes, values_eq_approx_remove_inf_nan
label_desc: Use image node_id 6 for calling a global function with example usage: _gemm_canonicalize(fgraph, r, scale, rval, maxclients) and returns: rval, None, rval, rval, thing, unknown, unknown, rval