bridge/class-master/depend/pari/src/basemath/alglin1.c
/* find Z such that A Z = B. Return NULL if no solution */
find Z such that A Z = B. Return NULL if no solution
find Z such that A Z = B . Return NULL if no solution
GEN
gen_matinvimage(GEN A, GEN B, void *E, const struct bb_field *ff)
{
  pari_sp av = avma;
  GEN d, x, X, Y;
  long i, j, nY, nA, nB;
  x = gen_ker(shallowconcat(gen_matneg(A, E, ff), B), 0, E, ff);
  nY = lg(x) - 1;
  nB = lg(B) - 1;
  if (nY < nB) { avma = av; return NULL; }
  nA = lg(A) - 1;
  Y = rowslice(x, nA + 1, nA + nB); 
  d = cgetg(nB + 1, t_VECSMALL);
  for (i = nB, j = nY; i >= 1; i--, j--) {
    for (; j >= 1; j--)
      if (!ff->equal0(gcoeff(Y, i, j))) { d[i] = j; break; }
    if (!j) { avma = av; return NULL; }
  }
  Y = vecpermute(Y, d);
  x = vecpermute(x, d);
  X = rowslice(x, 1, nA);
  return gerepileupto(av, gen_matmul(X, gen_matinv_upper(Y, E, ff), E, ff));
}
GEN gen_matinvimage ( GEN A , GEN B , void * E , const struct bb_field * ff ) { pari_sp av = avma ; GEN d , x , X , Y ; long i , j , nY , nA , nB ; x = gen_ker ( shallowconcat ( gen_matneg ( A , E , ff ) , B ) , 0 , E , ff ) ; nY = lg ( x ) - 1 ; nB = lg ( B ) - 1 ; if ( nY < nB ) { avma = av ; return NULL ; } nA = lg ( A ) - 1 ; Y = rowslice ( x , nA + 1 , nA + nB ) ; d = cgetg ( nB + 1 , t_VECSMALL ) ; for ( i = nB , j = nY ; i >= 1 ; i -- , j -- ) { for ( ; j >= 1 ; j -- ) if ( ! ff -> equal0 ( gcoeff ( Y , i , j ) ) ) { d [ i ] = j ; break ; } if ( ! j ) { avma = av ; return NULL ; } } Y = vecpermute ( Y , d ) ; x = vecpermute ( x , d ) ; X = rowslice ( x , 1 , nA ) ; return gerepileupto ( av , gen_matmul ( X , gen_matinv_upper ( Y , E , ff ) , E , ff ) ) ; }
find Z such that A Z = B.
find Z such that A Z = B .
/* AX = BY, Y in strict upper echelon form with pivots = 1.
   * We must find T such that Y T = Id_nB then X T = Z. This exists
   * iff Y has at least nB columns and full rank. */ /* nB rows */ /* reduce to the case Y square, upper triangular with 1s on diagonal */