code: def local_dot22_to_ger_or_gemv(fgraph, node):
      """dot22 computing an outer-product -> GER."""
      if node.op == _dot22:
          x, y = node.inputs
          xb = x.broadcastable
          yb = y.broadcastable
          one = ptb.as_tensor_variable(np.asarray(1, dtype=x.dtype))
          zero = ptb.as_tensor_variable(np.asarray(0, dtype=x.dtype))
          if xb[1] and yb[0]:
              # x and y are both vectors so this might qualifies for a GER
              xv = x.dimshuffle(0)
              yv = y.dimshuffle(1)
              zeros = ptb.zeros([x.shape[0], y.shape[1]], dtype=x.dtype)
              rval = ger(zeros, one, xv, yv)
              new_out = [rval]
          elif xb[0] and yb[1]:
              # x and y are both vectors so this qualifies for a sdot / ddot
              # TODO: PyTensor doesn't have a sdot, but gemv is better than _dot22
              xv = x.dimshuffle(1)
              zeros = ptb.AllocEmpty(x.dtype)(1)
              rval = gemv_no_inplace(zeros, one, y.T, xv, zero)
              new_out = [rval.dimshuffle("x", 0)]
          elif xb[0] and not yb[0] and not yb[1]:
              # x is vector, y is matrix so try gemv
              xv = x.dimshuffle(1)
              zeros = ptb.AllocEmpty(x.dtype)(y.shape[1])
              rval = gemv_no_inplace(zeros, one, y.T, xv, zero)
              new_out = [rval.dimshuffle("x", 0)]
          elif not xb[0] and not xb[1] and yb[1]:
              # x is matrix, y is vector, try gemv
              yv = y.dimshuffle(0)
              zeros = ptb.AllocEmpty(x.dtype)(x.shape[0])
              rval = gemv_no_inplace(zeros, one, x, yv, zero)
              new_out = [rval.dimshuffle(0, "x")]
          else:
              return
          copy_stack_trace(node.outputs, new_out)
          return new_out
  
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 16 for calling a global function with example usage: local_dot22_to_ger_or_gemv(fgraph, node) and returns: new_out