code: def vectorize(function):
      
  
      def decorated(self, X, *args, **kwargs):
          if not isinstance(X, np.ndarray):
              return function(self, X, *args, **kwargs)
  
          if len(X.shape) == 1:
              X = X.reshape([-1, 1])
  
          if len(X.shape) == 2:
              return np.fromiter(
                  (function(self, *x, *args, **kwargs) for x in X),
                  np.dtype('float64')
              )
  
          else:
              raise ValueError('Arrays of dimensionality higher than 2 are not supported.')
  
      decorated.__doc__ = function.__doc__
      return decorated
docs: Allow a method that only accepts scalars to accept vectors too.
  
      This decorator has two different behaviors depending on the dimensionality of the
      array passed as an argument:
  
      **1-d array**
  
      It will work under the assumption that the `function` argument is a callable
      with signature::
  
          function(self, X, *args, **kwargs)
  
      where X is an scalar magnitude.
  
      In this case the arguments of the input array will be given one at a time, and
      both the input and output of the decorated function will have shape (n,).
  
      **2-d array**
  
      It will work under the assumption that the `function` argument is a callable with signature::
  
          function(self, X0, ..., Xj, *args, **kwargs)
  
      where `Xi` are scalar magnitudes.
  
      It will pass the contents of each row unpacked on each call. The input is espected to have
      shape (n, j), the output a shape of (n,)
  
      It will return a function that is guaranteed to return a `numpy.array`.
  
      Args:
          function(callable): Function that only accept and return scalars.
  
      Returns:
          callable: Decorated function that can accept and return :attr:`numpy.array`.