
    Vpfj                        d dl mZ d dlZd dlZd dlZd dlmZ d dlmZ d dlm	Z	 d dlm
Z d dlmZmZmZmZmZ d dlmZ d dlm	Z d dlmZ  eej        e	j        j        	          Z eej        e	j        j        	          Z eej        e	j        j        	          Z d
 Z!d Z"d Z#d Z$d Z%d Z& eeej'                  Z( eeej)                  Z* eee          Z+ed             Z,d Z-d.dde,ddZ.d.dde,ddZ/d Z0d.dddddddZ1d.ddddddZ2d.dZ3d Z4d/d Z5d! Z6d" Z7d# Z8d$ Z9d% Z:d& Z;d' Z<d( Z=d.ddd)ddd*d+d,Z>d.dddddd-Z?dS )0    )partialN)
device_put)lax)scipy)tree_leavestree_maptree_structuretree_reducePartial)dtypes)safe_map	precisionc                     t          | j        |j                  }t          j        |           st          j        |          r|t          | j        |j                  z  }|S )zVector dot-product guaranteed to have a real valued result despite
     possibly complex input. Thus neglects the real-imaginary cross-terms.
     The result is a real float.
  )_vdotrealjnpiscomplexobjimag)xyresults      \/var/www/html/nettyfy-visnx/env/lib/python3.11/site-packages/jax/_src/scipy/sparse/linalg.py_vdot_real_partr   (   sY       &a $C,Q// $
eAFAF###F	-    c           	      b    t          t          t          t          | |                              S N)sumr   r   r   r   r   s     r   _vdot_real_treer    8   s$    	[/1a8899	:	::r   c           
          t          t          t          t          t          j        t          j        j                  | |                              S )Nr   )	r   r   r   r   r   vdotr   	PrecisionHIGHESTr   s     r   
_vdot_treer%   <   sN    	['H-#/ #/ #/0116 6 7 7 
8 
8 8r   c           	          t          |           }t          j        t          t	          t
          ||                              S r   )r   r   sqrtr   mapr   )r   xss     r   _normr*   A   s1    1~~"	#c/2r2233	4	44r   c                 R    t          t          t          j        |           |          S r   )r   r   operatormul)scalartrees     r   _mulr0   F   s    	'(,//	6	66r   c                 D    t          t          fd          |           S )Nc                     | z  S r    )vr.   s    r   <lambda>z_div.<locals>.<lambda>K   s    AJ r   )r   r   )r/   r.   s    `r   _divr6   J   s%    	'....//	6	66r   c                     | S r   r3   r   s    r   	_identityr9   S   s    	
(r   c                 D   t          |           r| S t          | t          j        t          j        f          rS| j        dk    s| j        d         | j        d         k    rt          d| j                   t          t          |           S t          | d          rut          | d          rt          | j                  dk    s| j        d         | j        d         k    rt          d| j                   t          t          j        |           S t          d|            )z;Normalize an argument for computing matrix-vector products.   r      z8linear operator must be a square matrix, but has shape: 
__matmul__shapez6linear operator must be either a function or ndarray: )callable
isinstancenpndarrayjaxArrayndimr>   
ValueErrorr   _dothasattrlenr,   matmul	TypeError)fs    r   _normalize_matvecrM   X   s'   a[[ FH!bj#),-- Fv{{agajAGAJ..
NQW
N
NP P P4q, Fq' Ps17||q00AGAJ!'!*4L4L
NQW
N
NP P P8?A&&&
DDDF F Fr   gh㈵>        )tolatolMc                    t          ||          }t          j        t          j        |          |z  t          j        |                    fd} fd}	t	          |  |                    }
 |
          x}}t          j        t          |           t          |
|                                        }||
||df}t          j	        ||	|          ^}}|S )Nc                 n    | \  }}}}}t           u r|j        nt          ||          }|k    |k     z  S r   )r9   r   r    )	value_rgammakrsrQ   atol2maxiters	         r   cond_funz_cg_solve.<locals>.cond_funs   sC    Aq%AI~~?1a+@+@BJ1w;''r   c                    | \  }}}}} |          }|t          ||                                        z  }t          |t          ||                    }t	          |t          ||                    }	 |	          }
t          |	|
                                        }||z  }t          |
t          ||                    }||	|||dz   fS Nr<   )r    astype_addr0   _sub)rT   r   rV   rW   prX   Apalphax_r_z_gamma_beta_p_ArQ   dtypes                 r   body_funz_cg_solve.<locals>.body_funx   s    Aq%A	
1BOAr**11%888E	aeQ	 	 B	aeR	!	!B	
2BR$$++E22FUNE	b$ua..	!	!Br62q1u$$r   r   )
r    r   maximumsquarera   result_typer   r_   r   
while_loop)rk   bx0r[   rO   rP   rQ   bsr\   rm   r0p0z0gamma0initial_valuex_finalrU   rZ   rl   s   `  `  `          @@r   	_cg_solver{   k   s	    q!"
+cjoo*CJt,<,<
=
=%( ( ( ( ( ( (

% 
% 
% 
% 
% 
% 
% Aqquu~~"AbEE/"r
/;r??
+%2r""))%00&r62q)-x=AA+'A	.r   c          	          t          ||          }t          j        t          j        |          |z  t          j        |                    fd} fd}	t	          |  |                    }
t          j        dgt          j        t          |           R  x}x}}||
|
||||
|
df	}t          j        ||	|          ^}}|S )Nc                 Z    | ^}}}}t          ||          }|k    |k     z  |dk    z  S )Nr   )r    )rT   r   rV   rU   rX   rY   rZ   r[   s         r   r\   z!_bicgstab_solve.<locals>.cond_fun   s;    KAq1a	A		BJ1w;'1622r   c                     | \	  }}}}}}}}}	t          ||          }
|
|z  |z  |z  }t          |t          |t          |t          ||                                        } |          } |          }|
t          ||          z  }t          |t          ||                    }t	          ||          k     } |          } |          }t          ||          t          ||          z  }t          t          t          j        |          t          |t          ||                    t          |t          t          ||          t          ||                                        }t          t          t          j        |          |t          |t          ||                              }t          j        |dk    |dk    z  d|	dz             }t          j        |
dk    d|          }||||||
|||f	S )Nr   ir<   i)	r%   r`   r0   ra   r    r   r   r   where)rT   r   rV   rhatrd   omegarhorb   qrX   rho_betarj   phatq_alpha_s
exit_earlyshattomega_re   rf   k_rk   rQ   rZ   s                           r   rm   z!_bicgstab_solve.<locals>.body_fun   s   -2*Aq$uc1adAD#:%D	adDDNN3344	5	5B1R55D	
4BJtR(((FQVR  !!A A&&.J1Q44D	$A1
1a 0 00F	'#)Z00q$vt,,--q$tFD1143E3EFFGG
 
B 
'#)Z00T!T&!__--
/ 
/B	FaKFaK0#q1u	=	=B	DAIR	(	(Br4r2r99r   r<   r   )r    r   rn   ro   ra   lax_internal_convert_element_typer   _lattice_result_typer   r   rq   )rk   rr   rs   r[   rO   rP   rQ   rt   r\   rm   ru   rho0alpha0omega0ry   rz   rU   rZ   s   `  `  `          @r   _bicgstab_solver      s	    q!"
+cjoo*CJt,<,<
=
=%3 3 3 3 3 3: : : : : : :. Aqquu~~"'=8

%{1~~
68 8 8 8$ 8&r2vvtRQ?-x=AA+'A	.r   c                 P    t          t          j        t          |                     S r   )r(   r   r>   r   )pytrees    r   _shapesr      s    	SYF++	,	,,r   F)rO   rP   r[   rQ   check_symmetricc                   |t          t          j        |          }t          ||f          \  }}|+t	          d t          |          D                       }	d|	z  }|t          }t          |          }t          |          }t          |          t          |          k    r/t          dt          |           dt          |                     t          |          t          |          k    r/t          dt          |           dt          |                     t          | |||||          }
d }|r*t          t          |t          |                              nd}t          j        |||
|
|	          }d }||fS )
Nc              3   $   K   | ]}|j         V  d S r   size.0bis     r   	<genexpr>z_isolve.<locals>.<genexpr>   s$      002rw000000r   
   ,x0 and b must have matching tree structure:  vs z.arrays in x0 and b must have matching shapes: )rs   rO   rP   r[   rQ   c                 L    t          | j        j        t          j                   S r   )
issubclassrl   typerA   complexfloatingr8   s    r   real_valuedz_isolve.<locals>.real_valued   s    !',(:;;;;r   F)solvetranspose_solve	symmetric)r   r   
zeros_liker   r   r   r9   rM   r	   rF   r   r   allr(   r   custom_linear_solve)_isolve_solverk   rr   rs   rO   rP   r[   rQ   r   r   isolve_solver   r   r   infos                  r   _isolver      s   Z	#.!	$	$B
aW

%!R_00Q00000D4iGYA!!B>!,,,,
	7"	7 	7#1!#4#4	7 	78 8 8 R[[GAJJ
	)2;;	) 	)#AJJ	) 	)* * * $1F F F,< < < "c#k;q>>22333! 	,  ! 
$	
D.r   )rO   rP   r[   rQ   c                <    t          t          | ||||||d	  	        S )a	  Use Conjugate Gradient iteration to solve ``Ax = b``.

  The numerics of JAX's ``cg`` should exact match SciPy's ``cg`` (up to
  numerical precision), but note that the interface is slightly different: you
  need to supply the linear operator ``A`` as a function instead of a sparse
  matrix or ``LinearOperator``.

  Derivatives of ``cg`` are implemented via implicit differentiation with
  another ``cg`` solve, rather than by differentiating *through* the solver.
  They will be accurate only if both solves converge.

  Parameters
  ----------
  A: ndarray, function, or matmul-compatible object
      2D array or function that calculates the linear map (matrix-vector
      product) ``Ax`` when called like ``A(x)`` or ``A @ x``. ``A`` must represent
      a hermitian, positive definite matrix, and must return array(s) with the
      same structure and shape as its argument.
  b : array or tree of arrays
      Right hand side of the linear system representing a single vector. Can be
      stored as an array or Python container of array(s) with any shape.

  Returns
  -------
  x : array or tree of arrays
      The converged solution. Has the same structure as ``b``.
  info : None
      Placeholder for convergence information. In the future, JAX will report
      the number of iterations when convergence is not achieved, like SciPy.

  Other Parameters
  ----------------
  x0 : array or tree of arrays
      Starting guess for the solution. Must have the same structure as ``b``.
  tol, atol : float, optional
      Tolerances for convergence, ``norm(residual) <= max(tol*norm(b), atol)``.
      We do not implement SciPy's "legacy" behavior, so JAX's tolerance will
      differ from SciPy unless you explicitly pass ``atol`` to SciPy's ``cg``.
  maxiter : integer
      Maximum number of iterations.  Iteration will stop after maxiter
      steps even if the specified tolerance has not been achieved.
  M : ndarray, function, or matmul-compatible object
      Preconditioner for A.  The preconditioner should approximate the
      inverse of A.  Effective preconditioning dramatically improves the
      rate of convergence, which implies that fewer iterations are needed
      to reach a given error tolerance.

  See also
  --------
  scipy.sparse.linalg.cg
  jax.lax.custom_linear_solve
  T)rk   rr   rs   rO   rP   r[   rQ   r   )r   r{   rk   rr   rs   rO   rP   r[   rQ   s          r   cgr      s0    j 
bc At
= 
= 
= =r   c                    t          |           }t          j        t          |            \  }}t          j        |          }|t          j        |j                  j        }|	                    |          j
        }||k    t          j        |||          t          fd|           }t          j        |d          }||fS )a!  
  Returns the L2-normalized vector (which can be a pytree) x, and optionally
  the computed norm. If the computed norm is less than the threshold `thresh`,
  which by default is the machine precision of x's dtype, it will be
  taken to be 0, and the normalized x to be the zero vector.
  Nc                 6    t          j        | z  d          S )NrN   )r   r   )r   	norm_castuse_norms    r   r5   z!_safe_normalize.<locals>.<lambda>8  s    CIhIs$K$K r   rN   )r*   r   r   r   canonicalize_dtyper   finforl   epsr_   r   r   r   r   r   )r   threshnormrl   	weak_typenormalized_xr   r   s         @@r   _safe_normalizer   '  s     
q$0+a..A%

#E
*
*%^Ytz""&F==$&F](0uiHH)KKKKKQOO,	8T3	'	'$	t	r   c                 Z    t          d | |          }t          t          j        |          S )z
  Returns A.T.conj() @ v.
  c                 H    t          d|                                 |          S )Nz...n,...->n)_einsumconjXr   s     r   r5   z%_project_on_columns.<locals>.<lambda>B  s    7=!&&((A66 r   )r   r
   r,   add)rk   r4   v_projs      r   _project_on_columnsr   =  s1     661 & 
X\6	*	**r   r;   c                 2    t                     d         }t          j        |j        d         |j                  }|}|t          j        d          z  } fd}fd}	 |d|||f          \  }
}}}t          j        |	||
|||f          \  }
}}}||fS )a  
  Orthogonalize x against the columns of Q. The process is repeated
  up to `max_iterations` times, or fewer if the condition
  ||r|| < (1/sqrt(2)) ||x|| is met earlier (see below for the meaning
  of r and x).

  Parameters
  ----------
  Q : array or tree of arrays
      A matrix of orthonormal columns.
  x : array or tree of arrays
      A vector. It will be replaced with a new vector q which is orthonormal
      to the columns of Q, such that x in span(col(Q), q).
  xnorm : float
      Norm of x.

  Returns
  -------
  q : array or tree of arrays
      A unit vector, orthonormal to each column of Q, such that
      x in span(col(Q), q).
  r : array
      Stores the overlaps of x with each vector in Q.
  r   rl          @c                    
 | \  }}}}t          |          
t          
fd          }t          ||          }t          |
          }fd}d }|d||f}t	          j        |||          \  }	}	}}|dz   |||fS )Nc                 $    t          |           S r   rG   )r   hs    r   r5   zJ_iterative_classical_gram_schmidt.<locals>.body_function.<locals>.<lambda>o  s    DAJJ r   c                 J    | \  }}}}t          j        ||dz
  k               S r^   r   logical_and)carryrX   not_donerU   max_iterationss       r   
qnorm_condzL_iterative_classical_gram_schmidt.<locals>.body_function.<locals>.qnorm_conds  s-    a1a_XqNQ,>'?@@@r   c                 n    | \  }}}}t          |          \  }}|t          j        d          z  }|d||fS )Nr   F)r   r   r'   )r   rX   rU   r   qnorm_scaledqnorms         r   r   zG_iterative_classical_gram_schmidt.<locals>.body_function.<locals>.qnormw  sB    #aA| ##haSXc]]*l<((r   Tr<   )r   r   ra   r`   r   rq   )r   rX   r   rV   r   Qhr   r   initrU   r   Qr   s             @r   body_functionz8_iterative_classical_gram_schmidt.<locals>.body_functionl  s    !Aq!\Aq!!A	&&&&	*	*BQAQ

AA A A A A) ) ) tQ%DN:udCCAq!\E1a&&r   c                 v    | \  }}}}t          |          \  }}t          j        |dz
  k     ||k               S r^   )r   r   r   )r   rX   rU   rV   r   rnormr   s         r   cond_functionz8_iterative_classical_gram_schmidt.<locals>.cond_function  sC    !Aq!\q!!HAu?1 23U\5IJJJr   )r   r   zerosr>   rl   r'   r   rq   )r   r   xnormr   Q0rV   r   xnorm_scaledr   r   rX   r   rU   s   `  `         r   !_iterative_classical_gram_schmidtr   G  s    @ 1~~a"	iBH---!!#&,' ' ' ' ' '*K K K K K
 (-Aq,(?@@!Q<~m] !Q57 7*!Q1	
A+r   c                 \    t          j        t          |           \  }}t          j        |          }t	          j        |          j        }t           fd|          } | ||                    }t          |          \  }}	t          |||	d          \  }}
||	z  }t          ||          \  }}t           fd||          }|
j
         dz                                |                    |                    }
|j
         ddf                             |
          }|dk    }|||fS )	a  
  Performs a single (the k'th) step of the Arnoldi process. Thus,
  adds a new orthonormalized Krylov vector A(M(V[:, k])) to V[:, k+1],
  and that vectors overlaps with the existing Krylov vectors to
  H[k, :]. The tolerance 'tol' sets the threshold at which an invariant
  subspace is declared to have been found, in which case in which case the new
  vector is taken to be the zero vector.
  c                     | df         S )N.r3   )r   rX   s    r   r5   z(_kth_arnoldi_iteration.<locals>.<lambda>  s    36 r   r;   )r   )r   c                 N    | j         ddz   f                             |          S )N.r<   )atset)r   r   rX   s     r   r5   z(_kth_arnoldi_iteration.<locals>.<lambda>  s$    ADa!e,0033 r   r<   NrN   )r   r   r   r   r   r   r   r   r   r   r   r   r_   )rX   rk   rQ   VHrl   rU   r   r4   v_norm_0r   rO   unit_vv_norm_1	breakdowns   `              r   _kth_arnoldi_iterationr     s-    (+a..9(%

#E
*
*%	%#""""A&&!a!gg!""+!X	*1a!	L	L	L$!Qh#$Qs333&(3333Q??!d1q5koohooe,,--!d1aaa4jnnQ!"n)	
Ayr   c                 &   | |         }| |dz            }|                                 |z  |                                 |z  z
  }||z  ||z  z   }| j        |                             |          } | j        |dz                                |          } | S r^   )r   r   r   )r   icssnx1y1x2y2s           r   _rotate_vectorsr     s    t"Qx"	wwyy2~		B&"	Bwb"d1gkk"oo!d1q5koob!	
(r   c           
         t          |          dk    }t          |           t          |          k     }t          j        || |           t          j        |||           z  }t          j        dt          |          dz  z                                 |j                  }t          j        |dt          j        |||z  |                    }t          j        |dt          j        ||||z                      }||fS )Nr   r<   r;   )absr   r   r   rsqrtr_   rl   )arr   b_zeroa_lt_br   rV   r   r   s           r   _givens_rotationr    s    q66Q;&q66CFF?&
yA61a!8!88!	iCFFaK  ''00!
yCIfa!eQ7788"
yCIfaQ7788"	R-r   c                     fd}t          j        d|||           }t          ||         ||dz                      }j        |ddf                             |          t          ||g|R  }|fS )z
  Applies the Givens rotations stored in the vectors cs and sn to the vector
  H_row. Then constructs and applies a new Givens rotation that eliminates
  H_row's k'th element.
  c                 4    t          || g| d d f         R  S r   )r   )r   H_rowgivenss     r   apply_ith_rotationz3_apply_givens_rotations.<locals>.apply_ith_rotation  s'    5!3fQTl3333r   r   r<   N)r   	fori_loopr  r   r   r   )r  r	  rX   r
  R_rowgivens_factorss    `    r   _apply_givens_rotationsr    s    4 4 4 4 4
-10%
8
8%#E!HeAEl;;.9QT?~..&
%
4^
4
4
4%	r   c                     t          fd|          }t          j        t          |           }	t          j        dz   |	          }
t          j        df|	          }t          j        dz   |	          }|j        d                             |                    |	                    }fd} fd}d|||
||f}t          j
        |||          }|\  }}}}
}}~t          j                            |
dddd	f         j        |dd	                   t          fd
|          }t          ||          } t!          |  |                              }t#          |          \  }}|||fS )a2  
  Implements a single restart of GMRES. The restart-dimensional Krylov subspace
  K(A, x0) = span(A(x0), A@x0, A@A@x0, ..., A^restart @ x0) is built, and the
  projection of the true solution into this subspace is returned.

  This implementation builds the QR factorization during the Arnoldi process.
  c                 V    t          j        | d         d| j        z  dffz             S N).N))r   r   r   r   padrE   r   restarts    r   r5   z$_gmres_incremental.<locals>.<lambda>  )    )i!&&8QL?&JKK r   r<   r   r;   r   c                 P    | \  }}}}}}t          j        |k     |k              S r   r   )r   rX   errrU   ptolr  s       r   	loop_condz%_gmres_incremental.<locals>.loop_cond  s/    AsAq!Q?1w;d
333r   c                 >   | \  }}}}}}t          |
||          \  }}}t          ||d d f         ||          \  }}|j        |d d f                             |          }t	          ||g||d d f         R  }t          ||dz                      }	|dz   |	||||fS r^   )r   r  r   r   r   r   )r   rX   rU   r   Rbeta_vecr	  r   r  r  rk   rQ   s             r   arnoldi_qr_stepz+_gmres_incremental.<locals>.arnoldi_qr_step  s    #( Aq!Q&$Q1a33GAq!+AadGVQ??ME6	QT
uAx:VAqqqD\:::H
hq1uo

Cq5#q!Xv--r   Nr   c                 8    t          | dd df                   S N.r   r   r   s    r   r5   z$_gmres_incremental.<locals>.<lambda>      $qcrc{A.. r   )r   r   rp   r   eyer   r   r   r_   r   rq   jsplinalgsolve_triangularTr`   ra   r   )rk   rr   rs   unit_residualresidual_normr  r  rQ   r   rl   r  r	  r  r  r  r   rX   rU   dxr   residualr   s   `    ```             @r   _gmres_incrementalr+    s    KKKK ! /;q>>
*% 
ggw{%000!9gq\///&Y!E222([^ 4 4U ; ;<<(4 4 4 4 4 4. . . . . . mQ8V
4%
.OU
;
;%(-%!]Aq(A	j!!!AAAssF)+x}==!....22"
2rll!QtAqqtt}}(!0!:!:-	
M=	((r   c                     t          | j                                        |           }t          | j                                        |          }t          j                            ||d          S )Npos)assume_a)rG   r&  r   r#  r$  r   )r  rr   a2b2s       r   _lstsqr1    sQ    ACHHJJ"ACHHJJ"			"b5		1	11r   c                     ~t          fd|          }t          j        t          |           \  }	}
t          j        |	          }	t          j        t          j        dz   |	          |
          }fd} fd}||ddf}t          j
        |||          \  }}}}t          j        |dz   f	          j        d                             |                    |	                    }t          |j        |          t          fd
|          }t#          ||          } t%          |  |                              }t'          |          \  }}|||fS )ac  
  Implements a single restart of GMRES. The ``restart``-dimensional Krylov
  subspace
  K(A, x0) = span(A(x0), A@x0, A@A@x0, ..., A^restart @ x0) is built, and the
  projection of the true solution into this subspace is returned.

  This implementation solves a dense linear problem instead of building
  a QR factorization during the Arnoldi process.
  c                 V    t          j        | d         d| j        z  dffz             S r  r  r  s    r   r5   z _gmres_batched.<locals>.<lambda>  r  r   r<   r   )r   c                 h    | \  }}}}t          j        |k     t          j        |                    S r   )r   r   logical_not)r   rU   r   rX   r  s       r   r  z!_gmres_batched.<locals>.loop_cond  s1    Aq)Q?1w;	(B(BCCCr   c                 R    | \  }}}}t          |||          \  }}}||||dz   fS r^   )r   )r   r   r   rU   rX   r   rk   rQ   s         r   arnoldi_processz'_gmres_batched.<locals>.arnoldi_process"  s>    JAq!Q,Q1a;;OAq)aAE!!r   Fr   )r>   c                 8    t          | dd df                   S r   r   r   s    r   r5   z _gmres_batched.<locals>.<lambda>,  r!  r   )r   r   r   r   r   r   r   r   r"  r   rq   r   r   r   r_   r1  r&  r`   ra   r   )rk   rr   rs   r'  r(  r  r  rQ   r   rl   r   r   r  r7  r   rU   r  r)  r   r*  r   s   `     ``            @r   _gmres_batchedr9  	  s    KKKK ! 0+a..A%

#E
*
*%(	ggw{%000IG G G!D D D D D" " " " " "
 a
%~i%@@*!Q1^Agk^4447:>>}?S?STY?Z?Z[[(QS(!....22"
2rll!QtAqqtt}}(!0!:!:-	
M=	((r   c	                       t            |                              }	t          |	          \  }
}fd} fd}|d|
|f}t          j        |||          \  }}}}|}|}|S )a  
  The main function call wrapped by custom_linear_solve. Repeatedly calls GMRES
  to find the projected solution within the order-``restart``
  Krylov space K(A, x0, restart), using the result of the previous projection
  in place of x0 each time. Parameters are the same as in ``gmres`` except:

  atol: Tolerance for norm(A(x) - b), used between restarts.
  ptol: Tolerance for norm(M(A(x) - b)), used within a restart.
  gmres_func: A function performing a single GMRES restart.

  Returns: The solution.
  c                 L    | \  }}}}t          j        |k     |k              S r   r   )rT   rU   rX   r(  rP   r[   s       r   r\   z_gmres_solve.<locals>.cond_funE  s,    "Aq!]?1w;(<===r   c           
      P    | \  }}}} |||	
          \  }}}||dz   ||fS r^   r3   )rT   r   rX   r'  r(  rk   rQ   rr   
gmres_funcr  r  s        r   rm   z_gmres_solve.<locals>.body_funI  sO    ).&Aq-&0j	1atWa'A 'A#A}ma!e]M11r   r   )ra   r   r   rq   )rk   rr   rs   rP   r  r  r[   rQ   r=  r*  r'  r(  r\   rm   initializationrz   rX   rU   r  s   `` ``````          r   _gmres_solver?  5  s     QtAqquu~~(!0!:!:-> > > > > >2 2 2 2 2 2 2 2 2 2 =-8.~h.II'1a!	!	.r      batched)rO   rP   r  r[   rQ   solve_methodc                   t          t          j        |          t          t	          |           } t	                    t          |f          \  }t          d t          |          D                       }	d|	z  t          |	          t                    t          |          k    r/t          dt                     dt          |                     t          |          }
t          j        ||
z             |          }t          |          }|t          j        d|
z            z  |dk    rt          n!|dk    rt          nt          d	| d
          fd}t!          j        | |||          }t          j        t          |                    }t          j        |dd          }||fS )a  
  GMRES solves the linear system A x = b for x, given A and b.

  A is specified as a function performing A(vi) -> vf = A @ vi, and in principle
  need not have any particular special properties, such as symmetry. However,
  convergence is often slow for nearly symmetric operators.

  Parameters
  ----------
  A: ndarray, function, or matmul-compatible object
      2D array or function that calculates the linear map (matrix-vector
      product) ``Ax`` when called like ``A(x)`` or ``A @ x``. ``A``
      must return array(s) with the same structure and shape as its argument.
  b : array or tree of arrays
      Right hand side of the linear system representing a single vector. Can be
      stored as an array or Python container of array(s) with any shape.

  Returns
  -------
  x : array or tree of arrays
      The converged solution. Has the same structure as ``b``.
  info : None
      Placeholder for convergence information. In the future, JAX will report
      the number of iterations when convergence is not achieved, like SciPy.

  Other Parameters
  ----------------
  x0 : array or tree of arrays, optional
      Starting guess for the solution. Must have the same structure as ``b``.
      If this is unspecified, zeroes are used.
  tol, atol : float, optional
      Tolerances for convergence, ``norm(residual) <= max(tol*norm(b), atol)``.
      We do not implement SciPy's "legacy" behavior, so JAX's tolerance will
      differ from SciPy unless you explicitly pass ``atol`` to SciPy's ``gmres``.
  restart : integer, optional
      Size of the Krylov subspace ("number of iterations") built between
      restarts. GMRES works by approximating the true solution x as its
      projection into a Krylov space of this dimension - this parameter
      therefore bounds the maximum accuracy achievable from any guess
      solution. Larger values increase both number of iterations and iteration
      cost, but may be necessary for convergence. The algorithm terminates
      early if convergence is achieved before the full subspace is built.
      Default is 20.
  maxiter : integer
      Maximum number of times to rebuild the size-``restart`` Krylov space
      starting from the solution found at the last iteration. If GMRES
      halts or is very slow, decreasing this parameter may help.
      Default is infinite.
  M : ndarray, function, or matmul-compatible object
      Preconditioner for A.  The preconditioner should approximate the
      inverse of A.  Effective preconditioning dramatically improves the
      rate of convergence, which implies that fewer iterations are needed
      to reach a given error tolerance.
  solve_method : 'incremental' or 'batched'
      The 'incremental' solve method builds a QR decomposition for the Krylov
      subspace incrementally during the GMRES process using Givens rotations.
      This improves numerical stability and gives a free estimate of the
      residual norm that allows for early termination within a single "restart".
      In contrast, the 'batched' solve method solves the least squares problem
      from scratch at the end of each GMRES iteration. It does not allow for
      early termination, but has much less overhead on GPUs.

  See also
  --------
  scipy.sparse.linalg.gmres
  jax.lax.custom_linear_solve
  Nc              3   $   K   | ]}|j         V  d S r   r   r   s     r   r   zgmres.<locals>.<genexpr>  s$      ..RW......r   r   r   r   g      ?incrementalrA  zinvalid solve_method z+, must be either 'incremental' or 'batched'c                 2    t          | |	  	        S r   )r?  )	rk   rr   rQ   rP   r=  r[   r  r  rs   s	     r   _solvezgmres.<locals>._solve  s!    1b$gw:NNNr   )r   r   r   r   )r   r   r   r9   rM   r   r   r   minr	   rF   r*   rn   minimumr+  r9  r   r   isnanr   )rk   rr   rs   rO   rP   r  r[   rQ   rB  r   b_normMbMb_normrG  r   failedr   r=  r  s     ` ````         @@r   gmresrO  V  s"   L Z	#.!	$	$BYA!!
aW

%!R	..{1~~...	.	.$_4iG'B>!,,,,
	7"	7 	7#1!#4#4	7 	78 8 8 88&	S6\4	(	($qtt""II'	3;sD6M22	2$]""#JJy  JJ
 2\ 2 2 2 3 3 3O O O O O O O O O O O	a&&III!9U1XX&	62q	!	!$	
D.r   c          
      :    t          t          | ||||||          S )aO	  Use Bi-Conjugate Gradient Stable iteration to solve ``Ax = b``.

  The numerics of JAX's ``bicgstab`` should exact match SciPy's
  ``bicgstab`` (up to numerical precision), but note that the interface
  is slightly different: you need to supply the linear operator ``A`` as
  a function instead of a sparse matrix or ``LinearOperator``.

  As with ``cg``, derivatives of ``bicgstab`` are implemented via implicit
  differentiation with another ``bicgstab`` solve, rather than by
  differentiating *through* the solver. They will be accurate only if
  both solves converge.

  Parameters
  ----------
  A: ndarray, function, or matmul-compatible object
      2D array or function that calculates the linear map (matrix-vector
      product) ``Ax`` when called like ``A(x)`` or ``A @ x``. ``A`` can represent
      any general (nonsymmetric) linear operator, and function must return array(s)
      with the same structure and shape as its argument.
  b : array or tree of arrays
      Right hand side of the linear system representing a single vector. Can be
      stored as an array or Python container of array(s) with any shape.

  Returns
  -------
  x : array or tree of arrays
      The converged solution. Has the same structure as ``b``.
  info : None
      Placeholder for convergence information. In the future, JAX will report
      the number of iterations when convergence is not achieved, like SciPy.

  Other Parameters
  ----------------
  x0 : array or tree of arrays
      Starting guess for the solution. Must have the same structure as ``b``.
  tol, atol : float, optional
      Tolerances for convergence, ``norm(residual) <= max(tol*norm(b), atol)``.
      We do not implement SciPy's "legacy" behavior, so JAX's tolerance will
      differ from SciPy unless you explicitly pass ``atol`` to SciPy's ``cg``.
  maxiter : integer
      Maximum number of iterations.  Iteration will stop after maxiter
      steps even if the specified tolerance has not been achieved.
  M : ndarray, function, or matmul-compatible object
      Preconditioner for A.  The preconditioner should approximate the
      inverse of A.  Effective preconditioning dramatically improves the
      rate of convergence, which implies that fewer iterations are needed
      to reach a given error tolerance.

  See also
  --------
  scipy.sparse.linalg.bicgstab
  jax.lax.custom_linear_solve
  r   )r   r   r   s          r   bicgstabrQ    s.    n 
bc A
' 
' 
' 'r   r   )r;   )@	functoolsr   r,   numpyrA   rC   	jax.numpyr   r   r   r   r#  jax.tree_utilr   r   r	   r
   r   jax._srcr   jax._src.laxr   jax._src.utilr   r(   dotr#   r$   rG   r"   r   einsumr   r   r    r%   r*   r0   r6   r   r`   subra   	_dot_treer9   rM   r{   r   r   r   r   r   r   r   r   r   r  r  r+  r1  r9  r?  rO  rQ  r3   r   r   <module>r]     s               



                        1 1 1 1 1 1 1 1 1 1 1 1 1 1       , , , , , , ) ) ) ) ) ) wsw#-"7888CM$9:::
'#*(=
>
>
>   ; ; ;8 8 8
5 5 5
7 7 77 7 7 wx&&wx&&GHd##	 	  	F F F&!Ty ! ! ! ! !L,4cY , , , , ,^- - -&CD%& & & & &R7=TTT 7= 7= 7= 7= 7=t   ,+ + +B B B BJ  8      &0) 0) 0)f2 2 2)) )) ))X  Bn3Dyn n n n nb9'4c44 9' 9' 9' 9' 9' 9' 9'r   