class_docstr: Perform N-D batch matrix multiplication with NumPy-style broadcasting
  based on the following rules:
  
  Rule 1. If both ``x, y`` are 1-D, return the scalar from the dot product.
  
  Rule 2. If both ``x, y`` are 2-D or higher, perform a broadcast on the batch dimensions
  (all dimensions except the last ``2``).
  
  For example:
  
  * ``x.shape == (10, 4, 3)``
  * ``y.shape == (5, 10, 3, 2)``
  * ``matmul(x, y).shape == (5, 10, 4, 2)``
  
  Conventional matrix multiplication is a special case where both ``x, y`` are
  exactly 2-D. For example:
  
  * ``x.shape == (4, 3)``
  * ``y.shape == (3, 2)``
  * ``matmul(x, y).shape == (4, 2)``
  
  If ``x`` is 1-D, and ``y`` is N-D where ``N >= 2``, ``x`` is first promoted to
  matrix ``xm`` by prepending a ``1`` to its dimension, and the resulting ``xm`` is
  broadcast to ``y`` following Rule 2 above. After this, remove the inserted dimension.
  For example:
  
  * ``x.shape == (4)``
  * ``y.shape == (10, 4, 3)``
  * ``xm.shape == (1, 4)``
  * ``matmul(xm, y).shape == (10, 1, 3)``
  * Removing the inserted dimension results in ``matmul(x, y).shape == (10, 3)``.
  * Note: ``xm`` and ``matmul(xm, y)`` are for illustration only.
  
  If ``x`` is N-D where ``N >= 2``, and ``y`` is 1-D, ``y`` is first promoted to
  matrix ``ym`` by appending a ``1`` to its dimension, and the resulting ``ym`` is
  broadcast to ``x`` following Rule 2 above. After this, remove the inserted dimension.
  For example:
  
  * ``x.shape == (10, 3, 4)``
  * ``y.shape == (4,)``
  * ``ym.shape == (4, 1)``
  * ``matmul(x, ym).shape == (10, 3, 1)``
  * Removing the inserted dimension results in ``matmul(x, y).shape == (10, 3)``.
  * Note: ``xm`` and ``matmul(xm, y)`` are for illustration only.
  
  Parameters
  ----------
  x: tensor<[\*,K1], T> (Required)
      * ``x`` must be 1-D or higher.
  y: tensor<[\*,K2], T> (Required)
      * ``y`` must be 1-D or higher.
  transpose_x: const bool (Optional)
      * Default to ``False``.
      * Use ``True`` to transpose the last two dimensions of ``x`` before multiplication.
        It has no effect when ``x`` is 1-D.
  transpose_y: const bool (Optional)
      * Default to ``False``.
      * Use ``True`` to transpose the last two dimensions of ``y`` before multiplication.
        It has no effect when ``y`` is 1-D.
  
  Returns
  -------
  tensor<\*, T>
      * Scalar or tensor output.
  
  Attributes
  ----------
  T: fp16, fp32, i32
class_docstr_tok: ["Perform","N-D","batch","matrix","multiplication","with","NumPy-style","broadcasting","based","on","the","following","rules",":","Rule","1",".","If","both","``","x",",","y","``","are","1-D",",","return","the","scalar","from","the","dot","product",".","Rule","2",".","If","both","``","x",",","y","``","are","2-D","or","higher",",","perform","a","broadcast","on","the","batch","dimensions","(","all","dimensions","except","the","last","``","2","``",")",".","For","example",":","*","``","x.shape","==","(","10",",","4",",","3",")","``","*","``","y.shape","==","(","5",",","10",",","3",",","2",")","``","*","``","matmul","(","x",",","y",")",".shape","==","(","5",",","10",",","4",",","2",")","``","Conventional","matrix","multiplication","is","a","special","case","where","both","``","x",",","y","``","are","exactly","2-D.","For","example",":","*","``","x.shape","==","(","4",",","3",")","``","*","``","y.shape","==","(","3",",","2",")","``","*","``","matmul","(","x",",","y",")",".shape","==","(","4",",","2",")","``","If","``","x","``","is","1-D",",","and","``","y","``","is","N-D","where","``","N",">","=","2","``",",","``","x","``","is","first","promoted","to","matrix","``","xm","``","by","prepending","a","``","1","``","to","its","dimension",",","and","the","resulting","``","xm","``","is","broadcast","to","``","y","``","following","Rule","2","above",".","After","this",",","remove","the","inserted","dimension",".","For","example",":","*","``","x.shape","==","(","4",")","``","*","``","y.shape","==","(","10",",","4",",","3",")","``","*","``","xm.shape","==","(","1",",","4",")","``","*","``","matmul","(","xm",",","y",")",".shape","==","(","10",",","1",",","3",")","``","*","Removing","the","inserted","dimension","results","in","``","matmul","(","x",",","y",")",".shape","==","(","10",",","3",")","``",".","*","Note",":","``","xm","``","and","``","matmul","(","xm",",","y",")","``","are","for","illustration","only",".","If","``","x","``","is","N-D","where","``","N",">","=","2","``",",","and","``","y","``","is","1-D",",","``","y","``","is","first","promoted","to","matrix","``","ym","``","by","appending","a","``","1","``","to","its","dimension",",","and","the","resulting","``","ym","``","is","broadcast","to","``","x","``","following","Rule","2","above",".","After","this",",","remove","the","inserted","dimension",".","For","example",":","*","``","x.shape","==","(","10",",","3",",","4",")","``","*","``","y.shape","==","(","4",",",")","``","*","``","ym.shape","==","(","4",",","1",")","``","*","``","matmul","(","x",",","ym",")",".shape","==","(","10",",","3",",","1",")","``","*","Removing","the","inserted","dimension","results","in","``","matmul","(","x",",","y",")",".shape","==","(","10",",","3",")","``",".","*","Note",":","``","xm","``","and","``","matmul","(","xm",",","y",")","``","are","for","illustration","only",".","Parameters","--","--","--","--","--","x",":","tensor","<","[","\\","*",",","K1","]",",","T",">","(","Required",")","*","``","x","``","must","be","1-D","or","higher",".","y",":","tensor","<","[","\\","*",",","K2","]",",","T",">","(","Required",")","*","``","y","``","must","be","1-D","or","higher",".","transpose_x",":","const","bool","(","Optional",")","*","Default","to","``","False","``",".","*","Use","``","True","``","to","transpose","the","last","two","dimensions","of","``","x","``","before","multiplication",".","It","has","no","effect","when","``","x","``","is","1-D.","transpose_y",":","const","bool","(","Optional",")","*","Default","to","``","False","``",".","*","Use","``","True","``","to","transpose","the","last","two","dimensions","of","``","y","``","before","multiplication",".","It","has","no","effect","when","``","y","``","is","1-D.","Returns","--","--","--","-","tensor","<","\\","*",",","T",">","*","Scalar","or","tensor","output",".","Attributes","--","--","--","--","--","T",":","fp16",",","fp32",",","i32"]
code: def type_inference(self):
      x_type = self.x.dtype
      x_shape = list(self.x.shape)
      y_shape = list(self.y.shape)
      x_rank = len(x_shape)
  
      if x_rank == 1 and self.transpose_x.val:
          msg = "Op {} (matmul): x is rank 1, but transpose_x is True, which is not allowed."
          raise ValueError(msg.format(self.name))
  
      if self.transpose_x.val:
          x_shape = list(x_shape)
          x_shape[-1], x_shape[-2] = x_shape[-2], x_shape[-1]
          x_shape = tuple(x_shape)
      if self.transpose_y.val:
          y_shape = list(y_shape)
          y_shape[-1], y_shape[-2] = y_shape[-2], y_shape[-1]
          y_shape = tuple(y_shape)
      if not (
          x_shape[-1] == y_shape[-2]
          or is_symbolic(x_shape[-1])
          or is_symbolic(y_shape[-2])
      ):
          msg = "Op {} (matmul): x {}, y {} are not broadcastable"
          raise ValueError(
              msg.format(self.name, self.x.shape, self.y.shape)
          )
  
      if x_rank == 1:
          # promote shape of x to rank 2
          x_shape = list((1,) + tuple(x_shape))
      ret_shape = list(broadcast_shapes(x_shape[:-2], y_shape[:-2]))
      ret_shape += [x_shape[-2], y_shape[-1]]
      if x_rank == 1:
          # remove the first dimension of the returned shape
          return types.tensor(x_type, tuple(ret_shape[1:]))
      else:
          return types.tensor(x_type, tuple(ret_shape))
  
imports: import numpy
  from coremltools.converters.mil.mil import DefaultInputs, InputSpec, Operation, TensorInputType, TupleInputType, precondition, types
  from coremltools.converters.mil.mil.operation import VALUE
  from coremltools.converters.mil.mil.ops.defs._op_reqs import register_op
  from coremltools.converters.mil.mil.ops.defs._utils import broadcast_shapes, parse_einsum_equation
  from coremltools.converters.mil.mil.types import nptype_from_builtin
  from coremltools.converters.mil.mil.types.symbolic import is_symbolic
label_desc: Use image node_id 2 for calling the matmul obj's underlying member method code with example usage: obj.type_inference() and returns: types, types