// // replsymm.cc // // Copyright (C) 1996 Limit Point Systems, Inc. // // Author: Curtis Janssen // Maintainer: LPS // // This file is part of the SC Toolkit. // // The SC Toolkit is free software; you can redistribute it and/or modify // it under the terms of the GNU Library General Public License as published by // the Free Software Foundation; either version 2, or (at your option) // any later version. // // The SC Toolkit is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with the SC Toolkit; see the file COPYING.LIB. If not, write to // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. // // The U.S. Government is granted a limited license as per AL 91-7. // #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace sc; ///////////////////////////////////////////////////////////////////////////// // ReplSymmSCMatrix member functions static ClassDesc ReplSymmSCMatrix_cd( typeid(ReplSymmSCMatrix),"ReplSymmSCMatrix",1,"public SymmSCMatrix", 0, 0, 0); static double ** init_symm_rows(double *data, int n) { double** r = new double*[n]; for (int i=0; in(); matrix = new double[n*(n+1)>>1]; rows = init_symm_rows(matrix,n); init_blocklist(); } void ReplSymmSCMatrix::before_elemop() { // zero out the blocks not in my block list int i, j, index; int nproc = messagegrp()->n(); int me = messagegrp()->me(); for (i=0, index=0; iblocks()->nblock(); i++) { for (j=0; j<=i; j++, index++) { if (index%nproc == me) continue; for (int ii=d->blocks()->start(i); iiblocks()->fence(i); ii++) { for (int jj=d->blocks()->start(j); jj < d->blocks()->fence(j) && jj <= ii; jj++) { matrix[(ii*(ii+1)>>1) + jj] = 0.0; } } } } } void ReplSymmSCMatrix::after_elemop() { messagegrp()->sum(matrix, d->n()*(d->n()+1)>>1); } void ReplSymmSCMatrix::init_blocklist() { int i, j, index; int nproc = messagegrp()->n(); int me = messagegrp()->me(); blocklist = new SCMatrixBlockList; for (i=0, index=0; iblocks()->nblock(); i++) { for (j=0; j<=i; j++, index++) { if (index%nproc != me) continue; blocklist->insert( new SCMatrixLTriSubBlock(d->blocks()->start(i), d->blocks()->fence(i), d->blocks()->start(j), d->blocks()->fence(j), matrix)); } } } ReplSymmSCMatrix::~ReplSymmSCMatrix() { if (matrix) delete[] matrix; if (rows) delete[] rows; } int ReplSymmSCMatrix::compute_offset(int i,int j) const { if (i<0 || j<0 || i>=d->n() || j>=d->n()) { ExEnv::errn() << indent << "ReplSymmSCMatrix: index out of bounds\n"; abort(); } return ij_offset(i,j); } double ReplSymmSCMatrix::get_element(int i,int j) const { return matrix[compute_offset(i,j)]; } void ReplSymmSCMatrix::set_element(int i,int j,double a) { matrix[compute_offset(i,j)] = a; } void ReplSymmSCMatrix::accumulate_element(int i,int j,double a) { matrix[compute_offset(i,j)] += a; } SCMatrix * ReplSymmSCMatrix::get_subblock(int br, int er, int bc, int ec) { int nsrow = er-br+1; int nscol = ec-bc+1; if (nsrow > n() || nscol > n()) { ExEnv::errn() << indent << "ReplSymmSCMatrix::get_subblock: trying to get too big a " << "subblock (" << nsrow << "," << nscol << ") from (" << n() << "," << n() << ")\n"; abort(); } RefSCDimension dnrow = (nsrow==n()) ? dim().pointer():new SCDimension(nsrow); RefSCDimension dncol = (nscol==n()) ? dim().pointer():new SCDimension(nscol); SCMatrix * sb = kit()->matrix(dnrow,dncol); sb->assign(0.0); ReplSCMatrix *lsb = require_dynamic_cast(sb, "ReplSymmSCMatrix::get_subblock"); for (int i=0; i < nsrow; i++) for (int j=0; j < nscol; j++) lsb->rows[i][j] = get_element(i+br,j+bc); return sb; } SymmSCMatrix * ReplSymmSCMatrix::get_subblock(int br, int er) { int nsrow = er-br+1; if (nsrow > n()) { ExEnv::errn() << indent << "ReplSymmSCMatrix::get_subblock: trying to get too big a " << "subblock (" << nsrow << "," << nsrow << ") from (" << n() << "," << n() << ")\n"; abort(); } RefSCDimension dnrow = new SCDimension(nsrow); SymmSCMatrix * sb = kit()->symmmatrix(dnrow); sb->assign(0.0); ReplSymmSCMatrix *lsb = require_dynamic_cast(sb, "ReplSymmSCMatrix::get_subblock"); for (int i=0; i < nsrow; i++) for (int j=0; j <= i; j++) lsb->rows[i][j] = get_element(i+br,j+br); return sb; } void ReplSymmSCMatrix::assign_subblock(SCMatrix*sb, int br, int er, int bc, int ec) { ReplSCMatrix *lsb = require_dynamic_cast(sb, "ReplSCMatrix::assign_subblock"); int nsrow = er-br+1; int nscol = ec-bc+1; if (nsrow > n() || nscol > n()) { ExEnv::errn() << indent << "ReplSymmSCMatrix::assign_subblock: trying to assign too big a " << "subblock (" << nsrow << "," << nscol << ") to (" << n() << "," << n() << ")\n"; abort(); } for (int i=0; i < nsrow; i++) for (int j=0; j < nscol; j++) set_element(i+br,j+bc,lsb->rows[i][j]); } void ReplSymmSCMatrix::assign_subblock(SymmSCMatrix*sb, int br, int er) { ReplSymmSCMatrix *lsb = require_dynamic_cast(sb, "ReplSymmSCMatrix::assign_subblock"); int nsrow = er-br+1; if (nsrow > n()) { ExEnv::errn() << indent << "ReplSymmSCMatrix::assign_subblock: trying to assign too big a " << "subblock (" << nsrow << "," << nsrow << ") to (" << n() << "," << n() << ")\n"; abort(); } for (int i=0; i < nsrow; i++) for (int j=0; j <= i; j++) set_element(i+br,j+br,lsb->rows[i][j]); } void ReplSymmSCMatrix::accumulate_subblock(SCMatrix*sb, int br, int er, int bc, int ec) { ReplSCMatrix *lsb = require_dynamic_cast(sb, "ReplSymmSCMatrix::accumulate_subblock"); int nsrow = er-br+1; int nscol = ec-bc+1; if (nsrow > n() || nscol > n()) { ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate_subblock: " << "trying to accumulate too big a " << "subblock (" << nsrow << "," << nscol << ") to (" << n() << "," << n() << ")\n"; abort(); } for (int i=0; i < nsrow; i++) for (int j=0; j < nscol; j++) set_element(i+br,j+br,get_element(i+br,j+br)+lsb->rows[i][j]); } void ReplSymmSCMatrix::accumulate_subblock(SymmSCMatrix*sb, int br, int er) { ReplSCMatrix *lsb = require_dynamic_cast(sb, "ReplSymmSCMatrix::accumulate_subblock"); int nsrow = er-br+1; if (nsrow > n()) { ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate_subblock: trying to " << "accumulate too big a " << "subblock (" << nsrow << "," << nsrow << ") to (" << n() << "," << n() << ")\n"; abort(); } for (int i=0; i < nsrow; i++) for (int j=0; j <= i; j++) set_element(i+br,j+br,get_element(i+br,j+br)+lsb->rows[i][j]); } SCVector * ReplSymmSCMatrix::get_row(int i) { if (i >= n()) { ExEnv::errn() << indent << "ReplSymmSCMatrix::get_row: trying to get invalid row " << i << " max " << n() << endl; abort(); } SCVector * v = kit()->vector(dim()); ReplSCVector *lv = require_dynamic_cast(v, "ReplSymmSCMatrix::get_row"); for (int j=0; j < n(); j++) lv->set_element(j,get_element(i,j)); return v; } void ReplSymmSCMatrix::assign_row(SCVector *v, int i) { if (i >= n()) { ExEnv::errn() << indent << "ReplSymmSCMatrix::assign_row: trying to assign invalid row " << i << " max " << n() << endl; abort(); } if (v->n() != n()) { ExEnv::errn() << indent << "ReplSymmSCMatrix::assign_row: vector is wrong size, " << "is " << v->n() << ", should be " << n() << endl; abort(); } ReplSCVector *lv = require_dynamic_cast(v, "ReplSymmSCMatrix::assign_row"); for (int j=0; j < n(); j++) set_element(i,j,lv->get_element(j)); } void ReplSymmSCMatrix::accumulate_row(SCVector *v, int i) { if (i >= n()) { ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate_row: trying to assign invalide row " << i << " max " << n() << endl; abort(); } if (v->n() != n()) { ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate_row: vector is wrong size, " << "is " << v->n() << ", should be " << n() << endl; abort(); } ReplSCVector *lv = require_dynamic_cast(v, "ReplSymmSCMatrix::accumulate_row"); for (int j=0; j < n(); j++) set_element(i,j,get_element(i,j)+lv->get_element(j)); } void ReplSymmSCMatrix::assign_val(double val) { int n = (d->n()*(d->n()+1))/2; for (int i=0; i(m); if (lm && dim()->equiv(lm->dim())) { int d = i_offset(n()); memcpy(matrix, lm->matrix, sizeof(double)*d); } else SymmSCMatrix::assign(m); } void ReplSymmSCMatrix::assign_p(const double*m) { int d = i_offset(n()); memcpy(matrix, m, sizeof(double)*d); } void ReplSymmSCMatrix::assign_pp(const double**m) { for (int i=0; i < n(); i++) for (int j=0; j <= i; j++) rows[i][j] = m[i][j]; } void ReplSymmSCMatrix::scale(double s) { int nelem = i_offset(n()); for (int i=0; i < nelem; i++) matrix[i] *= s; } void ReplSymmSCMatrix::accumulate(const SymmSCMatrix*a) { // make sure that the arguments is of the correct type const ReplSymmSCMatrix* la = require_dynamic_cast(a,"ReplSymmSCMatrix::accumulate"); // make sure that the dimensions match if (!dim()->equiv(la->dim())) { ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate(SCMatrix*a): " << "dimensions don't match\n"; abort(); } int nelem = (this->n() * (this->n() + 1))/2; for (int i=0; imatrix[i]; } double ReplSymmSCMatrix::invert_this() { if (messagegrp()->n() == 1) return cmat_invert(rows,1,n()); else { RefDiagSCMatrix refa = kit()->diagmatrix(d); RefSCMatrix refb = kit()->matrix(d,d); diagonalize(refa.pointer(),refb.pointer()); double determ = 1.0; for (int i=0; in(); i++) { double val = refa->get_element(i); determ *= val; } Ref op = new SCElementInvert(1.0e-12); refa->element_op(op.pointer()); assign(0.0); accumulate_transform(refb.pointer(), refa.pointer()); return determ; } } double ReplSymmSCMatrix::determ_this() { if (messagegrp()->n() == 1) return cmat_determ(rows,1,n()); else { RefDiagSCMatrix refa = kit()->diagmatrix(d); RefSCMatrix refb = kit()->matrix(d,d); diagonalize(refa.pointer(),refb.pointer()); double determ = 1.0; for (int i=0; in(); i++) { double val = refa->get_element(i); determ *= val; } return determ; } } double ReplSymmSCMatrix::trace() { double ret=0; for (int i=0; i < n(); i++) ret += rows[i][i]; return ret; } double ReplSymmSCMatrix::solve_this(SCVector*v) { ReplSCVector* lv = require_dynamic_cast(v,"ReplSymmSCMatrix::solve_this"); // make sure that the dimensions match if (!dim()->equiv(lv->dim())) { ExEnv::errn() << indent << "ReplSymmSCMatrix::solve_this(SCVector*v): " << "dimensions don't match\n"; abort(); } return cmat_solve_lin(rows,1,lv->vector,n()); } void ReplSymmSCMatrix::gen_invert_this() { RefSCMatrix evecs = kit()->matrix(dim(),dim()); RefDiagSCMatrix evals = kit()->diagmatrix(dim()); const char *name = "ReplSymmSCMatrix::gen_invert_this"; ReplDiagSCMatrix *levals = require_dynamic_cast(evals,name); ReplSCMatrix *levecs = require_dynamic_cast(evecs,name); this->diagonalize(evals.pointer(), evecs.pointer()); for (int i=0; i < n(); i++) { if (fabs(levals->matrix[i]) > 1.0e-8) levals->matrix[i] = 1.0/levals->matrix[i]; else levals->matrix[i] = 0; } assign(0.0); accumulate_transform(levecs, levals); } void ReplSymmSCMatrix::diagonalize(DiagSCMatrix*a,SCMatrix*b) { int i; const char* name = "ReplSymmSCMatrix::diagonalize"; // make sure that the arguments is of the correct type ReplDiagSCMatrix* la = require_dynamic_cast(a,name); ReplSCMatrix* lb = require_dynamic_cast(b,name); if (!dim()->equiv(la->dim()) || !dim()->equiv(lb->coldim()) || !dim()->equiv(lb->rowdim())) { ExEnv::errn() << indent << "ReplSymmSCMatrix::diagonalize(DiagSCMatrix*a,SCMatrix*b): " << "bad dims\n"; abort(); } // This sets up the index list of columns to be stored on this node int n = dim()->n(); int me = messagegrp()->me(); int nproc = messagegrp()->n(); // if there are fewer vectors than processors, do serial diagonalization if (n < nproc || nproc==1) { double *eigvals = la->matrix; double **eigvecs = lb->rows; cmat_diag(rows, eigvals, eigvecs, n, 1, 1.0e-15); } else { int nvec = n/nproc + (me<(n%nproc)?1:0); int mvec = n/nproc + ((n%nproc) ? 1 : 0); int *ivec = new int[nvec]; for (i=0; iassign(0.0); for (i=0; i < nvec; i++) { int c = ivec[i]; int j; for (j=0; j <= c; j++) rect[i][j] = rows[c][j]; for (; j < n; j++) rect[i][j] = rows[j][c]; } dist_diagonalize(n, nvec, rect[0], eigvals, eigvecs[0], messagegrp()); la->assign(eigvals); delete[] eigvals; int *tivec = new int [mvec]; for (i=0; i < nproc; i++) { int tnvec; if (i==me) { messagegrp()->bcast(nvec, me); messagegrp()->bcast(eigvecs[0], n*nvec, me); messagegrp()->bcast(ivec, nvec, me); tnvec = nvec; memcpy(tivec, ivec, sizeof(int)*nvec); memcpy(rect[0], eigvecs[0], sizeof(double)*n*nvec); } else { messagegrp()->bcast(tnvec, i); messagegrp()->bcast(rect[0], n*tnvec, i); messagegrp()->bcast(tivec, tnvec, i); } for (int j=0; j < tnvec; j++) { int c = tivec[j]; for (int k=0; k < n; k++) lb->rows[k][c] = rect[j][k]; } } delete[] ivec; delete[] tivec; cmat_delete_matrix(eigvecs); cmat_delete_matrix(rect); } } // computes this += a * a.t void ReplSymmSCMatrix::accumulate_symmetric_product(SCMatrix*a) { // make sure that the argument is of the correct type ReplSCMatrix* la = require_dynamic_cast(a,"ReplSymmSCMatrix::" "accumulate_symmetric_product"); if (!dim()->equiv(la->rowdim())) { ExEnv::errn() << indent << "ReplSymmSCMatrix::" << "accumulate_symmetric_product(SCMatrix*a): bad dim\n"; abort(); } cmat_symmetric_mxm(rows,n(),la->rows,la->ncol(),1); } // computes this += a + a.t void ReplSymmSCMatrix::accumulate_symmetric_sum(SCMatrix*a) { // make sure that the argument is of the correct type ReplSCMatrix* la = require_dynamic_cast(a,"ReplSymmSCMatrix::" "accumulate_symmetric_sum"); if (!dim()->equiv(la->rowdim()) || !dim()->equiv(la->coldim())) { ExEnv::errn() << indent << "ReplSymmSCMatrix::" << "accumulate_symmetric_sum(SCMatrix*a): bad dim\n"; abort(); } int n = dim().n(); double** tdat = this->rows; double** adat = la->rows; for (int i=0; i(a,"ReplSymmSCMatrix::" "accumulate_symmetric_outer_product"); if (!dim()->equiv(la->dim())) { ExEnv::errn() << indent << "ReplSymmSCMatrix::" << "accumulate_symmetric_outer_product(SCMatrix*a): bad dim\n"; abort(); } int n = dim().n(); double** tdat = this->rows; double* adat = la->vector; for (int i=0; i(a,"%s::accumulate_transform", class_name()); ReplSymmSCMatrix*lb = require_dynamic_cast( b,"%s::accumulate_transform", class_name()); // check the dimensions if (t == SCMatrix::NormalTransform) { if (!dim()->equiv(la->rowdim()) || !lb->dim()->equiv(la->coldim())) { ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate_transform: bad dim\n"; abort(); } nc = lb->n(); nr = la->nrow(); } else { if (!dim()->equiv(la->coldim()) || !lb->dim()->equiv(la->rowdim())) { ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate_transform: bad dim\n"; abort(); } nc = lb->n(); nr = la->ncol(); } if (nr==0 || nc==0) return; int nproc = messagegrp()->n(); double **ablock = cmat_new_square_matrix(D1); double **bblock = cmat_new_square_matrix(D1); double **cblock = cmat_new_square_matrix(D1); // if one processor then minimize the amount of memory used if (nproc == 1) { double **temp = cmat_new_rect_matrix(D1,nc); for (i=0; i < nr; i += D1) { int ni = nr-i; if (ni > D1) ni = D1; memset(temp[0], 0, sizeof(double)*D1*nc); for (j=0; j < nc; j+= D1) { int nj = nc-j; if (nj > D1) nj = D1; for (k=0; k < nc; k += D1) { int nk = nc-k; if (nk > D1) nk = D1; if (t == SCMatrix::NormalTransform) copy_block(ablock, la->rows, i, ni, k, nk); else copy_trans_block(ablock, la->rows, i, ni, k, nk); copy_sym_block(bblock, lb->rows, j, nj, k, nk); copy_block(cblock, temp, 0, ni, j, nj); mult_block(ablock, bblock, cblock, ni, nj, nk); return_block(temp, cblock, 0, ni, j, nj); } } // now do ab * a~ for (j=0; j <= i; j+= D1) { int nj = nr-j; if (nj > D1) nj = D1; memset(cblock[0], 0, sizeof(double)*D1*D1); for (k=0; k < nc; k += D1) { int nk = nc-k; if (nk > D1) nk = D1; copy_block(ablock, temp, 0, ni, k, nk); if (t == SCMatrix::NormalTransform) copy_block(bblock, la->rows, j, nj, k, nk); else copy_trans_block(bblock, la->rows, j, nj, k, nk); mult_block(ablock, bblock, cblock, ni, nj, nk); } // copy cblock(i,j) into result if (j==i) { for (ii=0; ii < ni; ii++) for (jj=0; jj <= ii; jj++) rows[i+ii][j+jj] += cblock[ii][jj]; } else { for (ii=0; ii < ni; ii++) for (jj=0; jj < nj; jj++) rows[i+ii][j+jj] += cblock[ii][jj]; } } } cmat_delete_matrix(temp); } // this version requires a full temp matrix be kept else { int me = messagegrp()->me(); int mod = nr%nproc; int njrow = nr/nproc + ((mod <= me) ? 0 : 1); int jstart = (nr/nproc)*me + ((mod <= me) ? mod : me); int jend = jstart+njrow; double **temp = cmat_new_rect_matrix(nr,nc); memset(temp[0], 0, sizeof(double)*nr*nc); for (i=0; i < nc; i += D1) { int ni = nc-i; if (ni > D1) ni = D1; for (k=0; k < nc; k += D1) { int nk = nc-k; if (nk > D1) nk = D1; copy_sym_block(ablock, lb->rows, i, ni, k, nk); for (j=jstart; j < jend; j += D1) { int nj = jend-j; if (nj > D1) nj = D1; if (t == SCMatrix::NormalTransform) copy_block(bblock, la->rows, j, nj, k, nk); else copy_trans_block(bblock, la->rows, j, nj, k, nk); memset(cblock[0], 0, sizeof(double)*D1*D1); mult_block(ablock, bblock, cblock, ni, nj, nk); for (jj=0; jj < nj; jj++) for (ii=0; ii < ni; ii++) temp[j+jj][i+ii] += cblock[ii][jj]; } } } for (i=0; i < nproc; i++) { njrow = nr/nproc + ((mod <= i) ? 0 : 1); jstart = (nr/nproc)*i + ((mod <= i) ? mod : i); if (!njrow) break; messagegrp()->bcast(temp[jstart], njrow*nc, i); } int ind=0; for (i=0; i < nr; i += D1) { int ni = nr-i; if (ni > D1) ni = D1; for (j=0; j <= i; j += D1, ind++) { if (ind%nproc != me) continue; int nj = nr-j; if (nj > D1) nj = D1; memset(cblock[0], 0, sizeof(double)*D1*D1); for (k=0; k < nc; k += D1) { int nk = nc-k; if (nk > D1) nk = D1; if (t == SCMatrix::NormalTransform) copy_block(ablock, la->rows, i, ni, k, nk); else copy_trans_block(ablock, la->rows, i, ni, k, nk); copy_block(bblock, temp, j, nj, k, nk); mult_block(ablock, bblock, cblock, ni, nj, nk); } if (i==j) { for (ii=0; ii < ni; ii++) for (jj=0; jj <= ii; jj++) rows[i+ii][j+jj] += cblock[ii][jj]; } else { for (ii=0; ii < ni; ii++) for (jj=0; jj < nj; jj++) rows[i+ii][j+jj] += cblock[ii][jj]; } } } ind=0; for (i=0; i < nr; i += D1) { int ni = nr-i; if (ni > D1) ni = D1; for (j=0; j <= i; j += D1, ind++) { int nj = nr-j; if (nj > D1) nj = D1; int proc = ind%nproc; if (proc==me) copy_sym_block(ablock, rows, i, ni, j, nj); messagegrp()->bcast(ablock[0], D1*D1, proc); if (i==j) { for (ii=0; ii < ni; ii++) for (jj=0; jj <= ii; jj++) rows[i+ii][j+jj] = ablock[ii][jj]; } else { for (ii=0; ii < ni; ii++) for (jj=0; jj < nj; jj++) rows[i+ii][j+jj] = ablock[ii][jj]; } } } cmat_delete_matrix(temp); } cmat_delete_matrix(ablock); cmat_delete_matrix(bblock); cmat_delete_matrix(cblock); } // this += a * b * transpose(a) void ReplSymmSCMatrix::accumulate_transform(SCMatrix*a,DiagSCMatrix*b, SCMatrix::Transform t) { // do the necessary castdowns ReplSCMatrix*la = require_dynamic_cast(a,"%s::accumulate_transform", class_name()); ReplDiagSCMatrix*lb = require_dynamic_cast(b,"%s::accumulate_transform", class_name()); // check the dimensions if (!dim()->equiv(la->rowdim()) || !lb->dim()->equiv(la->coldim())) { ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate_transform: bad dim\n"; abort(); } cmat_transform_diagonal_matrix(rows,n(),lb->matrix,lb->n(),la->rows,1); } void ReplSymmSCMatrix::accumulate_transform(SymmSCMatrix*a,SymmSCMatrix*b) { SymmSCMatrix::accumulate_transform(a,b); } double ReplSymmSCMatrix::scalar_product(SCVector*a) { // make sure that the argument is of the correct type ReplSCVector* la = require_dynamic_cast(a,"ReplSCVector::scalar_product"); // make sure that the dimensions match if (!dim()->equiv(la->dim())) { ExEnv::errn() << indent << "ReplSCVector::scale_product(SCVector*a): " << "dimensions don't match\n"; abort(); } int nelem = n(); double* adat = la->vector; double result = 0.0; for (int i=0; i& op) { if (op->has_side_effects()) before_elemop(); scmat_perform_op_on_blocks(op, blocklist); if (op->has_side_effects()) after_elemop(); if (op->has_collect()) op->collect(messagegrp()); } void ReplSymmSCMatrix::element_op(const Ref& op, SymmSCMatrix* m) { ReplSymmSCMatrix *lm = require_dynamic_cast(m,"ReplSymSCMatrix::element_op"); if (!dim()->equiv(lm->dim())) { ExEnv::errn() << indent << "ReplSymmSCMatrix: bad element_op\n"; abort(); } if (op->has_side_effects()) before_elemop(); if (op->has_side_effects_in_arg()) lm->before_elemop(); SCMatrixBlockListIter i, j; for (i = blocklist->begin(), j = lm->blocklist->begin(); i != blocklist->end(); i++, j++) { op->process_base(i.block(), j.block()); } if (op->has_side_effects()) after_elemop(); if (op->has_side_effects_in_arg()) lm->after_elemop(); if (op->has_collect()) op->collect(messagegrp()); } void ReplSymmSCMatrix::element_op(const Ref& op, SymmSCMatrix* m,SymmSCMatrix* n) { ReplSymmSCMatrix *lm = require_dynamic_cast(m,"ReplSymSCMatrix::element_op"); ReplSymmSCMatrix *ln = require_dynamic_cast(n,"ReplSymSCMatrix::element_op"); if (!dim()->equiv(lm->dim()) || !dim()->equiv(ln->dim())) { ExEnv::errn() << indent << "ReplSymmSCMatrix: bad element_op\n"; abort(); } if (op->has_side_effects()) before_elemop(); if (op->has_side_effects_in_arg1()) lm->before_elemop(); if (op->has_side_effects_in_arg2()) ln->before_elemop(); SCMatrixBlockListIter i, j, k; for (i = blocklist->begin(), j = lm->blocklist->begin(), k = ln->blocklist->begin(); i != blocklist->end(); i++, j++, k++) { op->process_base(i.block(), j.block(), k.block()); } if (op->has_side_effects()) after_elemop(); if (op->has_side_effects_in_arg1()) lm->after_elemop(); if (op->has_side_effects_in_arg2()) ln->after_elemop(); if (op->has_collect()) op->collect(messagegrp()); } // from Ed Seidl at the NIH (with a bit of hacking) void ReplSymmSCMatrix::vprint(const char *title, ostream& os, int prec) const { int ii,jj,kk,nn; int i,j; int lwidth,width; double max=this->maxabs(); if (messagegrp()->me() != 0) return; max = (max==0.0) ? 1.0 : log10(max); if (max < 0.0) max=1.0; lwidth = prec + 5 + (int) max; width = 75/(lwidth+SCFormIO::getindent(os)); os.setf(ios::fixed,ios::floatfield); os.precision(prec); os.setf(ios::right,ios::adjustfield); if (title) os << endl << indent << title << endl; else os << endl; if (n()==0) { os << indent << "empty matrix\n"; return; } for (ii=jj=0;;) { ii++; jj++; kk=width*jj; nn = (n() > kk) ? kk : n(); // print column indices os << indent; for (i=ii; i <= nn; i++) os << setw(lwidth) << i; os << endl; // print the rows for (i=ii-1; i < n() ; i++) { os << indent << setw(5) << i+1; for (j=ii-1; j ReplSymmSCMatrix::local_blocks(SCMatrixSubblockIter::Access access) { return new ReplSCMatrixListSubblockIter(access, blocklist, messagegrp(), matrix, (d->n()*(d->n()+1))/2); } Ref ReplSymmSCMatrix::all_blocks(SCMatrixSubblockIter::Access access) { if (access == SCMatrixSubblockIter::Write) { ExEnv::errn() << indent << "ReplSymmSCMatrix::all_blocks: " << "Write access permitted for local blocks only" << endl; abort(); } Ref allblocklist = new SCMatrixBlockList(); allblocklist->insert(new SCMatrixLTriSubBlock(0, d->n(), 0, d->n(), matrix)); return new ReplSCMatrixListSubblockIter(access, allblocklist, messagegrp(), matrix, (d->n()*(d->n()+1))/2); } Ref ReplSymmSCMatrix::skit() { return dynamic_cast(kit().pointer()); } ///////////////////////////////////////////////////////////////////////////// // Local Variables: // mode: c++ // c-file-style: "CLJ" // End: