docstr: LU-factorization of a n*n matrix using the Gauss algorithm.
  Returns L and U in one matrix and the pivot indices.
  
  Use overwrite to specify whether A will be overwritten with L and U.
docstr_tok: ["LU-factorization","of","a","n","*","n","matrix","using","the","Gauss","algorithm",".","Returns","L","and","U","in","one","matrix","and","the","pivot","indices",".","Use","overwrite","to","specify","whether","A","will","be","overwritten","with","L","and","U","."]
code: def LU_decomp(ctx, A, overwrite=False, use_cache=True):
      """
      LU-factorization of a n*n matrix using the Gauss algorithm.
      Returns L and U in one matrix and the pivot indices.
  
      Use overwrite to specify whether A will be overwritten with L and U.
      """
      if not A.rows == A.cols:
          raise ValueError("need n*n matrix")
      # get from cache if possible
      if use_cache and isinstance(A, ctx.matrix) and A._LU:
          return A._LU
      if not overwrite:
          orig = A
          A = A.copy()
      tol = ctx.absmin(
          ctx.mnorm(A, 1) * ctx.eps
      )  # each pivot element has to be bigger
      n = A.rows
      p = [None] * (n - 1)
      for j in xrange(n - 1):
          # pivoting, choose max(abs(reciprocal row sum)*abs(pivot element))
          biggest = 0
          for k in xrange(j, n):
              s = ctx.fsum([ctx.absmin(A[k, l]) for l in xrange(j, n)])
              if ctx.absmin(s) <= tol:
                  raise ZeroDivisionError(
                      "matrix is numerically singular"
                  )
              current = 1 / s * ctx.absmin(A[k, j])
              if current > biggest:  # TODO: what if equal?
                  biggest = current
                  p[j] = k
          # swap rows according to p
          ctx.swap_row(A, j, p[j])
          if ctx.absmin(A[j, j]) <= tol:
              raise ZeroDivisionError("matrix is numerically singular")
          # calculate elimination factors and add rows
          for i in xrange(j + 1, n):
              A[i, j] /= A[j, j]
              for k in xrange(j + 1, n):
                  A[i, k] -= A[i, j] * A[j, k]
      if ctx.absmin(A[n - 1, n - 1]) <= tol:
          raise ZeroDivisionError("matrix is numerically singular")
      # cache decomposition
      if not overwrite and isinstance(orig, ctx.matrix):
          orig._LU = (A, p)
      return A, p
  
imports: from copy import copy
  from ..libmp.backend import xrange
label_desc: Use image node_id 1 for calling the LinearAlgebraMethods obj's underlying member method code with example usage: obj.LU_decomp(ctx, A, overwrite, use_cache) and returns: A,  p, A