docstr: Ax = b => x
  
  Solve a determined or overdetermined linear equations system.
  Fast LU decomposition is used, which is less accurate than QR decomposition
  (especially for overdetermined systems), but it's twice as efficient.
  Use qr_solve if you want more precision or have to solve a very ill-
  conditioned system.
  
  If you specify real=True, it does not check for overdeterminded complex
  systems.
docstr_tok: ["Ax","=","b","=",">","x","Solve","a","determined","or","overdetermined","linear","equations","system",".","Fast","LU","decomposition","is","used",",","which","is","less","accurate","than","QR","decomposition","(","especially","for","overdetermined","systems",")",",","but","it","'s","twice","as","efficient",".","Use","qr_solve","if","you","want","more","precision","or","have","to","solve","a","very","ill-","conditioned","system",".","If","you","specify","real=True",",","it","does","not","check","for","overdeterminded","complex","systems","."]
code: def lu_solve(ctx, A, b, **kwargs):
      """
      Ax = b => x
  
      Solve a determined or overdetermined linear equations system.
      Fast LU decomposition is used, which is less accurate than QR decomposition
      (especially for overdetermined systems), but it's twice as efficient.
      Use qr_solve if you want more precision or have to solve a very ill-
      conditioned system.
  
      If you specify real=True, it does not check for overdeterminded complex
      systems.
      """
      prec = ctx.prec
      try:
          ctx.prec += 10
          # do not overwrite A nor b
          A, b = (
              ctx.matrix(A, **kwargs).copy(),
              ctx.matrix(b, **kwargs).copy(),
          )
          if A.rows < A.cols:
              raise ValueError("cannot solve underdetermined system")
          if A.rows > A.cols:
              # use least-squares method if overdetermined
              # (this increases errors)
              AH = A.H
              A = AH * A
              b = AH * b
              if kwargs.get("real", False) or not sum(
                  type(i) is ctx.mpc for i in A
              ):
                  # TODO: necessary to check also b?
                  x = ctx.cholesky_solve(A, b)
              else:
                  x = ctx.lu_solve(A, b)
          else:
              # LU factorization
              A, p = ctx.LU_decomp(A)
              b = ctx.L_solve(A, b, p)
              x = ctx.U_solve(A, b)
      finally:
          ctx.prec = prec
      return x
  
imports: from copy import copy
  from ..libmp.backend import xrange
label_desc: Use image node_id 4 for calling the LinearAlgebraMethods obj's underlying member method code with example usage: obj.lu_solve(ctx, A, b) and returns: x