code: def mul(lhs: Any, rhs: Any, default: Any = RaiseTypeErrorIfNotProvided) -> Any:
      
      # Use left-hand-side's __mul__.
      left_mul = getattr(lhs, '__mul__', None)
      result = NotImplemented if left_mul is None else left_mul(rhs)
  
      # Fallback to right-hand-side's __rmul__.
      if result is NotImplemented:
          right_mul = getattr(rhs, '__rmul__', None)
          result = NotImplemented if right_mul is None else right_mul(lhs)
  
      # Don't build up factors of 1.0 vs sympy Symbols.
      if lhs == 1 and is_parameterized(rhs):
          result = rhs
      if rhs == 1 and is_parameterized(lhs):
          result = lhs
      if lhs == -1 and is_parameterized(rhs):
          result = -rhs
      if rhs == -1 and is_parameterized(lhs):
          result = -lhs
  
      # Output.
      if result is not NotImplemented:
          return result
      if default is not RaiseTypeErrorIfNotProvided:
          return default
      raise TypeError("unsupported operand type(s) for *: '{}' and '{}'".format(
          type(lhs), type(rhs)))
docs: Returns lhs * rhs, or else a default if the operator is not implemented.
  
      This method is mostly used by __pow__ methods trying to return
      NotImplemented instead of causing a TypeError.
  
      Args:
          lhs: Left hand side of the multiplication.
          rhs: Right hand side of the multiplication.
          default: Default value to return if the multiplication is not defined.
              If not default is specified, a type error is raised when the
              multiplication fails.
  
      Returns:
          The product of the two inputs, or else the default value if the product
          is not defined, or else raises a TypeError if no default is defined.
  
      Raises:
          TypeError:
              lhs doesn't have __mul__ or it returned NotImplemented
              AND lhs doesn't have __rmul__ or it returned NotImplemented
              AND a default value isn't specified.