docs: def permutations(x):
      '''Given a listlike, x, return all permutations of x
  
      Returns the permutations of x in the lexical order of their indices:
      e.g.
      >>> x = [ 1, 2, 3, 4 ]
      >>> for p in permutations(x):
      >>>   print p
      [ 1, 2, 3, 4 ]
      [ 1, 2, 4, 3 ]
      [ 1, 3, 2, 4 ]
      [ 1, 3, 4, 2 ]
      [ 1, 4, 2, 3 ]
      [ 1, 4, 3, 2 ]
      [ 2, 1, 3, 4 ]
      ...
      [ 4, 3, 2, 1 ]
      '''
      #
      # The algorithm is attributed to Narayana Pandit from his
      # Ganita Kaumundi (1356). The following is from
      #
      # http://en.wikipedia.org/wiki/Permutation#Systematic_generation_of_all_permutations
      #
      # 1. Find the largest index k such that a[k] < a[k + 1].
      #    If no such index exists, the permutation is the last permutation.
      # 2. Find the largest index l such that a[k] < a[l].
      #    Since k + 1 is such an index, l is well defined and satisfies k < l.
      # 3. Swap a[k] with a[l].
      # 4. Reverse the sequence from a[k + 1] up to and including the final
      #    element a[n].
      #
      yield list(x) # don't forget to do the first one
      x = np.array(x)
      a = np.arange(len(x))
      while True:
          # 1 - find largest or stop
          ak_lt_ak_next = np.argwhere(a[:-1] < a[1:])
          if len(ak_lt_ak_next) == 0:
              raise StopIteration()
          k = ak_lt_ak_next[-1, 0]
          # 2 - find largest a[l] < a[k]
          ak_lt_al = np.argwhere(a[k] < a)
          l =  ak_lt_al[-1, 0]
          # 3 - swap
          a[k], a[l]  = (a[l], a[k])
          # 4 - reverse
          if k < len(x)-1:
              a[k+1:] = a[:k:-1].copy()
          yield x[a].tolist()