
    Џkh                     H    d Z ddlZddlmZmZmZmZmZ ddl	m
Z
mZ d Zd Zy)a   
This module provides some Powell-style linear algebra procedures.

Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA.

Dedicated to late Professor M. J. D. Powell FRS (1936--2015).

Python translation by Nickolai Belakovski.
    N   )isminorplanerotmatprodinprodhypot)	DEBUGGINGEPSc           
      J   |j                   d   }|}t        | |      }t        t        |       t        |            }t        j                  t        ||      D 	cg c]  \  }}	t        ||	      rdn| c}	}      }t        |dz
  |dz
  d      D ]g  }
t        ||
dz            dkD  st        ||
|
dz          }t        |dd|
|
dz   gf   |j                        |dd|
|
dz   gf<   t        ||
|
dz     ||
<   i ||k  r/t        ||         t        dz  kD  rt        ||   ||         s|dz  }|dz
  dk\  r|dz
  |k  r||dz
     ||dz
  <   t        rI||cxk  rt        |dz   |      k  sJ  J |t        |      cxk  r|k  sJ  J |j                   ||fk(  sJ |||fS c c}	}w )a  
    This function updates the QR factorization of an MxN matrix A of full column rank, attempting to
    add a new column C to this matrix as the LAST column while maintaining the full-rankness.
    Case 1. If C is not in range(A) (theoretically, it implies N < M), then the new matrix is np.hstack([A, C])
    Case 2. If C is in range(A), then the new matrix is np.hstack([A[:, :n-1], C])
    N.B.:
    0. Instead of R, this subroutine updates Rdiag, which is np.diag(R), with a size at most M and at
    least min(m, n+1). The number is min(m, n+1) rather than min(m, n) as n may be augmented by 1 in
    the function.
    1. With the two cases specified as above, this function does not need A as an input.
    2. The function changes only Q[:, nsave:m] (nsave is the original value of n) and
    R[:, n-1] (n takes the updated value)
    3. Indeed, when C is in range(A), Powell wrote in comments that "set iOUT to the index of the
    constraint (here, column of A --- Zaikun) to be deleted, but branch if no suitable index can be
    found". The idea is to replace a column of A by C so that the new matrix still has full rank
    (such a column must exist unless C = 0). But his code essentially sets iout=n always. Maybe he
    found this worked well enough in practice. Meanwhile, Powell's code includes a snippet that can
    never be reached, which was probably intended to deal with the case that IOUT != n
    r   r      N)shaper   absnparrayzipr   ranger   Tr   r
   r	   minlen)cQRdiagnmnsavecqcqacqicqaikGs               \/var/www/teggl/fontify/venv/lib/python3.12/site-packages/scipy/_lib/pyprima/common/powalg.pyqradd_Rdiagr$      s   ( 	

AE 
AB
#a&#a&
!C 
SS\R	TT*13R	SB
 1Q3!R  &r!A#w<! Aac#A$Qq1ac({^QSS9Aa!QqSkN2a!9%BqE& 	1ur!u:Qwr!uc!f'=FA 	1uza!eai!a%ya!e.SA......CJ#!#####ww1a&   eQ;9 Ss   F
c                    | j                   \  }}|dk\  r||k  sJ |dk\  r||k  sJ t        |      |k(  sJ |j                   d   |k(  r$|j                   d   |k\  r|j                   d   |k  sJ |dk  s||k\  r||fS t        ||dz
        D ]^  }t        ||dz      t	        |dd|f   | dd|dz   f         g      }t        |dd|dz   |gf   |j                        |dd||dz   gf<   ` t        ||dz
        D cg c]  }t	        |dd|f   | dd|dz   f         ! c}|||dz
   t	        |dd|dz
  f   | dd|f         ||dz
  <   ||fS c c}w )a[  
    This function updates the QR factorization for an MxN matrix A=Q@R so that the updated Q and
    R form a QR factorization of [A_0, ..., A_{I-1}, A_{I+1}, ..., A_{N-1}, A_I] which is the matrix
    obtained by rearranging columns [I, I+1, ... N-1] of A to [I+1, ..., N-1, I]. Here A is ASSUMED TO
    BE OF FULL COLUMN RANK, Q is a matrix whose columns are orthogonal, and R, which is not present,
    is an upper triangular matrix whose diagonal entries are nonzero. Q and R need not be square.
    N.B.:
    0. Instead of R, this function updates Rdiag, which is np.diag(R), the size being n.
    1. With L = Q.shape[1] = R.shape[0], we have M >= L >= N. Most often L = M or N.
    2. This function changes only Q[:, i:] and Rdiag[i:]
    3. (NDB 20230919) In Python, i is either icon or nact - 2, whereas in FORTRAN it is either icon or nact - 1.
    r   r   N)r   r   r   r   r   r   r   )Ar   r   ir   r   r!   r"   s           r#   qrexc_Rdiagr(   L   s    77DAq 6a1f6a!eu:??771:?qwwqzQ1771:?BB
 	1uQ%x 1ac] 8eAaCj&1a4!AqsF)"<=> 1qsAh;!##7!a1X+8 9>a1F1F1QT7Aa1fI.FE!AaCL!QqS&	1QT7+E!A#Je8O Gs   ?$E)__doc__numpyr   linalgr   r   r   r   r   constsr	   r
   r$   r(        r#   <module>r/      s#     = = "9x7r.   