int PLA_Obj_set_to_identity( PLA_Obj A )
{
  int length, width;
  PLA_Obj A11 = NULL,     ABR = NULL;

  PLA_Obj_global_length( A, &length );
  PLA_Obj_global_width( A, &width );

  if ( length != width ){
    printf("PLA_Obj_set_to_identity() error:  object not square\n");
    exit ( 0 );
  }

  PLA_Obj_set_to_zero( A );
  PLA_Obj_view_all( A, &ABR );
  
  while ( TRUE ){
    PLA_Obj_global_length( ABR, &length );
    if ( 0 == length ) break;
    
    PLA_Obj_split_4( ABR, 1, 1, &A11,      PLA_DUMMY,
                                 PLA_DUMMY, &ABR );

    PLA_Obj_set_to_one( A11 );
  }

  PLA_Obj_free( &A11 );
  PLA_Obj_free( &ABR );

  return PLA_SUCCESS;
}
Exemplo n.º 2
0
static int pmatfactor(void*MM, int *flag){
  plapackM* ctx=(plapackM*)MM;
  int info,dummy;
  double ddxerror;
  DSDPFunctionBegin;
  wallclock(&ctx->t1);
  info=PLA_Obj_set_to_one(ctx->wVec);DSDPCHKERR(info);
  info=PLA_Obj_set_to_zero(ctx->vVec);DSDPCHKERR(info);
  info=PLA_Symv( PLA_LOWER_TRIANGULAR, ctx->one, ctx->AMat, ctx->wVec, ctx->zero, ctx->vVec ); DSDPCHKERR(info);
  *flag=0;
  info = PLA_Chol(PLA_LOWER_TRIANGULAR, ctx->AMat); DSDPCHKERR(info);
  if (info!=0) {
    *flag=1;
    printf("PLAPACK WARNING: Non positive-definite Matrix M : Row: %d\n",info);
  }
  info = PLA_Trsv(PLA_LOWER_TRIANGULAR, PLA_NO_TRANSPOSE, PLA_NONUNIT_DIAG, ctx->AMat, ctx->vVec);DSDPCHKERR(info);
  info = PLA_Trsv(PLA_LOWER_TRIANGULAR, PLA_TRANSPOSE, PLA_NONUNIT_DIAG, ctx->AMat,ctx->vVec); DSDPCHKERR(info);  

  info=PLA_Obj_set_to_minus_one(ctx->wVec);DSDPCHKERR(info); 
  info=PLA_Axpy( ctx->one, ctx->vVec, ctx->wVec );DSDPCHKERR(info); 
  info=PLA_Nrm2( ctx->wVec, ctx->dxerror );DSDPCHKERR(info); 
  PLA_Obj_get_local_contents( ctx->dxerror, PLA_NO_TRANS, &dummy, &dummy,
			      &ddxerror, 1, 1 );
  if (ddxerror/sqrt(1.0*ctx->global_size) > 0.1){
    *flag=1;
    if (ctx->rank==-1){
      printf("PDSDPPLAPACK: Non positive-definite Matrix. %4.2e\n",ddxerror);
    }
  }
  wallclock(&ctx->t2);
  ctx->tsolve+=ctx->t2-ctx->t1;
  PPDSDPPrintTime(ctx->rank,"PLAPACK: Factor M",ctx->t2-ctx->t1,ctx->tsolve);
  PPDSDPPrintTime(ctx->rank,"Subtotal Time",0,ctx->t2-ctx->t1);
  DSDPFunctionReturn(0);
}
Exemplo n.º 3
0
int pmatsetup(void *MM, int m){
  plapackM* ctx=(plapackM*)MM;
  MPI_Comm rowcomm,colcomm;
  int itmp,nprocs,info;

  DSDPFunctionBegin;
  ctx->global_size=m;

  info = MPI_Comm_size(ctx->mpi_comm,&nprocs); DSDPCHKERR(info);
  itmp=(m-nprocs+1)/nprocs;
  itmp=DSDPMax(2,itmp);
  ctx->nb_distr=DSDPMin(ctx->nb_distr,itmp);

  info = PLA_Comm_1D_to_2D_ratio(ctx->mpi_comm,ctx->ratio,&ctx->plapack_comm); DSDPCHKERR(info);
  info = PLA_Init(ctx->plapack_comm); DSDPCHKERR(info);
  info = PLA_Temp_create(ctx->nb_distr, 0, &ctx->templ); DSDPCHKERR(info);

  info=PLA_Matrix_create(MPI_DOUBLE, m, m, ctx->templ,
			 PLA_ALIGN_FIRST, PLA_ALIGN_FIRST, &ctx->AMat);DSDPCHKERR(info);  
  info=PLA_Mvector_create(MPI_DOUBLE, m, 1, ctx->templ, PLA_ALIGN_FIRST, &ctx->vVec);DSDPCHKERR(info);  
  info=PLA_Mvector_create(MPI_DOUBLE, m, 1, ctx->templ, PLA_ALIGN_FIRST, &ctx->wVec);DSDPCHKERR(info);  
  info=PLA_Mscalar_create( MPI_DOUBLE, PLA_ALL_ROWS, PLA_ALL_COLS, 1, 1, ctx->templ, &ctx->dxerror );DSDPCHKERR(info);  
  info=PLA_Mscalar_create( MPI_DOUBLE, PLA_ALL_ROWS, PLA_ALL_COLS, 1, 1, ctx->templ, &ctx->one );DSDPCHKERR(info);
  info=PLA_Mscalar_create( MPI_DOUBLE, PLA_ALL_ROWS, PLA_ALL_COLS, 1, 1, ctx->templ, &ctx->zero );DSDPCHKERR(info);
  info=PLA_Obj_set_to_one(ctx->one);DSDPCHKERR(info);
  info=PLA_Obj_set_to_zero(ctx->zero);DSDPCHKERR(info);

  info = MPI_Comm_rank(ctx->plapack_comm,&ctx->rank); DSDPCHKERR(info);
  info = MPI_Comm_size(ctx->plapack_comm,&ctx->nprocs); DSDPCHKERR(info);

  info = PLA_Temp_comm_col_info(ctx->templ, &rowcomm, &ctx->rowrank, &ctx->numrownodes); DSDPCHKERR(info);
  info = PLA_Temp_comm_row_info(ctx->templ, &colcomm, &ctx->colrank, &ctx->numcolnodes); DSDPCHKERR(info);

  ctx->t0=0;ctx->t1=0;ctx->t2=0;
  ctx->thessian=0;ctx->tsolve=0;
  wallclock(&ctx->t0);
  DSDPFunctionReturn(0);
}
Exemplo n.º 4
0
int PLA_Bi_red( PLA_Obj A, PLA_Obj sL, PLA_Obj sR, PLA_Obj U, PLA_Obj V )
/*
  PLA_Tri_red

  Purpose: Reduce general matrix A to bidiagonal form using 
  Householder similarity transformations.

  input:
  A                       MATRIX to be reduced

  output:
  A                       Reduced matrix A.  Householder vectors used
                          to reduce A are stored below subdiagonal
                          of A and above first superdiagonal of A.
  sL                      Scaling factors for the Householder transforms
                          computed to reduce A (applied to left of A).
  sR                      Scaling factors for the Householder transforms
                          computed to reduce A (applied to right of A).
  U                       if U != NULL, U equals the accumulation of 
                          Householder transforms that were applied from the
                          left.
  V                       if V != NULL, V equals the accumulation of 
                          Householder transforms that were applied from the
                          right.
*/
{
  PLA_Obj
    uv = NULL,  uv_B = NULL, u = NULL,  v = NULL,
    sR_B = NULL, betaR_1 = NULL, betaR_1_dup = NULL,
    sL_B = NULL, betaL_1 = NULL, betaL_1_dup = NULL,
    A_BR = NULL, a_21 = NULL, A_21 = NULL, 
    u_11 = NULL, u_12 = NULL, u_21 = NULL, U_22 = NULL;
    v_11 = NULL, v_12 = NULL, v_21 = NULL, V_22 = NULL;
  int
    size, value = PLA_SUCCESS;

  if ( PLA_ERROR_CHECKING )    /* Perform parameter and error checking */
    value = PLA_Bi_red_enter( A, sR, sL, U, V );

  /* The whole purpose of the game is to update most of the matrix
     A = A - ( u | w_R ) / 0 | w_L^T \
                         \ 0 | v^T   /
     where u equals the Householder transform that hits
     the active part of A from the left and
     v equals the Householder transform that hits the active
           part from the right:
     A <- ( I - betaL_1 u u^T ) A ( I - betaR_1 / 0 \ ( 0 v^T ) 
                                                \ v /                 */

  /* Create a multivector in which to compute ( u  |  w_R ) */

  PLA_Mvector_create_conf_to( A, 1, &uwR );

  /* Create a multivector in which to compute ( w_L | v ) */

  PLA_Mvector_create_conf_to( A, 1, &wLv );
  
  /* Create duplicated multiscalars in which to hold the scaling factor
     for the Householder transforms being computed */
  PLA_Obj_horz_split_2( sL, 1, &betaL_1,
			      PLA_DUMMY );
  PLA_Mscalar_create_conf_to( betaL_1, PLA_ALL_ROWS, PLA_ALL_COLS, 
			      &betaL_1_dup );
  PLA_Obj_horz_split_2( sR, 1, &betaR_1,
			      PLA_DUMMY );
  PLA_Mscalar_create_conf_to( betaR_1, PLA_ALL_ROWS, PLA_ALL_COLS, 
			      &betaR_1_dup );

  /* Track the active parts of A, sL, sR, and uwR and wLv */
  PLA_Obj_view_all( A, &A_BR );    
  PLA_Obj_view_all( sL, &betaL_B );    
  PLA_Obj_view_all( sR, &betaR_B );    
  PLA_Obj_view_all( uwR, &uwR_B );
  PLA_Obj_horz_split_2( wLv, 1, PLA_DUMMY,
                                &wLv_B );

  while ( TRUE ){  
    PLA_Obj_global_length( A_BR, &size );
    if ( 0 == size ) break;

    /* Partition A_BR = ( a_L      A_R    ) where a_L is a column from
       which to compute the next u */
    PLA_Obj_vert_split_2( A_BR, 1, &a_L, &A_R );
    /* Split of the current element of vector sL */
    PLA_Obj_horz_split_2( betaL_B, 1, &betaL_1,
                                      &betaL_B );
    /* View the part of uwR in which to compute u and wR */
    PLA_Obj_vert_split_2( uwR_B, 1,  &u, &wR );

    /* View the part of wLv in which to compute w_L and v */
    PLA_Obj_vert_split_2( wLv_B, 1,  &w_L, &v );

    /* Redistributed a_L as a vector and compute Householder transform */
    PLA_Copy( a_L, u );  
    PLA_Compute_House_v( u, betaL_1_dup );

    /* Place data back in A and sL */
    PLA_Copy( u, a_L );
    PLA_Local_copy( betaL_1_dup, betaL_1 );

    /* Partition A_BR = /  *    a_12^T \  
                        \  *    A_22   / splitting off first column and row */
    PLA_Obj_vert_split_4( A_BR, 1, 1, PLA_DUMMY, &a_12,
                                      PLA_DUMMY, &A_BR );
    
    /* Copy a_12 into v */
    PLA_Obj_set_orientation( PLA_PROJ_ONTO_ROW, a_12 );
    PLA_Copy( a_12, v );
    
    /* w_L = betaL_1 * A_BR^T * u */
       First must split off first element of u */
    PLA_Obj_horz_split_2( u, 1, PLA_DUMMY,
			        &u_2 );

    PLA_Gemv( PLA_TRANSPOSE, betaL_1_dup, A_BR, u_2, zero, w_L );

    /* In v update a_12 = a_12 - betaL_1 * A_R^T u = 
                        = a_12 - betaL_1 * a_12 - w_L */

    PLA_Negate( betaL_1 );
    PLA_Axpy( betaL_1, v, v );
    PLA_Axpy( minus_one, w_L, v );

    /* Compute Householder transform to reflect resulting v */
    PLA_Compute_House_v( v, betaR_1_dup );

    /* Place data back in A and sR */
    PLA_Copy( v, a_12 );
    PLA_Local_copy( betaR_1_dup, betaR_1 );

    /* Set first element of v = 1 */
    PLA_Obj_horz_split_2( v, 1, &v_1,
			        PLA_DUMMY );
    PLA_Obj_set_to_one( v_1 );

    /* Update A_BR <- ( I - betaL_1 u_2 u_2^T ) A_BR ( I - betaR_1 v v^T )
                   =  ( A_BR - u_2 ( betaL_1 u_2^T A_BR ) ) ( I - betaR_1 v v^T )
		   =  A_BR - ( u_2 | w_R ) * ( w_L | v )
       where w_L = betaL_1 * A_BR^T u_2,  w_R = betaR_1 * A_BR * v - betaR_1 * w_L^T * v * u_2 
    */
    
    /* Compute w_R */
    PLA_Gemv( PLA_NO_TRANSPOSE, betaR_1, A_BR, v, zero, w_R );
    PLA_Dot( x_L, v, temp );
    PLA_Scal( betaR_1_dup, temp );
    PLA_Negate( temp );
    PLA_Axpy( temp, u_2, w_R );

    /* Update A_BR */
    PLA_Pmvector_create_conf_to( A_BR, PLA_PROJ_ONTO_COL, PLA_ALL_COLS, 2, &uwR_2_dup );
    PLA_Copy( uwR_2, uwR_2_dup );

    PLA_Pmvector_create_conf_to( A_BR, PLA_PROJ_ONTO_ROW, PLA_ALL_ROWS, 2, &wLv_dup );
    PLA_Copy( wLv, wLv_dup );
    
    PLA_Gemm( PLA_NO_TRANSPOSE, PLA_NO_TRANSPOSE, minus_one, uwR_2, wLv, one, A_BR );
  }

  /* Free the temporary objects */
  PLA_Obj_free( &u );
  PLA_Obj_free( &u_B );
  PLA_Obj_free( &beta_B );
  PLA_Obj_free( &beta_1 );
  PLA_Obj_free( &beta_1_dup );
  PLA_Obj_free( &A_BR );
  PLA_Obj_free( &a_21 );
  PLA_Obj_free( &A_21 );
  PLA_Obj_free( &q_11 );
  PLA_Obj_free( &q_12 );
  PLA_Obj_free( &q_21 );
  PLA_Obj_free( &Q_22 );

  if ( PLA_ERROR_CHECKING )   
    value = PLA_Bi_red_exit( A, sL, sR, U, V );

  return PLA_SUCCESS;
}
int PLA_Compute_WY( PLA_Obj A_mv, PLA_Obj s, PLA_Obj W_mv, PLA_Obj Y_mv )

/* to use this routine, we need to modify the calling of
* PLA_QR_right
*/
/*
  Purpose: Compute WY transform from Householder vectors stored
           in A and s.

  Note: Utility routine used as part of computation of QR factorization
        of a matrix.
           
  Input:  A_mv    --   General mxn matrix A   
                       (PLA_MVECTOR)
          s       --   vector of scaling factors
                       (MSCALAR of width=n, duplicated to all nodes)
          W_mv, Y_mv
                  --   matrices for storing W and Y which define the 
                       WY transform.
                       (PLA_MVECTOR of width n)

  Output: W_mv, Y_mv
                  --   W and Y which define the WY transform.

  Assumptions:  n<=m

  Return value: PLA_SUCCESS unless input parameter error is detected.
*/
{
  PLA_Obj   a_B1    = NULL,   A_mv_BR = NULL,   
            s_cur   = NULL,   beta    = NULL,   
            W_L     = NULL,   w_1     = NULL,   W_R = NULL,
            W_BR    = NULL,   w_B1    = NULL,
            Y_BL    = NULL,   y_B1    = NULL,   Y_BR = NULL,
            y_11    = NULL,   u_loc   = NULL,   u    = NULL,
                              u_loc_L = NULL,   u_L  = NULL,
            minus_one = NULL, zero    = NULL,   one     = NULL;
  int       global_width;

  PLA_Create_constants_conf_to( A_mv, &minus_one, &zero, &one );

  PLA_Obj_set_to_zero( W_mv );
  PLA_Obj_set_to_zero( Y_mv );


  /* A_mv_BR tracks the active part of A_mv */
  PLA_Obj_view_all( A_mv, &A_mv_BR );
  /* s_cur   tracks the active part of s */
  PLA_Obj_view_all( s,    &s_cur );

  /* W_L tracks the part of W already computed, W_R the part yet to be 
     computed.  Ditto for W_BR, Y_BL and Y_BR */  
  PLA_Obj_vert_split_2( W_mv, 0,  &W_L,      &W_R );
  PLA_Obj_vert_split_2( W_mv, 0,  PLA_DUMMY, &W_BR );
  PLA_Obj_vert_split_2( Y_mv, 0,  &Y_BL,     &Y_BR );

  /* Create duplicated multiscalar to hold u and local contributions to u */
  PLA_Mscalar_create_conf_to( s, PLA_ALL_ROWS, PLA_ALL_COLS, &u );
  PLA_Mscalar_create_conf_to( s, PLA_ALL_ROWS, PLA_ALL_COLS, &u_loc );

  /* u_L and u_loc_L tracks the part of u and u_loc 
     corresponding to Y_BL and Y_BR, respectively */
  PLA_Obj_horz_split_2( u, 0,      &u_L,     PLA_DUMMY );
  PLA_Obj_horz_split_2( u_loc, 0,  &u_loc_L, PLA_DUMMY );

  while( TRUE ){
    PLA_Obj_global_width( A_mv_BR, &global_width );
    if ( 0 == global_width ) break;

    /* Split off next column of A_mv_BR and columns of W and Y 
       to be computed */
    PLA_Obj_vert_split_2( A_mv_BR,  1,     &a_B1, PLA_DUMMY );
    PLA_Obj_vert_split_2( W_R,      1,     &w_1,  &W_R );
    PLA_Obj_vert_split_2( W_BR,     1,     &w_B1, PLA_DUMMY );
    PLA_Obj_vert_split_2( Y_BR,     1,     &y_B1, PLA_DUMMY );

    /* Split off current scaling factor beta */
    PLA_Obj_horz_split_2( s_cur,    1,     &beta,
                                           &s_cur );

    /* y_B1 = a_B1 with first element set to 1 */
    PLA_Local_copy( a_B1, y_B1 );
    PLA_Obj_horz_split_2( y_B1, 1, &y_11, 
                                   PLA_DUMMY );
    PLA_Obj_set_to_one( y_11 );

    /* w_1 = - beta ( /   0   \
                    \  y_B1 / + W_L Y_BL y_B1 ) */
    PLA_Local_copy( y_B1, w_B1 );

    PLA_Local_gemv( PLA_TRANS, one, Y_BL, y_B1, zero, u_loc_L );

    PLA_Reduce( u_loc_L, MPI_SUM, u_L );

    PLA_Obj_global_width( W_L, &global_width );
    if ( global_width > 0 )
      PLA_Local_gemv( PLA_NO_TRANS, one, W_L, u_L, one, w_1 );

    PLA_Local_scal( beta, w_1 );
/*    PLA_Local_scal( minus_one, w_1 ); */

    /* Update views */
    PLA_Obj_view_shift( W_L,    0,
                            0,      1,
                                0 );

    PLA_Obj_view_shift( Y_BL,    1,
                            0,        1,
                                 0 );


    PLA_Obj_view_shift( u_L,     0,
                            0,        0,
                                 1 );

    PLA_Obj_view_shift( u_loc_L,     0,
                               0,        0,
                                     1 );
    
    PLA_Obj_split_4( A_mv_BR, 1, 1,   PLA_DUMMY, PLA_DUMMY,
                                      PLA_DUMMY, &A_mv_BR);
    PLA_Obj_split_4( Y_BR, 1, 1,      PLA_DUMMY, PLA_DUMMY,
                                      PLA_DUMMY, &Y_BR );
    PLA_Obj_split_4( W_BR,    1, 1,   PLA_DUMMY, PLA_DUMMY,
                                      PLA_DUMMY, &W_BR );
  }

  /* Clean up temporary objects */
  PLA_Obj_free( &a_B1 );    PLA_Obj_free( &A_mv_BR );   
  PLA_Obj_free( &s_cur );  PLA_Obj_free( &beta );   
  PLA_Obj_free( &W_L );    PLA_Obj_free( &w_1 );   PLA_Obj_free( &W_R );
  PLA_Obj_free( &W_BR );    PLA_Obj_free( &w_B1 );
  PLA_Obj_free( &Y_BL );   PLA_Obj_free( &y_B1 );   PLA_Obj_free( &Y_BR );
  PLA_Obj_free( &y_11 ); 
  PLA_Obj_free( &u );    PLA_Obj_free( &u_loc ); 
  PLA_Obj_free( &u_L );    PLA_Obj_free( &u_loc_L ); 
  PLA_Obj_free( &minus_one );
  PLA_Obj_free( &zero );   PLA_Obj_free( &one );

  return PLA_SUCCESS;
}  
int PLA_Apply_sym_House( int uplo, PLA_Obj A, PLA_Obj u, PLA_Obj beta )
/*
  PLA_Apply_sym_House

  Purpose:
  
  Apply a Householder orthogonal similarity transformation to
  matrix A:

  Form    A <- ( I + beta u u^T ) A ( I + beta u u^T )
            =  A + beta u w^T + beta w u^T
   where w = v + beta/2 u^T v u   and  v = A u

   Assumptions:
   A is a PLA_MATRIX, u is a PLA_MVECTOR of width 1 with
   (implicitly) unit first entry, and beta is a PLA_MSCALAR
   duplicated on all nodes.
*/
{
  PLA_Obj
    u_1 = NULL, u_1_copy = NULL,  
    v = NULL, 
    zero = NULL, one = NULL, two = NULL,
    alpha = NULL; 
  double 
    d_two = 2.0;

  PLA_Create_constants_conf_to( A, NULL, &zero, &one );

  /* Set first entry of u to one, saving the old value in u_1_copy */
  PLA_Obj_horz_split_2( u, 1, &u_1,
                               PLA_DUMMY );
  PLA_Mvector_create_conf_to( u_1, 1, &u_1_copy );
  PLA_Local_copy( u_1, u_1_copy );
  PLA_Obj_set_to_one( u_1 );

  /* Compute v = A u */
  PLA_Mvector_create_conf_to( u, 1, &v );
  PLA_Symv( uplo, one, A, u, zero, v );

  /* Compute alpha = u^T v */
  PLA_Mscalar_create_conf_to( beta, PLA_ALL_ROWS, PLA_ALL_COLS, &alpha );
  PLA_Dot( u, v, alpha );

  /* Compute alpha = beta/2 * u^T v */
  PLA_Mscalar_create_conf_to( beta, PLA_ALL_ROWS, PLA_ALL_COLS, &two );
  PLA_Obj_set( two, MPI_DOUBLE, &d_two );

  PLA_Local_scal( beta, alpha );
  PLA_Local_inv_scal( two, alpha );

  /* Compute v = w = v + beta/2 * u^T v u */
  PLA_Local_axpy( alpha, u, v );

  /* Update A = A + beta u w^T + beta w u^T */
  PLA_Syr2( uplo, beta, u, v, A );

  /* Restore first entry of u */
  PLA_Local_copy( u_1_copy, u_1 );

  /* Free temporary objects */
  PLA_Obj_free( &u_1 );
  PLA_Obj_free( &u_1_copy );
  PLA_Obj_free( &v );
  PLA_Obj_free( &zero );
  PLA_Obj_free( &one );
  PLA_Obj_free( &two );
  PLA_Obj_free( &alpha );

  return PLA_SUCCESS;
}
Exemplo n.º 7
0
int PLA_Tri_red( int uplo, PLA_Obj A, PLA_Obj s, PLA_Obj Q )
/*
  PLA_Tri_red

  Purpose: Reduce symmetric matrix A to tridiagonal form using 
  Householder similarity transformations.

  input:
  uplo                    indicates whether A is stored in upper or
                          lower triangular part 
  A                       MATRIX to be reduced

  output:
  A                       Reduced matrix A.  Householder vectors used
                          to reduce A are stored below first subdiagonal
                          of A.
  s                       Scaling factors for the Householder transforms
                          computed to reduce A.
  Q                       if Q != NULL, Q equals the accumulation of 
                          Householder transforms.
*/
{
  PLA_Obj
    u = NULL,  u_B = NULL, 
    beta_B = NULL, beta_1 = NULL, beta_1_dup = NULL,
    A_BR = NULL, a_21 = NULL, A_21 = NULL, 
    q_11 = NULL, q_12 = NULL, q_21 = NULL, Q_22 = NULL;
  int
    size, value = PLA_SUCCESS;
  double time;

  if ( PLA_ERROR_CHECKING )    /* Perform parameter and error checking */
    value = PLA_Tri_red_enter( uplo, A, s, Q );

  if ( uplo != PLA_LOWER_TRIANGULAR ) 
    PLA_Abort( "only uplo == PLA_LOWER_TRIANGULAR currently supported",
		__LINE__, __FILE__ );

  /* Create a vector in which to compute the Householder vector */
  PLA_Mvector_create_conf_to( A, 1, &u );
  
  /* Create a duplicated multiscalar in which to hold the scaling factor
     for the Householder transform being computed */
  PLA_Obj_horz_split_2( s, 1, &beta_1,
			      PLA_DUMMY );
  PLA_Mscalar_create_conf_to( beta_1, PLA_ALL_ROWS, PLA_ALL_COLS, 
			      &beta_1_dup );

  /* Track the active parts of A, s, and u */
  PLA_Obj_view_all( A, &A_BR );    
  PLA_Obj_view_all( s, &beta_B );    
  PLA_Obj_view_all( u, &u_B );

  while ( TRUE ){  
    PLA_Obj_global_length( A_BR, &size );
    if ( 1 == size ) break;

    /* Partition A_BR = / alpha_11    *    \
                        \   a_21    A_BR   /  where alpha_11 is 1x1 */
    PLA_Obj_split_4( A_BR, 1, 1, PLA_DUMMY, PLA_DUMMY,
    		                 &a_21,     &A_BR );
    /* Split of the current element of vector s */
    PLA_Obj_horz_split_2( beta_B, 1, &beta_1,
                                     &beta_B );
    /* View the part of u in which to compute the Householder vector */
    PLA_Obj_horz_split_2( u_B, 1, PLA_DUMMY,
			          &u_B );

    /* Redistributed a_21 as a vector and compute Householder transform */
    PLA_Copy( a_21, u_B );  
    PLA_Compute_House_v( u_B, beta_1_dup );

    /* Place data back in A and s */
    PLA_Copy( u_B, a_21 );
    PLA_Local_copy( beta_1_dup, beta_1 );

    /* Update A_BR <- ( I - beta_1 u_B u_B^T ) A_BR ( I - beta_1 u_B u_B^T ) */
    PLA_Apply_sym_House( uplo, A_BR, u_B, beta_1_dup );
  }
  
  time = MPI_Wtime ();

  if ( Q != NULL ){
    /* Compute the orthogonal matrix */
    PLA_Obj_split_4( Q, 1, 1, &q_11, &q_12,
		              &q_21, &Q_22 );

    PLA_Obj_set_to_one ( q_11 );
    PLA_Obj_set_to_zero( q_12 );
    PLA_Obj_set_to_zero( q_21 );

    PLA_Obj_split_4( A, 1, -1, PLA_DUMMY, PLA_DUMMY,
		                &A_21,     PLA_DUMMY );

    PLA_Form_Q( PLA_NO_TRANSPOSE, A_21, s, Q_22 );
  }

  time = MPI_Wtime () - time;
  printf( " Form_Q = %f\n", time );



  /* Free the temporary objects */
  PLA_Obj_free( &u );
  PLA_Obj_free( &u_B );
  PLA_Obj_free( &beta_B );
  PLA_Obj_free( &beta_1 );
  PLA_Obj_free( &beta_1_dup );
  PLA_Obj_free( &A_BR );
  PLA_Obj_free( &a_21 );
  PLA_Obj_free( &A_21 );
  PLA_Obj_free( &q_11 );
  PLA_Obj_free( &q_12 );
  PLA_Obj_free( &q_21 );
  PLA_Obj_free( &Q_22 );

  if ( PLA_ERROR_CHECKING )   
    value = PLA_Tri_red_exit( uplo, A, s, Q );

  return PLA_SUCCESS;
}