#include "FLAME.h"

void FLA_LU( FLA_Obj A, FLA_Obj ipiv, int nb_alg )
{
  FLA_Obj
    ATL, ATR,   A00, A01, A02,  ipivT,  ipiv0,
    ABL, ABR,   A10, A11, A12,  ipivB,  ipiv1,
                A20, A21, A22,          ipiv2;

  int b;

  FLA_Part_2x2( A,  &ATL, /**/ &ATR,
  	          /* ************** */
		    &ABL, /**/ &ABR, 
		/* with */ 0, /* by */ 0, /* submatrix */ FLA_TL );

  FLA_Part_2x1( ipiv, &ipivT,
  		   /* ****** */
	              &ipivB,   
		/* with */ 0, /* length submatrix */ FLA_TOP );

  while ( b = min( min( FLA_Obj_length( ABR ), FLA_Obj_width( ABR ) ), nb_alg ) ){

    FLA_Repart_2x1_to_3x1( ipivT,                 &ipiv0,
                        /* ***** */             /* ***** */
		                                  &ipiv1,
                           ipivB,                 &ipiv2,                
                /* with */ b, /* length ipiv1 split from */ FLA_BOTTOM );

    /* ************************************************************************* */

    FLA_Part_1x2( ABR,   &ABR_1, &ABR_2, /* with */ b, /* width submatrix */ FLA_LEFT );

    FLA_LU_level2( ABR_1, ipiv1 );
    FLA_Apply_pivots( FLA_SIDE_LEFT, FLA_NO_TRANSPOSE, ipiv1, ABL );
    FLA_Apply_pivots( FLA_SIDE_LEFT, FLA_NO_TRANSPOSE, ipiv1, ABR_2 );

    /* ************************************************************************* */

    FLA_Repart_2x2_to_3x3( ATL, /**/ ATR,         &A00, /**/ &A01, &A02,
                        /* ************* */    /* ********************* */
		                /**/              &A10, /**/ &A11, &A12,
                           ABL, /**/ ABR,         &A20, /**/ &A21, &A22, 
                /* with */ b, /* by */ b, /* A11 split from */ FLA_BR );

    /* ************************************************************************* */

    FLA_Trsm( FLA_SIDE_LEFT, FLA_LOWER_TRIANGULAR, FLA_NO_TRANSPOSE, FLA_UNIT_DIAG,    
	      ONE, A11, A12 );

    FLA_Gemm( FLA_NO_TRANSPOSE, FLA_NO_TRANSPOSE, MINUS_ONE, A21, A12, ONE, A22 );

    /* ************************************************************************* */

    FLA_Cont_with_3x3_to_2x2( &ATL, /**/ &ATR,         A00, A01, /**/ A02,
		                    /**/               A10, A11, /**/ A12,
                            /* ************** */    /* ****************** */
                              &ABL, /**/ &ABR,         A20, A21, /**/ A22, 
                /* with A11 added to submatrix */ FLA_TL );

    FLA_Cont_with_3x1_to_2x1( &ipivT,                  ipiv0,
		                                       ipiv1,
                            /* ***** */             /* ***** */
                              &ipivB,                  ipiv2,              
                /* with ipiv1 added to */ FLA_TOP );
  }
}
