code: def cp_mode_dot(
      cp_tensor, matrix_or_vector, mode, keep_dim=False, copy=False
  ):
      """n-mode product of a CP tensor and a matrix or vector at the specified mode
  
      Parameters
      ----------
      cp_tensor : tl.CPTensor or (core, factors)
  
      matrix_or_vector : ndarray
          1D or 2D array of shape ``(J, i_k)`` or ``(i_k, )``
          matrix or vectors to which to n-mode multiply the tensor
      mode : int
  
      Returns
      -------
      CPTensor = (core, factors)
          `mode`-mode product of `tensor` by `matrix_or_vector`
          * of shape :math:`(i_1, ..., i_{k-1}, J, i_{k+1}, ..., i_N)` if matrix_or_vector is a matrix
          * of shape :math:`(i_1, ..., i_{k-1}, i_{k+1}, ..., i_N)` if matrix_or_vector is a vector
  
      See also
      --------
      cp_multi_mode_dot : chaining several mode_dot in one call
      """
      shape, _ = _validate_cp_tensor(cp_tensor)
      weights, factors = cp_tensor
      contract = False
  
      if T.ndim(matrix_or_vector) == 2:  # Tensor times matrix
          # Test for the validity of the operation
          if matrix_or_vector.shape[1] != shape[mode]:
              raise ValueError(
                  f"shapes {shape} and {matrix_or_vector.shape} not aligned in mode-{mode} multiplication: "
                  f"{shape[mode]} (mode {mode}) != {matrix_or_vector.shape[1]} (dim 1 of matrix)"
              )
  
      elif T.ndim(matrix_or_vector) == 1:  # Tensor times vector
          if matrix_or_vector.shape[0] != shape[mode]:
              raise ValueError(
                  f"shapes {shape} and {matrix_or_vector.shape} not aligned for mode-{mode} multiplication: "
                  f"{shape[mode]} (mode {mode}) != {matrix_or_vector.shape[0]} (vector size)"
              )
          if not keep_dim:
              contract = True  # Contract over that mode
      else:
          raise ValueError(
              "Can only take n_mode_product with a vector or a matrix."
          )
  
      if copy:
          factors = [T.copy(f) for f in factors]
          weights = T.copy(weights)
  
      if contract:
          factor = factors.pop(mode)
          factor = T.dot(matrix_or_vector, factor)
          mode = max(mode - 1, 0)
          factors[mode] *= factor
      else:
          factors[mode] = T.dot(matrix_or_vector, factors[mode])
  
      if copy:
          return CPTensor((weights, factors))
      else:
          cp_tensor.shape = tuple(f.shape[0] for f in factors)
          return cp_tensor
  
imports: from .None import backend
  from .base import fold, tensor_to_vec
  from ._factorized_tensor import FactorizedTensor
  from .tenalg import khatri_rao, unfolding_dot_khatri_rao
  from .metrics.factors import congruence_coefficient
  import numpy
label_desc: Use image node_id 10 for calling a global function with example usage: cp_mode_dot(cp_tensor, matrix_or_vector, mode, keep_dim, copy) and returns: CPTensor, cp_tensor