Exemplo n.º 1
0
int main() {
  Problem * p = create_problem();
  MSK_writedata(p->task_, "ex6.mps");
  MSK_deletetask(&(p->task_));
  MSK_deleteenv(&(p->env_));
  delete p;
  return 0;
}
Exemplo n.º 2
0
/*
 * Runs the main program
 */
int main(int argc, char *argv[]) {
    int N, C, ans = 0;
    int max_weights;
    int weight[MAX], value[MAX];
    struct timeval tstart, tend;
    double t1, t2;

    thread_count = 6;
    N = strtol(argv[1], NULL, 10);
    C = strtol(argv[2], NULL, 10);
    max_weights = strtol(argv[3], NULL, 10);

    create_problem(N, max_weights, weight, value);

    gettimeofday(&tstart, NULL);
    ans = solve(N, C, weight, value);
    gettimeofday(&tend, NULL);


    t1 = check_time(tstart, tend);
    printf("Solver finished in %lf seconds.\n", t1/1000000.0);

    gettimeofday(&tstart, NULL);
    solve2(N, C, weight, value);
    gettimeofday(&tend, NULL);

    t2 = check_time(tstart, tend);

    double s_scaling = t2 / (thread_count * t1);

    printf("Solver finished in %lf seconds.\n", t2/1000000.0);
    printf("Answer: %d \n", ans);
    printf("Strong Scaling: %lf\n", s_scaling);

    return 0;
}
Exemplo n.º 3
0
int main(int argc, char *argv[])
{
    MPI_Comm
    comm = MPI_COMM_NULL;
    MPI_Datatype
    datatype;
    PLA_Template
    templ = NULL;
    PLA_Obj
    A      = NULL, A_orig = NULL, residual = NULL,
    minus_one   = NULL, one  = NULL, diff = NULL;
    int
    n,
    nb_distr, nb_alg,
    error, parameters, sequential,
    me, nprocs, nprows, npcols,
    itype;
    double
    time,
    flops;

    MPI_Init(&argc, &argv);

    MPI_Comm_rank(MPI_COMM_WORLD, &me);
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);

    if (me==0) {
        printf("enter mesh size:\n");
        scanf("%d%d", &nprows, &npcols );
        printf("mesh size  = %d x %d \n", nprows, npcols );
        printf("enter distr. block size:\n");
        scanf("%d", &nb_distr );
        printf("nb_distr = %d\n", nb_distr );
        printf("enter alg. block size:\n");
        scanf("%d", &nb_alg );
        printf("nb_alg = %d\n", nb_alg );
        printf("turn on error checking? (0 = NO, 1 = YES):\n");
        scanf("%d", &error );
        printf("error checking = %d\n", error );
        printf("turn on parameter checking? (0 = NO, 1 = YES):\n");
        scanf("%d", &parameters );
        printf("parameter checking = %d\n", parameters );
        printf("turn on sequential checking? (0 = NO, 1 = YES):\n");
        scanf("%d", &sequential );
        printf("sequential checking = %d\n", sequential );
    }
    MPI_Bcast(&nprows, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&npcols, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&nb_distr, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&nb_alg,   1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&error, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&parameters, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&sequential, 1, MPI_INT, 0, MPI_COMM_WORLD);

    pla_Environ_set_nb_alg( PLA_OP_ALL_ALG, nb_alg );

    PLA_Set_error_checking( error, parameters, sequential, FALSE );

    /*  PLA_Comm_1D_to_2D_ratio(MPI_COMM_WORLD, 1.0, &comm); */
    PLA_Comm_1D_to_2D(MPI_COMM_WORLD, nprows, npcols, &comm);

    PLA_Init(comm);

    PLA_Temp_create( nb_distr, 0, &templ );

    while ( TRUE ) {
        if (me==0) {
            printf("enter datatype:\n");
            printf("-1 = quit\n");
            printf(" 0 = float\n");
            printf(" 1 = double\n");
            printf(" 2 = complex\n");
            printf(" 3 = double complex\n");
            scanf("%d", &itype );
            printf("itype = %d\n", itype );
        }
        MPI_Bcast(&itype, 1, MPI_INT, 0, MPI_COMM_WORLD);

        if ( itype == -1 ) break;
        switch( itype ) {
        case 0:
            datatype = MPI_FLOAT;
            break;
        case 1:
            datatype = MPI_DOUBLE;
            break;
        case 2:
            datatype = MPI_COMPLEX;
            break;
        case 3:
            datatype = MPI_DOUBLE_COMPLEX;
            break;
        default:
            PLA_Abort( "unknown datatype", __LINE__, __FILE__ );
        }

        if (me==0) {
            printf("enter n:\n");
            scanf("%d", &n );
            printf("n = %d\n", n );
        }

        MPI_Bcast(&n,     1, MPI_INT, 0, MPI_COMM_WORLD);

        PLA_Matrix_create( datatype,
                           n,
                           n,
                           templ,
                           PLA_ALIGN_FIRST,
                           PLA_ALIGN_FIRST,
                           &A );

        PLA_Matrix_create_conf_to( A, &A_orig );

        PLA_Matrix_create_conf_to( A, &residual );

        create_problem( A );

        {
            double d_n;

            d_n = (double) n;
            PLA_Shift( A, MPI_DOUBLE, &d_n );
        }

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

        PLA_Local_copy( A, A_orig );

        /* Use invert routine that uses factors */

        MPI_Barrier( MPI_COMM_WORLD );
        time = MPI_Wtime ();

        PLA_Triangular_invert( PLA_LOWER_TRIANGULAR, A );

        MPI_Barrier( MPI_COMM_WORLD );
        time = MPI_Wtime () - time;

        flops = 2.0/3.0 * n * n * n;

        if ( me == 0 )
            printf("%d time = %f, MFLOPS/node = %10.4lf \n", n, time,
                   flops / time * 1.0e-6 / nprocs );

        PLA_Obj_set_to_identity( residual );

        PLA_Set_triang_to_zero( PLA_LOWER_TRIANGULAR, PLA_NONUNIT_DIAG,
                                A_orig );
        PLA_Set_triang_to_zero( PLA_LOWER_TRIANGULAR, PLA_NONUNIT_DIAG,
                                A );

        PLA_Gemm( PLA_NO_TRANS, PLA_NO_TRANS, minus_one, A_orig, A, one,
                  residual );

        PLA_Mscalar_create( datatype, PLA_ALL_ROWS, PLA_ALL_COLS,
                            1, 1, templ, &diff );

        PLA_Matrix_one_norm( residual, diff );
    }

    PLA_Obj_free( &A );
    PLA_Obj_free( &A_orig );
    PLA_Obj_free( &residual );
    PLA_Obj_free( &minus_one );
    PLA_Obj_free( &one );
    PLA_Obj_free( &diff );

    PLA_Temp_free(&templ);
    PLA_Finalize( );
    MPI_Finalize( );

}
Exemplo n.º 4
0
int main(){
  clock_t begin, end;
  double time_spent;
  begin = clock();

  matrix* Q = create_matrix(2,2);
  value Q_arr[4] = {	2, 0,
			0, 2};
  insert_array(Q_arr, Q);


  matrix* q = create_matrix(2, 1);
  value q_arr[2] = {  -2, 
		      -5};
  insert_array(q_arr, q);


  matrix* F = create_matrix(5, 2);
  value F_arr[10] = {  1, -2, 
		       -1, -2,
		       -1,  2, 
		       1,  0,
		       0,  1};
  insert_array(F_arr, F);


  matrix* g = create_matrix(5, 1);
  value g_arr[5] = { -2, 
		     -6, 
		     -2, 
		     0,
		     0};
  insert_array(g_arr, g);

  /* starting point */
  matrix* z = create_matrix(2,1);
  value z_arr[2] = {1, 
		    1};
  insert_array(z_arr, z);


  problem* problem = create_problem(Q, q, NULL, NULL, F, g, z, 0, 0);

  quadopt_solver(problem);

  matrix* expected = create_matrix(2, 1);
  value e_arr[2] = {1.4,
		    1.7};
  insert_array(e_arr, expected);

  assert(compare_matrices(problem->solution, expected));

  free_matrix(expected);
  free_problem(problem);

  end = clock(); 
  time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
  printf("time taken was: %f \n", time_spent);

  return 0;
}
Exemplo n.º 5
0
/** This functions creates an interface between MATLAB and the solver together with the matrixlibrary. 
    It also converts MATLAB structured matrices into the matrixlibrary structure. 
*/
void mexFunction(int nlhs, mxArray* plhs[],
		 int nrhs, const mxArray* prhs[]){ 
  /* Declare variables */
  int nr_of_matrices = nrhs-2; /* Number of matrices */
  mxArray* mat_matrix; /* Used to store the incoming matrices from MATLAB when converting to Matlib matrices. */
  double* out_matrix; /* Used to return the result back to MATLAB. */
  matrix* lib_matrix; /* Used to temporarily store the Matlib matrix that is created when converting the MATLAB matrix. */
  matrix* result_matrix; /* The Matlib matrix containing the result returned from the solver. */
  matrix* lib_matrices[nr_of_matrices]; /* An array of all the matrices that should be sent to the solver. */
  
  /* Check for proper number of arguments */
  if(nrhs != 9){
    mexErrMsgIdAndTxt("MyToolbox:quadopt:nrhs","Nine inputs required.");
  }

  /* Convert MATLAB matrises to library matrices */
  int i;
  for(i = 0; i < nr_of_matrices; i++){
    mat_matrix = prhs[i];

    /* If matrix is not empty, create_matrix else set it to NULL */
    if(!mxIsEmpty(mat_matrix)){
      int rows = (int)mxGetM(mat_matrix);
      int columns = (int)mxGetN(mat_matrix);
      lib_matrix = create_matrix(rows, columns);
      double* element_ptr = mxGetPr(mat_matrix);
      
      int x;
      for(x = 0; x < columns; x++){
	int y;
	for(y = 0; y < rows; y++){
	  insert_value(*element_ptr, y+1, x+1, lib_matrix);
	  element_ptr++;
	}
      }
      lib_matrices[i] = lib_matrix;
    }else{
      lib_matrices[i] = NULL;
    }
  }

  /* Convert max_iter and max_time to integers */
  int max_iter = (int)(*mxGetPr(prhs[7]));
  int max_time = (int)(*mxGetPr(prhs[8]));

  /* Create problem from solver.h with library matrices */
  problem* problem = create_problem(lib_matrices[0], lib_matrices[1], lib_matrices[2], lib_matrices[3], 
				    lib_matrices[4], lib_matrices[5], lib_matrices[6], max_iter, max_time);

  /* Solve problem */
  quadopt_solver(problem);

  /* Get the solution from the problem struct */
  result_matrix = problem->solution; 

  /* Convert resulting matrix to MATLAB matrix and set output matrix */
  plhs[0] = mxCreateDoubleMatrix(result_matrix->rows, result_matrix->columns, mxREAL);

  out_matrix = mxGetPr(plhs[0]);
  
  int x;
  for(x = 0; x < result_matrix->columns; x++){
    int y;
    for(y = 0; y < result_matrix->rows; y++){
      *out_matrix = get_value(y+1, x+1, result_matrix);
      out_matrix++;
    }
  }
  
  /* Free memory */
  for(i = 0; i < nr_of_matrices; i++){
    if(lib_matrices[i] != NULL){
      free_matrix(lib_matrices[i]);
    }
  }
  free_matrix(result_matrix);
}
Exemplo n.º 6
0
int main(int argc, char *argv[])
{
  MPI_Comm 
    comm = MPI_COMM_NULL;
  MPI_Datatype
    datatype;
  PLA_Template 
    templ = NULL;
  PLA_Obj  
    A      = NULL, pivots = NULL,
    zero   = NULL, one  = NULL;
  int      
    n,
    nb_distr, nb_alg,
    error, parameters, sequential,
    me, nprocs, nprows, npcols,
    itype;
  double 
    time,
    flops;

  MPI_Init(&argc, &argv);

  MPI_Comm_rank(MPI_COMM_WORLD, &me);
  MPI_Comm_size(MPI_COMM_WORLD, &nprocs);

  if (me==0) {
    printf("enter mesh size:\n");
    scanf("%d%d", &nprows, &npcols );
    printf("mesh size  = %d x %d \n", nprows, npcols );
    printf("enter distr. block size:\n");
    scanf("%d", &nb_distr );
    printf("nb_distr = %d\n", nb_distr );
    printf("enter alg. block size:\n");
    scanf("%d", &nb_alg );
    printf("nb_alg = %d\n", nb_alg );
    printf("turn on error checking? (0 = NO, 1 = YES):\n");
    scanf("%d", &error );
    printf("error checking = %d\n", error );
    printf("turn on parameter checking? (0 = NO, 1 = YES):\n");
    scanf("%d", &parameters );
    printf("parameter checking = %d\n", parameters );
    printf("turn on sequential checking? (0 = NO, 1 = YES):\n");
    scanf("%d", &sequential );
    printf("sequential checking = %d\n", sequential );
  }
  MPI_Bcast(&nprows, 1, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast(&npcols, 1, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast(&nb_distr, 1, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast(&nb_alg,   1, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast(&error, 1, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast(&parameters, 1, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast(&sequential, 1, MPI_INT, 0, MPI_COMM_WORLD);

  pla_Environ_set_nb_alg( PLA_OP_ALL_ALG, nb_alg );

  PLA_Set_error_checking( error, parameters, sequential, FALSE );

/*  PLA_Comm_1D_to_2D_ratio(MPI_COMM_WORLD, 1.0, &comm); */
  PLA_Comm_1D_to_2D(MPI_COMM_WORLD, nprows, npcols, &comm); 

  PLA_Init(comm);
    
  PLA_Temp_create( nb_distr, 0, &templ );
    
  while ( TRUE ){
    if (me==0) {
      printf("enter datatype:\n");
      printf("-1 = quit\n");
      printf(" 0 = float\n");
      printf(" 1 = double\n");
      printf(" 2 = complex\n");
      printf(" 3 = double complex\n");
      scanf("%d", &itype );
      printf("itype = %d\n", itype );
    }
    MPI_Bcast(&itype, 1, MPI_INT, 0, MPI_COMM_WORLD);

    if ( itype == -1 ) break;
    switch( itype ){
    case 0:
      datatype = MPI_FLOAT;
      break;
    case 1:
      datatype = MPI_DOUBLE;
      break;
    case 2:
      datatype = MPI_COMPLEX;
      break;
    case 3:
      datatype = MPI_DOUBLE_COMPLEX;
      break;
    default:
      PLA_Abort( "unknown datatype", __LINE__, __FILE__ );
    }

    if (me==0) {
      printf("enter n:\n");
      scanf("%d", &n );
      printf("n = %d\n", n );
    }

    MPI_Bcast(&n,     1, MPI_INT, 0, MPI_COMM_WORLD);

    PLA_Matrix_create( datatype, 
		        n, 
		        n,
			templ, 
                        PLA_ALIGN_FIRST, 
                        PLA_ALIGN_FIRST, 
                        &A ); 

    PLA_Mvector_create( MPI_INT,
		        n, 
		        1,
			templ, 
                        PLA_ALIGN_FIRST, 
                        &pivots ); 

    create_problem( A );
    

    MPI_Barrier( MPI_COMM_WORLD );
    time = MPI_Wtime ();
      
    PLA_LU( A, pivots );

    MPI_Barrier( MPI_COMM_WORLD );
    time = MPI_Wtime () - time;

    flops = 2.0/3.0 * n * n * n;

    if ( me == 0 ) 
      printf("%d time = %f, MFLOPS/node = %10.4lf \n", n, time,
	       flops / time * 1.0e-6 / nprocs );
  }

  PLA_Obj_free( &A );
  PLA_Obj_free( &pivots );
  PLA_Obj_free( &zero );
  PLA_Obj_free( &one );

  PLA_Temp_free(&templ);
  PLA_Finalize( );
  MPI_Finalize( );
  
}
Exemplo n.º 7
0
void   acm_solve(oplist_t &l, const vector<coeff_t> &coeffs,
                 const vector<reg_t> &dests, reg_t src, reg_t (*tmpreg)()) {
    ASSERT(dests.size() == coeffs.size());

    cfset_t problem;
    regmap_t * regs = new regmap_t;

    regs->clear();
    (*regs)[1] = src;

    for(int i = coeffs.size()-1; i >= 0; --i) {
        if(coeffs[i]!=1)
          (*regs)[coeffs[i]] = dests[i];
    }

    /* compute registers for all fundamentals ('reduced' constants) */
    for(size_t i = 0; i < coeffs.size(); ++i) {
        coeff_t full    = coeffs[i];
        coeff_t reduced = fundamental(cfabs(full));
        if(reduced!=1)
            ADD(problem, reduced);
        if(!CONTAINS(*regs, reduced))
            (*regs)[reduced] = tmpreg();
    }

    if_verbose(1) cerr<<"synthesizing "<<problem.size()<<" unique fundamentals\n";

    create_problem(problem);
    GEN_CODE = true;
    solve(&l, regs, tmpreg);

    for(size_t i = 0; i < coeffs.size(); ++i) {
        coeff_t full    = coeffs[i];
        reg_t   dest    = dests[i];
        coeff_t reduced = fundamental(cfabs(full));
        if(full == 1)
            l.push_back(op::shl(dest, src, 0, full)); /* move dest <- src */

        else if(full == -1)
            l.push_back(op::neg(dest, src, full)); /* move dest <- -1*src */

        /* last op */
        else if(dest == (*regs)[full]) {
            if(full != reduced) {
                int t = (*regs)[reduced];

                /* see if we already computed the negative of it */
                int found_neg = -1;
                for(size_t j=0; j<i; ++j) {
                    if(coeffs[j] == -full) {
                        found_neg = j;
                        break;
                    }
                }
                /* if not */
                if(found_neg == -1) {
                    /* this is the first instance */
                    int shr = compute_shr(cfabs(full));
                    if(shr!=0) {
                        reg_t tmp = dest;
                        if(full < 0) {
                            tmp = tmpreg();
                            for(size_t j = i+1; j < coeffs.size(); ++j) {
                                if(coeffs[j] == -full) {
                                    tmp = dests[j];
                                    break;
                                }
                            }
                        }
                        l.push_back(op::shl(tmp, (*regs)[reduced], shr, cfabs(full)));
                        t = tmp;
                    }
                    /* negate if necessary */
                    if(full<0) l.push_back(op::neg(dest,t, full));
                }
                else /* negative was already computed, just negate */
                    if(full < 0) l.push_back(op::neg(dest,dests[found_neg],full));
            }
        }
        else /* we already computed it */
            l.push_back(op::shl(dest, (*regs)[full], 0, full));
    }
    delete regs;
}
Exemplo n.º 8
0
int main(int argc, char *argv[])
{
  /* Declarations */
  MPI_Comm 
    comm;

  PLA_Template 
    templ = NULL;

  PLA_Obj  
    A = NULL,    rhs = NULL,    
    A_append = NULL,
    pivots = NULL,
    x = NULL,         
    b = NULL, 
    b_norm = NULL,
    index = NULL,
    minus_one = NULL;

  double 
    operation_count,
    b_norm_value, 
    time;

  int  
    size, 
    nb_distr, nb_alg, 
    me, nprocs, 
    nprows, npcols,
    dummy, 
    ierror,
    info = 0;
  
  MPI_Datatype 
    datatype;

  /* Initialize MPI */
  MPI_Init(&argc, &argv);

#if MANUFACTURE == CRAY
  set_d_stream( 1 );
#endif

  /* Get problem size and distribution block size and broadcast */
  MPI_Comm_rank(MPI_COMM_WORLD, &me);
  if (0 == me) {
    printf("enter processor mesh dimension ( rows cols ):\n");
    scanf("%d %d", &nprows, &npcols );
    printf("enter matrix size, distr. block size:\n");
    scanf("%d %d", &size, &nb_distr );
    printf("enter algorithmic blocksize:\n");
    scanf("%d", &nb_alg );
    printf("Turn on error checking? (1 = YES, 0 = NO):\n");
    scanf("%d", &ierror );
  }

  MPI_Bcast(&nprows,   1, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast(&npcols,   1, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast(&size,     1, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast(&nb_distr, 1, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast(&nb_alg, 1, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast(&ierror, 1, MPI_INT, 0, MPI_COMM_WORLD);

  if ( ierror ) 
    PLA_Set_error_checking( ierror, TRUE, TRUE, FALSE );
  else
    PLA_Set_error_checking( ierror, FALSE, FALSE, FALSE );

  pla_Environ_set_nb_alg (PLA_OP_ALL_ALG,
			  nb_alg);

  /* Create a 2D communicator */
  PLA_Comm_1D_to_2D(MPI_COMM_WORLD, nprows, npcols, &comm); 

  /* Initialize PLAPACK */
  PLA_Init(comm);

  /* Create object distribution template */
  PLA_Temp_create( nb_distr, 0, &templ );

  /* Set the datatype */
  datatype = MPI_DOUBLE;

  /* Create objects for problem to be solved */

  /* Matrix A is big enough to hold the right-hand-side appended */
  PLA_Matrix_create(  datatype, size, size+1, 
		      templ, PLA_ALIGN_FIRST, PLA_ALIGN_FIRST, &A_append );

  PLA_Mvector_create( datatype, size, 1, templ, PLA_ALIGN_FIRST, &x );

  PLA_Mvector_create( datatype, size, 1, templ, PLA_ALIGN_FIRST, &b );
   
  PLA_Mvector_create( MPI_INT, size, 1, templ, PLA_ALIGN_FIRST, &pivots );
   
  /* Create 1x1 multiscalars to hold largest (in abs. value) element 
     of b - x and index of largest value */
  PLA_Mscalar_create( MPI_DOUBLE,
		      PLA_ALL_ROWS, PLA_ALL_COLS,
			 1, 1, templ, &b_norm );

  /* Create duplicated scalar constants with same datatype and template as A */
  PLA_Create_constants_conf_to( A_append, &minus_one, NULL, NULL );

  /* View the appended system as the matrix and the right-hand-side */
  PLA_Obj_vert_split_2( A_append, -1, &A, &rhs );

  /* Create a problem to be solved: A x = b */
  create_problem( A, x, b );

  /* Copy b to the appended column */
  PLA_Copy( b, rhs );

  /* Start timing */
  MPI_Barrier( MPI_COMM_WORLD );
  time = MPI_Wtime( );

  /* Factor P A_append -> L U overwriting lower triangular portion of A with L, upper, U */

  info = PLA_LU( A_append, pivots);

  if ( info != 0 ) {
    printf("Zero pivot encountered at row %d.\n", info);
  }
  else {
    /* Apply the permutations to the right hand sides */
    /* Not necessery since system was appended */
    /* PLA_Apply_pivots_to_rows ( b, pivots); */
    
    /* Solve L y = b, overwriting b with y */
    /* Not necessary since the system was appended */
    /* PLA_Trsv( PLA_LOWER_TRIANGULAR, PLA_NO_TRANSPOSE, PLA_UNIT_DIAG, A, b ); */
    PLA_Copy( rhs, b );

    /* Solve U x = y (=b), overwriting b with x */
    PLA_Trsv( PLA_UPPER_TRIANGULAR, PLA_NO_TRANSPOSE,  PLA_NONUNIT_DIAG, A, b );

    /* Stop timing */
    MPI_Barrier( MPI_COMM_WORLD );
    time = MPI_Wtime() - time;

    /* Report performance */
    if ( me == 0 ) {
      MPI_Comm_size(MPI_COMM_WORLD, &nprocs);

      operation_count = 2.0/3.0 * size * size * size;

      printf("n = %d, time = %lf, MFLOPS/node = %lf\n", size, time,
	      operation_count / time * 1.0e-6 / nprocs );
    }

    /* Process the answer.  As an example, this routine brings 
       result x (stored in b) to processor 0 and prints first and 
       last entry */
    Process_answer( b ); 

    /* Check answer by overwriting b <- b - x (where b holds computed
       approximation to x) */

    PLA_Axpy( minus_one, x, b );

    PLA_Nrm2( b, b_norm);

    /* Report norm of b - x */
    if ( me == 0 ) {
      PLA_Obj_get_local_contents( b_norm, PLA_NO_TRANS, &dummy, &dummy,
				  &b_norm_value, 1, 1 );
      printf( "Norm2 of x - computed x : %le\n", b_norm_value );
    }
  } 

  printf("****************************************************************\n");
  printf("* NOTE: while this driver times all operations performed by    *\n");
  printf("* a LINPACK benchmark, it does not use the ScaLAPACK random    *\n");
  printf("* matrix generator and thus according to the rules of the      *\n");
  printf("* LINPACK benchmark is not an official implementation.         *\n");
  printf("* Contact [email protected] if you are interested in creating *\n");
  printf("* a version that does meet the rules.                          *\n");
  printf("****************************************************************\n");

     
  /* Free the linear algebra objects */
  PLA_Obj_free(&A);            PLA_Obj_free(&x);
  PLA_Obj_free(&b);            PLA_Obj_free(&minus_one);
  PLA_Obj_free(&b_norm);       PLA_Obj_free(&pivots);
  PLA_Obj_free(&A_append);     PLA_Obj_free(&rhs);

  /* Free the template */
  PLA_Temp_free(&templ);

  /* Finalize PLAPACK and MPI */
  PLA_Finalize( );
  MPI_Finalize( );
}