// // distvect.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 using namespace std; using namespace sc; ///////////////////////////////////////////////////////////////////////////// // DistSCVector member functions static ClassDesc DistSCVector_cd( typeid(DistSCVector),"DistSCVector",1,"public SCVector", 0, 0, 0); DistSCVector::DistSCVector(const RefSCDimension&a, DistSCMatrixKit*k): SCVector(a,k) { init_blocklist(); } int DistSCVector::block_to_node(int i) const { return (i)%messagegrp()->n(); } Ref DistSCVector::block_to_block(int i) const { int offset = i; int nproc = messagegrp()->n(); if ((offset%nproc) != messagegrp()->me()) return 0; SCMatrixBlockListIter I; for (I=blocklist->begin(); I!=blocklist->end(); I++) { if (I.block()->blocki == i) return I.block(); } ExEnv::errn() << indent << "DistSCVector::block_to_block: internal error" << endl; abort(); return 0; } double * DistSCVector::find_element(int i) const { int bi, oi; d->blocks()->elem_to_block(i, bi, oi); Ref blk; blk << block_to_block(bi); if (blk.nonnull()) { return &blk->dat()[oi]; } else { return 0; } } int DistSCVector::element_to_node(int i) const { int bi, oi; d->blocks()->elem_to_block(i, bi, oi); return block_to_node(bi); } void DistSCVector::init_blocklist() { int i; int nproc = messagegrp()->n(); int me = messagegrp()->me(); blocklist = new SCMatrixBlockList; SCMatrixBlock *b; for (i=0; iblocks()->nblock(); i++) { if (i%nproc != me) continue; b = new SCVectorSimpleBlock(d->blocks()->start(i), d->blocks()->fence(i)); b->blocki = i; blocklist->insert(b); } } DistSCVector::~DistSCVector() { } double DistSCVector::get_element(int i) const { double res; double *e = find_element(i); if (e) { res = *e; messagegrp()->bcast(res, messagegrp()->me()); } else { messagegrp()->bcast(res, element_to_node(i)); } return res; } void DistSCVector::set_element(int i,double a) { double *e = find_element(i); if (e) { *e = a; } } void DistSCVector::accumulate_element(int i,double a) { double *e = find_element(i); if (e) { *e += a; } } void DistSCVector::accumulate(const SCVector*a) { // make sure that the argument is of the correct type const DistSCVector* la = require_dynamic_cast(a,"DistSCVector::accumulate"); // make sure that the dimensions match if (!dim()->equiv(la->dim())) { ExEnv::errn() << indent << "DistSCVector::accumulate(SCVector*a): " << "dimensions don't match\n"; abort(); } SCMatrixBlockListIter i1, i2; for (i1=la->blocklist->begin(),i2=blocklist->begin(); i1!=la->blocklist->end() && i2!=blocklist->end(); i1++,i2++) { int n = i1.block()->ndat(); if (n != i2.block()->ndat()) { ExEnv::errn() << indent << "DistSCVector::accumulate " << "mismatch: internal error" << endl; abort(); } double *dat1 = i1.block()->dat(); double *dat2 = i2.block()->dat(); for (int i=0; i(a,"DistSCVector::accumulate"); // make sure that the dimensions match if (!((la->rowdim()->equiv(dim()) && la->coldim()->n() == 1) || (la->coldim()->equiv(dim()) && la->rowdim()->n() == 1))) { ExEnv::errn() << indent << "DistSCVector::accumulate(SCMatrix*a): " << "dimensions don't match\n"; abort(); } SCMatrixBlockListIter I, J; for (I = la->blocklist->begin(), J = blocklist->begin(); I != la->blocklist->end() && J != blocklist->end(); I++,J++) { int n = I.block()->ndat(); if (n != J.block()->ndat()) { ExEnv::errn() << indent << "DistSCVector::accumulate(SCMatrix*a): " << "block lists do not match" << endl; abort(); } double *dati = I.block()->dat(); double *datj = J.block()->dat(); for (int i=0; i(a,"DistSCVector::assign_v"); // make sure that the dimensions match if (!dim()->equiv(la->dim())) { ExEnv::errn() << indent << "DistSCVector::assign_v(SCVector*a): " << "dimensions don't match\n"; abort(); } SCMatrixBlockListIter i1, i2; for (i1=la->blocklist->begin(),i2=blocklist->begin(); i1!=la->blocklist->end() && i2!=blocklist->end(); i1++,i2++) { int n = i1.block()->ndat(); if (n != i2.block()->ndat()) { ExEnv::errn() << indent << "DistSCVector::assign " << "mismatch: internal error" << endl; abort(); } double *dat1 = i1.block()->dat(); double *dat2 = i2.block()->dat(); for (int i=0; ibegin(); I!=blocklist->end(); I++) { Ref b = dynamic_cast(I.block()); if (b.null()) { ExEnv::errn() << indent << "DistSCVector::assign " << "mismatch: internal error" << endl; abort(); } int n = b->ndat(); const double *dat1 = &a[b->istart]; double *dat2 = b->dat(); for (int i=0; i(a,"DistSCVector::scalar_product"); // make sure that the dimensions match if (!dim()->equiv(la->dim())) { ExEnv::errn() << indent << "DistSCVector::scalar_product(SCVector*a): " << "dimensions don't match\n"; abort(); } double result = 0.0; SCMatrixBlockListIter i1, i2; for (i1=la->blocklist->begin(),i2=blocklist->begin(); i1!=la->blocklist->end() && i2!=blocklist->end(); i1++,i2++) { int n = i1.block()->ndat(); if (n != i2.block()->ndat()) { ExEnv::errn() << indent << "DistSCVector::scalar_product: block mismatch: " << "internal error" << endl; abort(); } double *dat1 = i1.block()->dat(); double *dat2 = i2.block()->dat(); for (int i=0; isum(result); return result; } void DistSCVector::element_op(const Ref& op) { SCMatrixBlockListIter i; for (i = blocklist->begin(); i != blocklist->end(); i++) { op->process_base(i.block()); } if (op->has_collect()) op->collect(messagegrp()); } void DistSCVector::element_op(const Ref& op, SCVector* m) { DistSCVector *lm = require_dynamic_cast(m, "DistSCVector::element_op"); if (!dim()->equiv(lm->dim())) { ExEnv::errn() << indent << "DistSCVector: bad element_op\n"; abort(); } 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_collect()) op->collect(messagegrp()); } void DistSCVector::element_op(const Ref& op, SCVector* m,SCVector* n) { DistSCVector *lm = require_dynamic_cast(m, "DistSCVector::element_op"); DistSCVector *ln = require_dynamic_cast(n, "DistSCVector::element_op"); if (!dim()->equiv(lm->dim()) || !dim()->equiv(ln->dim())) { ExEnv::errn() << indent << "DistSCVector: bad element_op\n"; abort(); } 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_collect()) op->collect(messagegrp()); } void DistSCVector::accumulate_product_rv(SCMatrix *pa, SCVector *pb) { const char* name = "DistSCMatrix::accumulate_product_rv"; // make sure that the arguments are of the correct type DistSCMatrix* a = require_dynamic_cast(pa,name); DistSCVector* b = require_dynamic_cast(pb,name); // make sure that the dimensions match if (!dim()->equiv(a->rowdim()) || !a->coldim()->equiv(b->dim())) { ExEnv::errn() << indent << "DistSCVector::accumulate_product_rv(SCMatrix*a,SCVector*b): " << "dimensions don't match\n"; abort(); } a->create_vecform(DistSCMatrix::Row); a->vecform_op(DistSCMatrix::CopyToVec); int n = dim()->n(); double *res = new double[n]; for (int i=0; i I = b->all_blocks(SCMatrixSubblockIter::Read); for (I->begin(); I->ready(); I->next()) { Ref blk = dynamic_cast(I->block()); int n = blk->iend - blk->istart; int joff = blk->istart; double *data = blk->data; for (int i=0; invec; i++) { double *aveci = a->vec[i]; for (int j=0; jvecoff] += aveci[j+joff]*data[j]; } } } a->delete_vecform(); messagegrp()->sum(res, n); I = local_blocks(SCMatrixSubblockIter::Accum); for (I->begin(); I->ready(); I->next()) { Ref blk = dynamic_cast(I->block()); int n = blk->iend - blk->istart; int ioff = blk->istart; double *data = blk->data; for (int i=0; in(); for (int i=0; i I = ((DistSCVector*)this)->local_blocks(SCMatrixSubblockIter::Read); for (I->begin(); I->ready(); I->next()) { Ref blk = dynamic_cast(I->block()); int ni = blk->iend - blk->istart; int ioff = blk->istart; double *data = blk->data; for (int i=0; isum(res, n); } void DistSCVector::convert(SCVector *v) { SCVector::convert(v); } Ref DistSCVector::local_blocks(SCMatrixSubblockIter::Access access) { return new SCMatrixListSubblockIter(access, blocklist); } Ref DistSCVector::all_blocks(SCMatrixSubblockIter::Access access) { return new DistSCMatrixListSubblockIter(access, blocklist, messagegrp()); } void DistSCVector::vprint(const char *title, ostream& os, int prec) const { double *data = new double[dim()->n()]; convert(data); int i; int lwidth; double max=this->maxabs(); max = (max==0.0) ? 1.0 : log10(max); if (max < 0.0) max=1.0; lwidth = prec+5+(int) max; os.setf(ios::fixed,ios::floatfield); os.precision(prec); os.setf(ios::right,ios::adjustfield); if (messagegrp()->me() == 0) { if (title) os << endl << indent << title << endl; else os << endl; if (n()==0) { os << indent << "empty vector\n"; return; } for (i=0; i DistSCVector::skit() { return dynamic_cast(kit().pointer()); } ///////////////////////////////////////////////////////////////////////////// // Local Variables: // mode: c++ // c-file-style: "CLJ" // End: