class_docstr: Perform  ``x * weight.T + bias`` where ``weight`` and ``bias`` are constant at
  compile time.
  
  Parameters
  ----------
  x: tensor<[\*D,D_in], T> (Required)
      * ``1 <= rank <= 3``.
      * ``0 <= rank(*D) <= 2``.
  weight: const tensor<[D_out,D_in], T> (Required)
  bias: const tensor<[D_out],T> (Optional)
      * Default to ``0``.
  
  Returns
  -------
  tensor<[\*D,D_out], T>
      * Same rank as the input ``x``.
  
  Attributes
  ----------
  T: fp16, fp32, i32
class_docstr_tok: ["Perform","``","x","*","weight.T","+","bias","``","where","``","weight","``","and","``","bias","``","are","constant","at","compile","time",".","Parameters","--","--","--","--","--","x",":","tensor","<","[","\\","*","D",",","D_in","]",",","T",">","(","Required",")","*","``","1","<","=","rank","<","=","3","``",".","*","``","0","<","=","rank","(","*","D",")","<","=","2","``",".","weight",":","const","tensor","<","[","D_out",",","D_in","]",",","T",">","(","Required",")","bias",":","const","tensor","<","[","D_out","]",",","T",">","(","Optional",")","*","Default","to","``","0","``",".","Returns","--","--","--","-","tensor","<","[","\\","*","D",",","D_out","]",",","T",">","*","Same","rank","as","the","input","``","x","``",".","Attributes","--","--","--","--","--","T",":","fp16",",","fp32",",","i32"]
code: def type_inference(self):
      x_type = self.x.dtype
      x_shape = self.x.shape
      weight_shape = self.weight.shape
      assert len(weight_shape) == 2
      if not (
          x_shape[-1] == weight_shape[-1]
          or is_symbolic(x_shape[-1])
          or is_symbolic(weight_shape[-1])
      ):
          msg = (
              "Op '{}' (linear op): Size of the last dimension of x, which is {}, "
              "does not match the last dimension of weights, which is {}"
          )
          raise ValueError(
              msg.format(self.name, x_shape[-1], weight_shape[-1])
          )
      if self.bias is not None:
          assert len(self.bias.shape) == 1
          if self.bias.shape[0] != weight_shape[-2]:
              msg = (
                  "Op '{}' (linear op): Size of the bias, which is {}, "
                  "does not match the first dimension of weights, which is {}"
              )
              raise ValueError(
                  msg.format(
                      self.name, self.bias.shape[0], weight_shape[-2]
                  )
              )
      shape = list(x_shape)
      shape[-1] = weight_shape[0]
      return types.tensor(x_type, tuple(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 linear obj's underlying member method code with example usage: obj.type_inference() and returns: types