| 1 | //
 | 
|---|
| 2 | // replsymm.cc
 | 
|---|
| 3 | //
 | 
|---|
| 4 | // Copyright (C) 1996 Limit Point Systems, Inc.
 | 
|---|
| 5 | //
 | 
|---|
| 6 | // Author: Curtis Janssen <cljanss@limitpt.com>
 | 
|---|
| 7 | // Maintainer: LPS
 | 
|---|
| 8 | //
 | 
|---|
| 9 | // This file is part of the SC Toolkit.
 | 
|---|
| 10 | //
 | 
|---|
| 11 | // The SC Toolkit is free software; you can redistribute it and/or modify
 | 
|---|
| 12 | // it under the terms of the GNU Library General Public License as published by
 | 
|---|
| 13 | // the Free Software Foundation; either version 2, or (at your option)
 | 
|---|
| 14 | // any later version.
 | 
|---|
| 15 | //
 | 
|---|
| 16 | // The SC Toolkit is distributed in the hope that it will be useful,
 | 
|---|
| 17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 19 | // GNU Library General Public License for more details.
 | 
|---|
| 20 | //
 | 
|---|
| 21 | // You should have received a copy of the GNU Library General Public License
 | 
|---|
| 22 | // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
 | 
|---|
| 23 | // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
|---|
| 24 | //
 | 
|---|
| 25 | // The U.S. Government is granted a limited license as per AL 91-7.
 | 
|---|
| 26 | //
 | 
|---|
| 27 | 
 | 
|---|
| 28 | #include <iostream>
 | 
|---|
| 29 | #include <iomanip>
 | 
|---|
| 30 | 
 | 
|---|
| 31 | #include <math.h>
 | 
|---|
| 32 | 
 | 
|---|
| 33 | #include <util/misc/formio.h>
 | 
|---|
| 34 | #include <util/keyval/keyval.h>
 | 
|---|
| 35 | #include <math/scmat/repl.h>
 | 
|---|
| 36 | #include <math/scmat/cmatrix.h>
 | 
|---|
| 37 | #include <math/scmat/elemop.h>
 | 
|---|
| 38 | #include <math/scmat/disthql.h>
 | 
|---|
| 39 | #include <math/scmat/offset.h>
 | 
|---|
| 40 | #include <math/scmat/mops.h>
 | 
|---|
| 41 | #include <math/scmat/util.h>
 | 
|---|
| 42 | 
 | 
|---|
| 43 | using namespace std;
 | 
|---|
| 44 | using namespace sc;
 | 
|---|
| 45 | 
 | 
|---|
| 46 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
| 47 | // ReplSymmSCMatrix member functions
 | 
|---|
| 48 | 
 | 
|---|
| 49 | static ClassDesc ReplSymmSCMatrix_cd(
 | 
|---|
| 50 |   typeid(ReplSymmSCMatrix),"ReplSymmSCMatrix",1,"public SymmSCMatrix",
 | 
|---|
| 51 |   0, 0, 0);
 | 
|---|
| 52 | 
 | 
|---|
| 53 | static double **
 | 
|---|
| 54 | init_symm_rows(double *data, int n)
 | 
|---|
| 55 | {
 | 
|---|
| 56 |   double** r = new double*[n];
 | 
|---|
| 57 |   for (int i=0; i<n; i++) r[i] = &data[(i*(i+1))/2];
 | 
|---|
| 58 |   return r;
 | 
|---|
| 59 | }
 | 
|---|
| 60 | 
 | 
|---|
| 61 | ReplSymmSCMatrix::ReplSymmSCMatrix(const RefSCDimension&a,ReplSCMatrixKit*k):
 | 
|---|
| 62 |   SymmSCMatrix(a,k),
 | 
|---|
| 63 |   rows(0)
 | 
|---|
| 64 | {
 | 
|---|
| 65 |   int n = d->n();
 | 
|---|
| 66 | 
 | 
|---|
| 67 |   matrix = new double[n*(n+1)>>1];
 | 
|---|
| 68 |   rows = init_symm_rows(matrix,n);
 | 
|---|
| 69 | 
 | 
|---|
| 70 |   init_blocklist();
 | 
|---|
| 71 | }
 | 
|---|
| 72 | 
 | 
|---|
| 73 | void
 | 
|---|
| 74 | ReplSymmSCMatrix::before_elemop()
 | 
|---|
| 75 | {
 | 
|---|
| 76 |   // zero out the blocks not in my block list
 | 
|---|
| 77 |   int i, j, index;
 | 
|---|
| 78 |   int nproc = messagegrp()->n();
 | 
|---|
| 79 |   int me = messagegrp()->me();
 | 
|---|
| 80 |   for (i=0, index=0; i<d->blocks()->nblock(); i++) {
 | 
|---|
| 81 |       for (j=0; j<=i; j++, index++) {
 | 
|---|
| 82 |           if (index%nproc == me) continue;
 | 
|---|
| 83 |           for (int ii=d->blocks()->start(i); ii<d->blocks()->fence(i); ii++) {
 | 
|---|
| 84 |               for (int jj=d->blocks()->start(j);
 | 
|---|
| 85 |                    jj < d->blocks()->fence(j) && jj <= ii;
 | 
|---|
| 86 |                    jj++) {
 | 
|---|
| 87 |                   matrix[(ii*(ii+1)>>1) + jj] = 0.0;
 | 
|---|
| 88 |                 }
 | 
|---|
| 89 |             }
 | 
|---|
| 90 |         }
 | 
|---|
| 91 |     }
 | 
|---|
| 92 | }
 | 
|---|
| 93 | 
 | 
|---|
| 94 | void
 | 
|---|
| 95 | ReplSymmSCMatrix::after_elemop()
 | 
|---|
| 96 | {
 | 
|---|
| 97 |   messagegrp()->sum(matrix, d->n()*(d->n()+1)>>1);
 | 
|---|
| 98 | }
 | 
|---|
| 99 | 
 | 
|---|
| 100 | void
 | 
|---|
| 101 | ReplSymmSCMatrix::init_blocklist()
 | 
|---|
| 102 | {
 | 
|---|
| 103 |   int i, j, index;
 | 
|---|
| 104 |   int nproc = messagegrp()->n();
 | 
|---|
| 105 |   int me = messagegrp()->me();
 | 
|---|
| 106 |   blocklist = new SCMatrixBlockList;
 | 
|---|
| 107 |   for (i=0, index=0; i<d->blocks()->nblock(); i++) {
 | 
|---|
| 108 |       for (j=0; j<=i; j++, index++) {
 | 
|---|
| 109 |           if (index%nproc != me) continue;
 | 
|---|
| 110 |           blocklist->insert(
 | 
|---|
| 111 |               new SCMatrixLTriSubBlock(d->blocks()->start(i),
 | 
|---|
| 112 |                                        d->blocks()->fence(i),
 | 
|---|
| 113 |                                        d->blocks()->start(j),
 | 
|---|
| 114 |                                        d->blocks()->fence(j),
 | 
|---|
| 115 |                                        matrix));
 | 
|---|
| 116 |         }
 | 
|---|
| 117 |     }
 | 
|---|
| 118 | }
 | 
|---|
| 119 | 
 | 
|---|
| 120 | ReplSymmSCMatrix::~ReplSymmSCMatrix()
 | 
|---|
| 121 | {
 | 
|---|
| 122 |   if (matrix) delete[] matrix;
 | 
|---|
| 123 |   if (rows) delete[] rows;
 | 
|---|
| 124 | }
 | 
|---|
| 125 | 
 | 
|---|
| 126 | int
 | 
|---|
| 127 | ReplSymmSCMatrix::compute_offset(int i,int j) const
 | 
|---|
| 128 | {
 | 
|---|
| 129 |   if (i<0 || j<0 || i>=d->n() || j>=d->n()) {
 | 
|---|
| 130 |       ExEnv::errn() << indent << "ReplSymmSCMatrix: index out of bounds\n";
 | 
|---|
| 131 |       abort();
 | 
|---|
| 132 |     }
 | 
|---|
| 133 |   return ij_offset(i,j);
 | 
|---|
| 134 | }
 | 
|---|
| 135 | 
 | 
|---|
| 136 | double
 | 
|---|
| 137 | ReplSymmSCMatrix::get_element(int i,int j) const
 | 
|---|
| 138 | {
 | 
|---|
| 139 |   return matrix[compute_offset(i,j)];
 | 
|---|
| 140 | }
 | 
|---|
| 141 | 
 | 
|---|
| 142 | void
 | 
|---|
| 143 | ReplSymmSCMatrix::set_element(int i,int j,double a)
 | 
|---|
| 144 | {
 | 
|---|
| 145 |   matrix[compute_offset(i,j)] = a;
 | 
|---|
| 146 | }
 | 
|---|
| 147 | 
 | 
|---|
| 148 | void
 | 
|---|
| 149 | ReplSymmSCMatrix::accumulate_element(int i,int j,double a)
 | 
|---|
| 150 | {
 | 
|---|
| 151 |   matrix[compute_offset(i,j)] += a;
 | 
|---|
| 152 | }
 | 
|---|
| 153 | 
 | 
|---|
| 154 | SCMatrix *
 | 
|---|
| 155 | ReplSymmSCMatrix::get_subblock(int br, int er, int bc, int ec)
 | 
|---|
| 156 | {
 | 
|---|
| 157 |   int nsrow = er-br+1;
 | 
|---|
| 158 |   int nscol = ec-bc+1;
 | 
|---|
| 159 | 
 | 
|---|
| 160 |   if (nsrow > n() || nscol > n()) {
 | 
|---|
| 161 |     ExEnv::errn() << indent
 | 
|---|
| 162 |          << "ReplSymmSCMatrix::get_subblock: trying to get too big a "
 | 
|---|
| 163 |          << "subblock (" << nsrow << "," << nscol
 | 
|---|
| 164 |          << ") from (" << n() << "," << n() << ")\n";
 | 
|---|
| 165 |     abort();
 | 
|---|
| 166 |   }
 | 
|---|
| 167 |   
 | 
|---|
| 168 |   RefSCDimension dnrow = (nsrow==n()) ? dim().pointer():new SCDimension(nsrow);
 | 
|---|
| 169 |   RefSCDimension dncol = (nscol==n()) ? dim().pointer():new SCDimension(nscol);
 | 
|---|
| 170 | 
 | 
|---|
| 171 |   SCMatrix * sb = kit()->matrix(dnrow,dncol);
 | 
|---|
| 172 |   sb->assign(0.0);
 | 
|---|
| 173 | 
 | 
|---|
| 174 |   ReplSCMatrix *lsb =
 | 
|---|
| 175 |     require_dynamic_cast<ReplSCMatrix*>(sb, "ReplSymmSCMatrix::get_subblock");
 | 
|---|
| 176 | 
 | 
|---|
| 177 |   for (int i=0; i < nsrow; i++)
 | 
|---|
| 178 |     for (int j=0; j < nscol; j++)
 | 
|---|
| 179 |       lsb->rows[i][j] = get_element(i+br,j+bc);
 | 
|---|
| 180 |       
 | 
|---|
| 181 |   return sb;
 | 
|---|
| 182 | }
 | 
|---|
| 183 | 
 | 
|---|
| 184 | SymmSCMatrix *
 | 
|---|
| 185 | ReplSymmSCMatrix::get_subblock(int br, int er)
 | 
|---|
| 186 | {
 | 
|---|
| 187 |   int nsrow = er-br+1;
 | 
|---|
| 188 | 
 | 
|---|
| 189 |   if (nsrow > n()) {
 | 
|---|
| 190 |     ExEnv::errn() << indent
 | 
|---|
| 191 |          << "ReplSymmSCMatrix::get_subblock: trying to get too big a "
 | 
|---|
| 192 |          << "subblock (" << nsrow << "," << nsrow
 | 
|---|
| 193 |          << ") from (" << n() << "," << n() << ")\n";
 | 
|---|
| 194 |     abort();
 | 
|---|
| 195 |   }
 | 
|---|
| 196 |   
 | 
|---|
| 197 |   RefSCDimension dnrow = new SCDimension(nsrow);
 | 
|---|
| 198 | 
 | 
|---|
| 199 |   SymmSCMatrix * sb = kit()->symmmatrix(dnrow);
 | 
|---|
| 200 |   sb->assign(0.0);
 | 
|---|
| 201 | 
 | 
|---|
| 202 |   ReplSymmSCMatrix *lsb =
 | 
|---|
| 203 |     require_dynamic_cast<ReplSymmSCMatrix*>(sb, "ReplSymmSCMatrix::get_subblock");
 | 
|---|
| 204 | 
 | 
|---|
| 205 |   for (int i=0; i < nsrow; i++)
 | 
|---|
| 206 |     for (int j=0; j <= i; j++)
 | 
|---|
| 207 |       lsb->rows[i][j] = get_element(i+br,j+br);
 | 
|---|
| 208 |       
 | 
|---|
| 209 |   return sb;
 | 
|---|
| 210 | }
 | 
|---|
| 211 | 
 | 
|---|
| 212 | void
 | 
|---|
| 213 | ReplSymmSCMatrix::assign_subblock(SCMatrix*sb, int br, int er, int bc, int ec)
 | 
|---|
| 214 | {
 | 
|---|
| 215 |   ReplSCMatrix *lsb = require_dynamic_cast<ReplSCMatrix*>(sb,
 | 
|---|
| 216 |                                       "ReplSCMatrix::assign_subblock");
 | 
|---|
| 217 | 
 | 
|---|
| 218 |   int nsrow = er-br+1;
 | 
|---|
| 219 |   int nscol = ec-bc+1;
 | 
|---|
| 220 | 
 | 
|---|
| 221 |   if (nsrow > n() || nscol > n()) {
 | 
|---|
| 222 |     ExEnv::errn() << indent
 | 
|---|
| 223 |          << "ReplSymmSCMatrix::assign_subblock: trying to assign too big a "
 | 
|---|
| 224 |          << "subblock (" << nsrow << "," << nscol
 | 
|---|
| 225 |          << ") to (" << n() << "," << n() << ")\n";
 | 
|---|
| 226 |     abort();
 | 
|---|
| 227 |   }
 | 
|---|
| 228 |   
 | 
|---|
| 229 |   for (int i=0; i < nsrow; i++)
 | 
|---|
| 230 |     for (int j=0; j < nscol; j++)
 | 
|---|
| 231 |       set_element(i+br,j+bc,lsb->rows[i][j]);
 | 
|---|
| 232 | }
 | 
|---|
| 233 | 
 | 
|---|
| 234 | void
 | 
|---|
| 235 | ReplSymmSCMatrix::assign_subblock(SymmSCMatrix*sb, int br, int er)
 | 
|---|
| 236 | {
 | 
|---|
| 237 |   ReplSymmSCMatrix *lsb = require_dynamic_cast<ReplSymmSCMatrix*>(sb,
 | 
|---|
| 238 |                                       "ReplSymmSCMatrix::assign_subblock");
 | 
|---|
| 239 | 
 | 
|---|
| 240 |   int nsrow = er-br+1;
 | 
|---|
| 241 | 
 | 
|---|
| 242 |   if (nsrow > n()) {
 | 
|---|
| 243 |     ExEnv::errn() << indent
 | 
|---|
| 244 |          << "ReplSymmSCMatrix::assign_subblock: trying to assign too big a "
 | 
|---|
| 245 |          << "subblock (" << nsrow << "," << nsrow
 | 
|---|
| 246 |          << ") to (" << n() << "," << n() << ")\n";
 | 
|---|
| 247 |     abort();
 | 
|---|
| 248 |   }
 | 
|---|
| 249 |   
 | 
|---|
| 250 |   for (int i=0; i < nsrow; i++)
 | 
|---|
| 251 |     for (int j=0; j <= i; j++)
 | 
|---|
| 252 |       set_element(i+br,j+br,lsb->rows[i][j]);
 | 
|---|
| 253 | }
 | 
|---|
| 254 | 
 | 
|---|
| 255 | void
 | 
|---|
| 256 | ReplSymmSCMatrix::accumulate_subblock(SCMatrix*sb, int br, int er, int bc, int ec)
 | 
|---|
| 257 | {
 | 
|---|
| 258 |   ReplSCMatrix *lsb = require_dynamic_cast<ReplSCMatrix*>(sb,
 | 
|---|
| 259 |                                   "ReplSymmSCMatrix::accumulate_subblock");
 | 
|---|
| 260 | 
 | 
|---|
| 261 |   int nsrow = er-br+1;
 | 
|---|
| 262 |   int nscol = ec-bc+1;
 | 
|---|
| 263 | 
 | 
|---|
| 264 |   if (nsrow > n() || nscol > n()) {
 | 
|---|
| 265 |     ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate_subblock: "
 | 
|---|
| 266 |          << "trying to accumulate too big a "
 | 
|---|
| 267 |          << "subblock (" << nsrow << "," << nscol
 | 
|---|
| 268 |          << ") to (" << n() << "," << n() << ")\n";
 | 
|---|
| 269 |     abort();
 | 
|---|
| 270 |   }
 | 
|---|
| 271 |   
 | 
|---|
| 272 |   for (int i=0; i < nsrow; i++)
 | 
|---|
| 273 |     for (int j=0; j < nscol; j++)
 | 
|---|
| 274 |       set_element(i+br,j+br,get_element(i+br,j+br)+lsb->rows[i][j]);
 | 
|---|
| 275 | }
 | 
|---|
| 276 | 
 | 
|---|
| 277 | void
 | 
|---|
| 278 | ReplSymmSCMatrix::accumulate_subblock(SymmSCMatrix*sb, int br, int er)
 | 
|---|
| 279 | {
 | 
|---|
| 280 |   ReplSCMatrix *lsb = require_dynamic_cast<ReplSCMatrix*>(sb,
 | 
|---|
| 281 |                                   "ReplSymmSCMatrix::accumulate_subblock");
 | 
|---|
| 282 | 
 | 
|---|
| 283 |   int nsrow = er-br+1;
 | 
|---|
| 284 | 
 | 
|---|
| 285 |   if (nsrow > n()) {
 | 
|---|
| 286 |     ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate_subblock: trying to "
 | 
|---|
| 287 |          << "accumulate too big a "
 | 
|---|
| 288 |          << "subblock (" << nsrow << "," << nsrow
 | 
|---|
| 289 |          << ") to (" << n() << "," << n() << ")\n";
 | 
|---|
| 290 |     abort();
 | 
|---|
| 291 |   }
 | 
|---|
| 292 |   
 | 
|---|
| 293 |   for (int i=0; i < nsrow; i++)
 | 
|---|
| 294 |     for (int j=0; j <= i; j++)
 | 
|---|
| 295 |       set_element(i+br,j+br,get_element(i+br,j+br)+lsb->rows[i][j]);
 | 
|---|
| 296 | }
 | 
|---|
| 297 | 
 | 
|---|
| 298 | SCVector *
 | 
|---|
| 299 | ReplSymmSCMatrix::get_row(int i)
 | 
|---|
| 300 | {
 | 
|---|
| 301 |   if (i >= n()) {
 | 
|---|
| 302 |     ExEnv::errn() << indent << "ReplSymmSCMatrix::get_row: trying to get invalid row "
 | 
|---|
| 303 |          << i << " max " << n() << endl;
 | 
|---|
| 304 |     abort();
 | 
|---|
| 305 |   }
 | 
|---|
| 306 |   
 | 
|---|
| 307 |   SCVector * v = kit()->vector(dim());
 | 
|---|
| 308 | 
 | 
|---|
| 309 |   ReplSCVector *lv =
 | 
|---|
| 310 |     require_dynamic_cast<ReplSCVector*>(v, "ReplSymmSCMatrix::get_row");
 | 
|---|
| 311 | 
 | 
|---|
| 312 |   for (int j=0; j < n(); j++)
 | 
|---|
| 313 |     lv->set_element(j,get_element(i,j));
 | 
|---|
| 314 |       
 | 
|---|
| 315 |   return v;
 | 
|---|
| 316 | }
 | 
|---|
| 317 | 
 | 
|---|
| 318 | void
 | 
|---|
| 319 | ReplSymmSCMatrix::assign_row(SCVector *v, int i)
 | 
|---|
| 320 | {
 | 
|---|
| 321 |   if (i >= n()) {
 | 
|---|
| 322 |     ExEnv::errn() << indent
 | 
|---|
| 323 |          << "ReplSymmSCMatrix::assign_row: trying to assign invalid row "
 | 
|---|
| 324 |          << i << " max " << n() << endl;
 | 
|---|
| 325 |     abort();
 | 
|---|
| 326 |   }
 | 
|---|
| 327 |   
 | 
|---|
| 328 |   if (v->n() != n()) {
 | 
|---|
| 329 |     ExEnv::errn() << indent << "ReplSymmSCMatrix::assign_row: vector is wrong size, "
 | 
|---|
| 330 |          << "is " << v->n() << ", should be " << n() << endl;
 | 
|---|
| 331 |     abort();
 | 
|---|
| 332 |   }
 | 
|---|
| 333 |   
 | 
|---|
| 334 |   ReplSCVector *lv =
 | 
|---|
| 335 |     require_dynamic_cast<ReplSCVector*>(v, "ReplSymmSCMatrix::assign_row");
 | 
|---|
| 336 | 
 | 
|---|
| 337 |   for (int j=0; j < n(); j++)
 | 
|---|
| 338 |     set_element(i,j,lv->get_element(j));
 | 
|---|
| 339 | }
 | 
|---|
| 340 | 
 | 
|---|
| 341 | void
 | 
|---|
| 342 | ReplSymmSCMatrix::accumulate_row(SCVector *v, int i)
 | 
|---|
| 343 | {
 | 
|---|
| 344 |   if (i >= n()) {
 | 
|---|
| 345 |     ExEnv::errn() << indent
 | 
|---|
| 346 |          << "ReplSymmSCMatrix::accumulate_row: trying to assign invalide row "
 | 
|---|
| 347 |          << i << " max " << n() << endl;
 | 
|---|
| 348 |     abort();
 | 
|---|
| 349 |   }
 | 
|---|
| 350 |   
 | 
|---|
| 351 |   if (v->n() != n()) {
 | 
|---|
| 352 |     ExEnv::errn() << indent
 | 
|---|
| 353 |          << "ReplSymmSCMatrix::accumulate_row: vector is wrong size, "
 | 
|---|
| 354 |          << "is " << v->n() << ", should be " << n() << endl;
 | 
|---|
| 355 |     abort();
 | 
|---|
| 356 |   }
 | 
|---|
| 357 |   
 | 
|---|
| 358 |   ReplSCVector *lv =
 | 
|---|
| 359 |     require_dynamic_cast<ReplSCVector*>(v, "ReplSymmSCMatrix::accumulate_row");
 | 
|---|
| 360 | 
 | 
|---|
| 361 |   for (int j=0; j < n(); j++)
 | 
|---|
| 362 |     set_element(i,j,get_element(i,j)+lv->get_element(j));
 | 
|---|
| 363 | }
 | 
|---|
| 364 | 
 | 
|---|
| 365 | void
 | 
|---|
| 366 | ReplSymmSCMatrix::assign_val(double val)
 | 
|---|
| 367 | {
 | 
|---|
| 368 |   int n = (d->n()*(d->n()+1))/2;
 | 
|---|
| 369 |   for (int i=0; i<n; i++) matrix[i] = val;
 | 
|---|
| 370 | }
 | 
|---|
| 371 | 
 | 
|---|
| 372 | void
 | 
|---|
| 373 | ReplSymmSCMatrix::assign_s(SymmSCMatrix*m)
 | 
|---|
| 374 | {
 | 
|---|
| 375 |   ReplSymmSCMatrix* lm = dynamic_cast<ReplSymmSCMatrix*>(m);
 | 
|---|
| 376 |   if (lm && dim()->equiv(lm->dim())) {
 | 
|---|
| 377 |       int d = i_offset(n());
 | 
|---|
| 378 |       memcpy(matrix, lm->matrix, sizeof(double)*d);
 | 
|---|
| 379 |     }
 | 
|---|
| 380 |   else
 | 
|---|
| 381 |       SymmSCMatrix::assign(m);
 | 
|---|
| 382 | }
 | 
|---|
| 383 | 
 | 
|---|
| 384 | void
 | 
|---|
| 385 | ReplSymmSCMatrix::assign_p(const double*m)
 | 
|---|
| 386 | {
 | 
|---|
| 387 |   int d = i_offset(n());
 | 
|---|
| 388 |   memcpy(matrix, m, sizeof(double)*d);
 | 
|---|
| 389 | }
 | 
|---|
| 390 | 
 | 
|---|
| 391 | void
 | 
|---|
| 392 | ReplSymmSCMatrix::assign_pp(const double**m)
 | 
|---|
| 393 | {
 | 
|---|
| 394 |   for (int i=0; i < n(); i++)
 | 
|---|
| 395 |       for (int j=0; j <= i; j++)
 | 
|---|
| 396 |           rows[i][j] = m[i][j];
 | 
|---|
| 397 | }
 | 
|---|
| 398 | 
 | 
|---|
| 399 | void
 | 
|---|
| 400 | ReplSymmSCMatrix::scale(double s)
 | 
|---|
| 401 | {
 | 
|---|
| 402 |   int nelem = i_offset(n());
 | 
|---|
| 403 |   for (int i=0; i < nelem; i++) matrix[i] *= s;
 | 
|---|
| 404 | }
 | 
|---|
| 405 | 
 | 
|---|
| 406 | void
 | 
|---|
| 407 | ReplSymmSCMatrix::accumulate(const SymmSCMatrix*a)
 | 
|---|
| 408 | {
 | 
|---|
| 409 |   // make sure that the arguments is of the correct type
 | 
|---|
| 410 |   const ReplSymmSCMatrix* la
 | 
|---|
| 411 |     = require_dynamic_cast<const ReplSymmSCMatrix*>(a,"ReplSymmSCMatrix::accumulate");
 | 
|---|
| 412 | 
 | 
|---|
| 413 |   // make sure that the dimensions match
 | 
|---|
| 414 |   if (!dim()->equiv(la->dim())) {
 | 
|---|
| 415 |       ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate(SCMatrix*a): "
 | 
|---|
| 416 |            << "dimensions don't match\n";
 | 
|---|
| 417 |       abort();
 | 
|---|
| 418 |     }
 | 
|---|
| 419 | 
 | 
|---|
| 420 |   int nelem = (this->n() * (this->n() + 1))/2;
 | 
|---|
| 421 |   for (int i=0; i<nelem; i++) matrix[i] += la->matrix[i];
 | 
|---|
| 422 | }
 | 
|---|
| 423 | 
 | 
|---|
| 424 | double
 | 
|---|
| 425 | ReplSymmSCMatrix::invert_this()
 | 
|---|
| 426 | {
 | 
|---|
| 427 |   if (messagegrp()->n() == 1)
 | 
|---|
| 428 |       return cmat_invert(rows,1,n());
 | 
|---|
| 429 |   else {
 | 
|---|
| 430 |       RefDiagSCMatrix refa = kit()->diagmatrix(d);
 | 
|---|
| 431 |       RefSCMatrix refb = kit()->matrix(d,d);
 | 
|---|
| 432 |       diagonalize(refa.pointer(),refb.pointer());
 | 
|---|
| 433 |       double determ = 1.0;
 | 
|---|
| 434 |       for (int i=0; i<dim()->n(); i++) {
 | 
|---|
| 435 |           double val = refa->get_element(i);
 | 
|---|
| 436 |           determ *= val;
 | 
|---|
| 437 |         }
 | 
|---|
| 438 |       Ref<SCElementOp> op = new SCElementInvert(1.0e-12);
 | 
|---|
| 439 |       refa->element_op(op.pointer());
 | 
|---|
| 440 |       assign(0.0);
 | 
|---|
| 441 |       accumulate_transform(refb.pointer(), refa.pointer());
 | 
|---|
| 442 |       return determ;
 | 
|---|
| 443 |     }
 | 
|---|
| 444 | }
 | 
|---|
| 445 | 
 | 
|---|
| 446 | double
 | 
|---|
| 447 | ReplSymmSCMatrix::determ_this()
 | 
|---|
| 448 | {
 | 
|---|
| 449 |   if (messagegrp()->n() == 1)
 | 
|---|
| 450 |       return cmat_determ(rows,1,n());
 | 
|---|
| 451 |   else {
 | 
|---|
| 452 |       RefDiagSCMatrix refa = kit()->diagmatrix(d);
 | 
|---|
| 453 |       RefSCMatrix refb = kit()->matrix(d,d);
 | 
|---|
| 454 |       diagonalize(refa.pointer(),refb.pointer());
 | 
|---|
| 455 |       double determ = 1.0;
 | 
|---|
| 456 |       for (int i=0; i<dim()->n(); i++) {
 | 
|---|
| 457 |           double val = refa->get_element(i);
 | 
|---|
| 458 |           determ *= val;
 | 
|---|
| 459 |         }
 | 
|---|
| 460 |       return determ;
 | 
|---|
| 461 |     }
 | 
|---|
| 462 | }
 | 
|---|
| 463 | 
 | 
|---|
| 464 | double
 | 
|---|
| 465 | ReplSymmSCMatrix::trace()
 | 
|---|
| 466 | {
 | 
|---|
| 467 |   double ret=0;
 | 
|---|
| 468 |   for (int i=0; i < n(); i++) ret += rows[i][i];
 | 
|---|
| 469 |   return ret;
 | 
|---|
| 470 | }
 | 
|---|
| 471 | 
 | 
|---|
| 472 | double
 | 
|---|
| 473 | ReplSymmSCMatrix::solve_this(SCVector*v)
 | 
|---|
| 474 | {
 | 
|---|
| 475 |   ReplSCVector* lv =
 | 
|---|
| 476 |     require_dynamic_cast<ReplSCVector*>(v,"ReplSymmSCMatrix::solve_this");
 | 
|---|
| 477 |   
 | 
|---|
| 478 |   // make sure that the dimensions match
 | 
|---|
| 479 |   if (!dim()->equiv(lv->dim())) {
 | 
|---|
| 480 |       ExEnv::errn() << indent << "ReplSymmSCMatrix::solve_this(SCVector*v): "
 | 
|---|
| 481 |            << "dimensions don't match\n";
 | 
|---|
| 482 |       abort();
 | 
|---|
| 483 |     }
 | 
|---|
| 484 | 
 | 
|---|
| 485 |   return cmat_solve_lin(rows,1,lv->vector,n());
 | 
|---|
| 486 | }
 | 
|---|
| 487 | 
 | 
|---|
| 488 | void
 | 
|---|
| 489 | ReplSymmSCMatrix::gen_invert_this()
 | 
|---|
| 490 | {
 | 
|---|
| 491 |   RefSCMatrix evecs = kit()->matrix(dim(),dim());
 | 
|---|
| 492 |   RefDiagSCMatrix evals = kit()->diagmatrix(dim());
 | 
|---|
| 493 | 
 | 
|---|
| 494 |   const char *name = "ReplSymmSCMatrix::gen_invert_this";
 | 
|---|
| 495 |   ReplDiagSCMatrix *levals = require_dynamic_cast<ReplDiagSCMatrix*>(evals,name);
 | 
|---|
| 496 |   ReplSCMatrix *levecs = require_dynamic_cast<ReplSCMatrix*>(evecs,name);
 | 
|---|
| 497 | 
 | 
|---|
| 498 |   this->diagonalize(evals.pointer(), evecs.pointer());
 | 
|---|
| 499 | 
 | 
|---|
| 500 |   for (int i=0; i < n(); i++) {
 | 
|---|
| 501 |       if (fabs(levals->matrix[i]) > 1.0e-8)
 | 
|---|
| 502 |           levals->matrix[i] = 1.0/levals->matrix[i];
 | 
|---|
| 503 |       else
 | 
|---|
| 504 |           levals->matrix[i] = 0;
 | 
|---|
| 505 |     }
 | 
|---|
| 506 | 
 | 
|---|
| 507 |   assign(0.0);
 | 
|---|
| 508 |   accumulate_transform(levecs, levals);
 | 
|---|
| 509 | }
 | 
|---|
| 510 | 
 | 
|---|
| 511 | void
 | 
|---|
| 512 | ReplSymmSCMatrix::diagonalize(DiagSCMatrix*a,SCMatrix*b)
 | 
|---|
| 513 | {
 | 
|---|
| 514 |   int i;
 | 
|---|
| 515 |   
 | 
|---|
| 516 |   const char* name = "ReplSymmSCMatrix::diagonalize";
 | 
|---|
| 517 |   // make sure that the arguments is of the correct type
 | 
|---|
| 518 |   ReplDiagSCMatrix* la = require_dynamic_cast<ReplDiagSCMatrix*>(a,name);
 | 
|---|
| 519 |   ReplSCMatrix* lb = require_dynamic_cast<ReplSCMatrix*>(b,name);
 | 
|---|
| 520 | 
 | 
|---|
| 521 |   if (!dim()->equiv(la->dim()) ||
 | 
|---|
| 522 |       !dim()->equiv(lb->coldim()) || !dim()->equiv(lb->rowdim())) {
 | 
|---|
| 523 |       ExEnv::errn() << indent
 | 
|---|
| 524 |            << "ReplSymmSCMatrix::diagonalize(DiagSCMatrix*a,SCMatrix*b): "
 | 
|---|
| 525 |            << "bad dims\n";
 | 
|---|
| 526 |       abort();
 | 
|---|
| 527 |     }
 | 
|---|
| 528 | 
 | 
|---|
| 529 |   // This sets up the index list of columns to be stored on this node
 | 
|---|
| 530 |   int n = dim()->n();
 | 
|---|
| 531 |   int me = messagegrp()->me();
 | 
|---|
| 532 |   int nproc = messagegrp()->n();
 | 
|---|
| 533 | 
 | 
|---|
| 534 |   // if there are fewer vectors than processors, do serial diagonalization
 | 
|---|
| 535 |   if (n < nproc || nproc==1) {
 | 
|---|
| 536 |       double *eigvals = la->matrix;
 | 
|---|
| 537 |       double **eigvecs = lb->rows;
 | 
|---|
| 538 |       cmat_diag(rows, eigvals, eigvecs, n, 1, 1.0e-15);
 | 
|---|
| 539 |     }
 | 
|---|
| 540 |   else {
 | 
|---|
| 541 |       int nvec = n/nproc + (me<(n%nproc)?1:0);
 | 
|---|
| 542 |       int mvec = n/nproc + ((n%nproc) ? 1 : 0);
 | 
|---|
| 543 |       
 | 
|---|
| 544 |       int *ivec = new int[nvec];
 | 
|---|
| 545 |       for (i=0; i<nvec; i++)
 | 
|---|
| 546 |           ivec[i] = i*nproc + me;
 | 
|---|
| 547 | 
 | 
|---|
| 548 |       double *eigvals = new double[n];
 | 
|---|
| 549 |       double **eigvecs = cmat_new_rect_matrix(mvec, n);
 | 
|---|
| 550 |       double **rect = cmat_new_rect_matrix(mvec, n);
 | 
|---|
| 551 | 
 | 
|---|
| 552 |       lb->assign(0.0);
 | 
|---|
| 553 | 
 | 
|---|
| 554 |       for (i=0; i < nvec; i++) {
 | 
|---|
| 555 |           int c = ivec[i];
 | 
|---|
| 556 |           int j;
 | 
|---|
| 557 |           for (j=0; j <= c; j++)
 | 
|---|
| 558 |               rect[i][j] = rows[c][j];
 | 
|---|
| 559 |           for (; j < n; j++)
 | 
|---|
| 560 |               rect[i][j] = rows[j][c];
 | 
|---|
| 561 |         }
 | 
|---|
| 562 |   
 | 
|---|
| 563 |       dist_diagonalize(n, nvec, rect[0], eigvals, eigvecs[0], messagegrp());
 | 
|---|
| 564 | 
 | 
|---|
| 565 |       la->assign(eigvals);
 | 
|---|
| 566 |       delete[] eigvals;
 | 
|---|
| 567 | 
 | 
|---|
| 568 |       int *tivec = new int [mvec];
 | 
|---|
| 569 |       for (i=0; i < nproc; i++) {
 | 
|---|
| 570 |           int tnvec;
 | 
|---|
| 571 |           
 | 
|---|
| 572 |           if (i==me) {
 | 
|---|
| 573 |               messagegrp()->bcast(nvec, me);
 | 
|---|
| 574 |               messagegrp()->bcast(eigvecs[0], n*nvec, me);
 | 
|---|
| 575 |               messagegrp()->bcast(ivec, nvec, me);
 | 
|---|
| 576 |               tnvec = nvec;
 | 
|---|
| 577 |               memcpy(tivec, ivec, sizeof(int)*nvec);
 | 
|---|
| 578 |               memcpy(rect[0], eigvecs[0], sizeof(double)*n*nvec);
 | 
|---|
| 579 |             }
 | 
|---|
| 580 |           else {
 | 
|---|
| 581 |               messagegrp()->bcast(tnvec, i);
 | 
|---|
| 582 |               messagegrp()->bcast(rect[0], n*tnvec, i);
 | 
|---|
| 583 |               messagegrp()->bcast(tivec, tnvec, i);
 | 
|---|
| 584 |             }
 | 
|---|
| 585 | 
 | 
|---|
| 586 |           for (int j=0; j < tnvec; j++) {
 | 
|---|
| 587 |               int c = tivec[j];
 | 
|---|
| 588 |               for (int k=0; k < n; k++)
 | 
|---|
| 589 |                   lb->rows[k][c] = rect[j][k];
 | 
|---|
| 590 |             }
 | 
|---|
| 591 |         }
 | 
|---|
| 592 | 
 | 
|---|
| 593 |       delete[] ivec;
 | 
|---|
| 594 |       delete[] tivec;
 | 
|---|
| 595 |       cmat_delete_matrix(eigvecs);
 | 
|---|
| 596 |       cmat_delete_matrix(rect);
 | 
|---|
| 597 |     }
 | 
|---|
| 598 | }
 | 
|---|
| 599 | 
 | 
|---|
| 600 | // computes this += a * a.t
 | 
|---|
| 601 | void
 | 
|---|
| 602 | ReplSymmSCMatrix::accumulate_symmetric_product(SCMatrix*a)
 | 
|---|
| 603 | {
 | 
|---|
| 604 |   // make sure that the argument is of the correct type
 | 
|---|
| 605 |   ReplSCMatrix* la
 | 
|---|
| 606 |     = require_dynamic_cast<ReplSCMatrix*>(a,"ReplSymmSCMatrix::"
 | 
|---|
| 607 |                                           "accumulate_symmetric_product");
 | 
|---|
| 608 | 
 | 
|---|
| 609 |   if (!dim()->equiv(la->rowdim())) {
 | 
|---|
| 610 |       ExEnv::errn() << indent << "ReplSymmSCMatrix::"
 | 
|---|
| 611 |            << "accumulate_symmetric_product(SCMatrix*a): bad dim\n";
 | 
|---|
| 612 |       abort();
 | 
|---|
| 613 |     }
 | 
|---|
| 614 | 
 | 
|---|
| 615 |   cmat_symmetric_mxm(rows,n(),la->rows,la->ncol(),1);
 | 
|---|
| 616 | }
 | 
|---|
| 617 | 
 | 
|---|
| 618 | // computes this += a + a.t
 | 
|---|
| 619 | void
 | 
|---|
| 620 | ReplSymmSCMatrix::accumulate_symmetric_sum(SCMatrix*a)
 | 
|---|
| 621 | {
 | 
|---|
| 622 |   // make sure that the argument is of the correct type
 | 
|---|
| 623 |   ReplSCMatrix* la
 | 
|---|
| 624 |     = require_dynamic_cast<ReplSCMatrix*>(a,"ReplSymmSCMatrix::"
 | 
|---|
| 625 |                                           "accumulate_symmetric_sum");
 | 
|---|
| 626 | 
 | 
|---|
| 627 |   if (!dim()->equiv(la->rowdim()) || !dim()->equiv(la->coldim())) {
 | 
|---|
| 628 |       ExEnv::errn() << indent << "ReplSymmSCMatrix::"
 | 
|---|
| 629 |            << "accumulate_symmetric_sum(SCMatrix*a): bad dim\n";
 | 
|---|
| 630 |       abort();
 | 
|---|
| 631 |     }
 | 
|---|
| 632 | 
 | 
|---|
| 633 |   int n = dim().n();
 | 
|---|
| 634 |   double** tdat = this->rows;
 | 
|---|
| 635 |   double** adat = la->rows;
 | 
|---|
| 636 |   for (int i=0; i<n; i++) {
 | 
|---|
| 637 |       for (int j=0; j<=i; j++) {
 | 
|---|
| 638 |           tdat[i][j] += adat[i][j] + adat[j][i];
 | 
|---|
| 639 |         }
 | 
|---|
| 640 |     }
 | 
|---|
| 641 | }
 | 
|---|
| 642 | 
 | 
|---|
| 643 | void
 | 
|---|
| 644 | ReplSymmSCMatrix::accumulate_symmetric_outer_product(SCVector*a)
 | 
|---|
| 645 | {
 | 
|---|
| 646 |   // make sure that the argument is of the correct type
 | 
|---|
| 647 |   ReplSCVector* la
 | 
|---|
| 648 |     = require_dynamic_cast<ReplSCVector*>(a,"ReplSymmSCMatrix::"
 | 
|---|
| 649 |                                       "accumulate_symmetric_outer_product");
 | 
|---|
| 650 | 
 | 
|---|
| 651 |   if (!dim()->equiv(la->dim())) {
 | 
|---|
| 652 |       ExEnv::errn() << indent << "ReplSymmSCMatrix::"
 | 
|---|
| 653 |            << "accumulate_symmetric_outer_product(SCMatrix*a): bad dim\n";
 | 
|---|
| 654 |       abort();
 | 
|---|
| 655 |     }
 | 
|---|
| 656 | 
 | 
|---|
| 657 |   int n = dim().n();
 | 
|---|
| 658 |   double** tdat = this->rows;
 | 
|---|
| 659 |   double* adat = la->vector;
 | 
|---|
| 660 |   for (int i=0; i<n; i++) {
 | 
|---|
| 661 |       for (int j=0; j<=i; j++) {
 | 
|---|
| 662 |           tdat[i][j] += adat[i]*adat[j];
 | 
|---|
| 663 |         }
 | 
|---|
| 664 |     }
 | 
|---|
| 665 | }
 | 
|---|
| 666 |     
 | 
|---|
| 667 | // this += a * b * transpose(a)
 | 
|---|
| 668 | void
 | 
|---|
| 669 | ReplSymmSCMatrix::accumulate_transform(SCMatrix*a,SymmSCMatrix*b,
 | 
|---|
| 670 |                                        SCMatrix::Transform t)
 | 
|---|
| 671 | {
 | 
|---|
| 672 |   int i,j,k;
 | 
|---|
| 673 |   int ii,jj;
 | 
|---|
| 674 |   int nc, nr;
 | 
|---|
| 675 | 
 | 
|---|
| 676 |   // do the necessary castdowns
 | 
|---|
| 677 |   ReplSCMatrix*la
 | 
|---|
| 678 |     = require_dynamic_cast<ReplSCMatrix*>(a,"%s::accumulate_transform",
 | 
|---|
| 679 |                                       class_name());
 | 
|---|
| 680 |   ReplSymmSCMatrix*lb = require_dynamic_cast<ReplSymmSCMatrix*>(
 | 
|---|
| 681 |       b,"%s::accumulate_transform", class_name());
 | 
|---|
| 682 | 
 | 
|---|
| 683 |   // check the dimensions
 | 
|---|
| 684 |   if (t == SCMatrix::NormalTransform) {
 | 
|---|
| 685 |     if (!dim()->equiv(la->rowdim()) || !lb->dim()->equiv(la->coldim())) {
 | 
|---|
| 686 |       ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate_transform: bad dim\n";
 | 
|---|
| 687 |       abort();
 | 
|---|
| 688 |     }
 | 
|---|
| 689 | 
 | 
|---|
| 690 |     nc = lb->n();
 | 
|---|
| 691 |     nr = la->nrow();
 | 
|---|
| 692 |   } else {
 | 
|---|
| 693 |     if (!dim()->equiv(la->coldim()) || !lb->dim()->equiv(la->rowdim())) {
 | 
|---|
| 694 |       ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate_transform: bad dim\n";
 | 
|---|
| 695 |       abort();
 | 
|---|
| 696 |     }
 | 
|---|
| 697 | 
 | 
|---|
| 698 |     nc = lb->n();
 | 
|---|
| 699 |     nr = la->ncol();
 | 
|---|
| 700 |   }
 | 
|---|
| 701 | 
 | 
|---|
| 702 |   if (nr==0 || nc==0)
 | 
|---|
| 703 |     return;
 | 
|---|
| 704 |   
 | 
|---|
| 705 |   int nproc = messagegrp()->n();
 | 
|---|
| 706 | 
 | 
|---|
| 707 |   double **ablock = cmat_new_square_matrix(D1);
 | 
|---|
| 708 |   double **bblock = cmat_new_square_matrix(D1);
 | 
|---|
| 709 |   double **cblock = cmat_new_square_matrix(D1);
 | 
|---|
| 710 | 
 | 
|---|
| 711 |   // if one processor then minimize the amount of memory used
 | 
|---|
| 712 |   if (nproc == 1) {
 | 
|---|
| 713 |     double **temp = cmat_new_rect_matrix(D1,nc);
 | 
|---|
| 714 | 
 | 
|---|
| 715 |     for (i=0; i < nr; i += D1) {
 | 
|---|
| 716 |       int ni = nr-i;
 | 
|---|
| 717 |       if (ni > D1) ni = D1;
 | 
|---|
| 718 | 
 | 
|---|
| 719 |       memset(temp[0], 0, sizeof(double)*D1*nc);
 | 
|---|
| 720 | 
 | 
|---|
| 721 |       for (j=0; j < nc; j+= D1) {
 | 
|---|
| 722 |         int nj = nc-j;
 | 
|---|
| 723 |         if (nj > D1) nj = D1;
 | 
|---|
| 724 | 
 | 
|---|
| 725 |         for (k=0; k < nc; k += D1) {
 | 
|---|
| 726 |         
 | 
|---|
| 727 |           int nk = nc-k;
 | 
|---|
| 728 |           if (nk > D1) nk = D1;
 | 
|---|
| 729 | 
 | 
|---|
| 730 |           if (t == SCMatrix::NormalTransform)
 | 
|---|
| 731 |             copy_block(ablock, la->rows, i, ni, k, nk);
 | 
|---|
| 732 |           else
 | 
|---|
| 733 |             copy_trans_block(ablock, la->rows, i, ni, k, nk);
 | 
|---|
| 734 |           
 | 
|---|
| 735 |           copy_sym_block(bblock, lb->rows, j, nj, k, nk);
 | 
|---|
| 736 |           copy_block(cblock, temp, 0, ni, j, nj);
 | 
|---|
| 737 |           mult_block(ablock, bblock, cblock, ni, nj, nk);
 | 
|---|
| 738 |           return_block(temp, cblock, 0, ni, j, nj);
 | 
|---|
| 739 |         }
 | 
|---|
| 740 |       }
 | 
|---|
| 741 | 
 | 
|---|
| 742 |       // now do ab * a~
 | 
|---|
| 743 |       for (j=0; j <= i; j+= D1) {
 | 
|---|
| 744 |         int nj = nr-j;
 | 
|---|
| 745 |         if (nj > D1) nj = D1;
 | 
|---|
| 746 | 
 | 
|---|
| 747 |         memset(cblock[0], 0, sizeof(double)*D1*D1);
 | 
|---|
| 748 |       
 | 
|---|
| 749 |         for (k=0; k < nc; k += D1) {
 | 
|---|
| 750 |         
 | 
|---|
| 751 |           int nk = nc-k;
 | 
|---|
| 752 |           if (nk > D1) nk = D1;
 | 
|---|
| 753 | 
 | 
|---|
| 754 |           copy_block(ablock, temp, 0, ni, k, nk);
 | 
|---|
| 755 |           if (t == SCMatrix::NormalTransform)
 | 
|---|
| 756 |             copy_block(bblock, la->rows, j, nj, k, nk);
 | 
|---|
| 757 |           else
 | 
|---|
| 758 |             copy_trans_block(bblock, la->rows, j, nj, k, nk);
 | 
|---|
| 759 |           
 | 
|---|
| 760 |           mult_block(ablock, bblock, cblock, ni, nj, nk);
 | 
|---|
| 761 |         }
 | 
|---|
| 762 | 
 | 
|---|
| 763 |         // copy cblock(i,j) into result
 | 
|---|
| 764 |         if (j==i) {
 | 
|---|
| 765 |           for (ii=0; ii < ni; ii++)
 | 
|---|
| 766 |             for (jj=0; jj <= ii; jj++)
 | 
|---|
| 767 |               rows[i+ii][j+jj] += cblock[ii][jj];
 | 
|---|
| 768 |         } else {
 | 
|---|
| 769 |           for (ii=0; ii < ni; ii++)
 | 
|---|
| 770 |             for (jj=0; jj < nj; jj++)
 | 
|---|
| 771 |               rows[i+ii][j+jj] += cblock[ii][jj];
 | 
|---|
| 772 |         }
 | 
|---|
| 773 |       }
 | 
|---|
| 774 |     }
 | 
|---|
| 775 | 
 | 
|---|
| 776 |     cmat_delete_matrix(temp);
 | 
|---|
| 777 |   }
 | 
|---|
| 778 | 
 | 
|---|
| 779 |   // this version requires a full temp matrix be kept
 | 
|---|
| 780 |   else {
 | 
|---|
| 781 |     int me = messagegrp()->me();
 | 
|---|
| 782 |     int mod = nr%nproc;
 | 
|---|
| 783 |     int njrow = nr/nproc + ((mod <= me) ? 0 : 1);
 | 
|---|
| 784 |     int jstart = (nr/nproc)*me + ((mod <= me) ? mod : me);
 | 
|---|
| 785 |     int jend = jstart+njrow;
 | 
|---|
| 786 | 
 | 
|---|
| 787 |     double **temp = cmat_new_rect_matrix(nr,nc);
 | 
|---|
| 788 |     memset(temp[0], 0, sizeof(double)*nr*nc);
 | 
|---|
| 789 |     
 | 
|---|
| 790 |     for (i=0; i < nc; i += D1) {
 | 
|---|
| 791 |       int ni = nc-i;
 | 
|---|
| 792 |       if (ni > D1) ni = D1;
 | 
|---|
| 793 | 
 | 
|---|
| 794 |       for (k=0; k < nc; k += D1) {
 | 
|---|
| 795 |         int nk = nc-k;
 | 
|---|
| 796 |         if (nk > D1) nk = D1;
 | 
|---|
| 797 |           
 | 
|---|
| 798 |         copy_sym_block(ablock, lb->rows, i, ni, k, nk);
 | 
|---|
| 799 | 
 | 
|---|
| 800 |         for (j=jstart; j < jend; j += D1) {
 | 
|---|
| 801 |           int nj = jend-j;
 | 
|---|
| 802 |           if (nj > D1) nj = D1;
 | 
|---|
| 803 |           
 | 
|---|
| 804 |           if (t == SCMatrix::NormalTransform)
 | 
|---|
| 805 |             copy_block(bblock, la->rows, j, nj, k, nk);
 | 
|---|
| 806 |           else
 | 
|---|
| 807 |             copy_trans_block(bblock, la->rows, j, nj, k, nk);
 | 
|---|
| 808 | 
 | 
|---|
| 809 |           memset(cblock[0], 0, sizeof(double)*D1*D1);
 | 
|---|
| 810 |           mult_block(ablock, bblock, cblock, ni, nj, nk);
 | 
|---|
| 811 | 
 | 
|---|
| 812 |           for (jj=0; jj < nj; jj++)
 | 
|---|
| 813 |             for (ii=0; ii < ni; ii++)
 | 
|---|
| 814 |               temp[j+jj][i+ii] += cblock[ii][jj];
 | 
|---|
| 815 |         }
 | 
|---|
| 816 |       }
 | 
|---|
| 817 |     }
 | 
|---|
| 818 | 
 | 
|---|
| 819 |     for (i=0; i < nproc; i++) {
 | 
|---|
| 820 |       njrow = nr/nproc + ((mod <= i) ? 0 : 1);
 | 
|---|
| 821 |       jstart = (nr/nproc)*i + ((mod <= i) ? mod : i);
 | 
|---|
| 822 |       if (!njrow)
 | 
|---|
| 823 |         break;
 | 
|---|
| 824 |       messagegrp()->bcast(temp[jstart], njrow*nc, i);
 | 
|---|
| 825 |     }
 | 
|---|
| 826 | 
 | 
|---|
| 827 |     int ind=0;
 | 
|---|
| 828 |     for (i=0; i < nr; i += D1) {
 | 
|---|
| 829 |       int ni = nr-i;
 | 
|---|
| 830 |       if (ni > D1) ni = D1;
 | 
|---|
| 831 |         
 | 
|---|
| 832 |       for (j=0; j <= i; j += D1, ind++) {
 | 
|---|
| 833 |         if (ind%nproc != me)
 | 
|---|
| 834 |           continue;
 | 
|---|
| 835 |         
 | 
|---|
| 836 |         int nj = nr-j;
 | 
|---|
| 837 |         if (nj > D1) nj = D1;
 | 
|---|
| 838 |         
 | 
|---|
| 839 |         memset(cblock[0], 0, sizeof(double)*D1*D1);
 | 
|---|
| 840 |       
 | 
|---|
| 841 |         for (k=0; k < nc; k += D1) {
 | 
|---|
| 842 |           int nk = nc-k;
 | 
|---|
| 843 |           if (nk > D1) nk = D1;
 | 
|---|
| 844 |             
 | 
|---|
| 845 |           if (t == SCMatrix::NormalTransform)
 | 
|---|
| 846 |             copy_block(ablock, la->rows, i, ni, k, nk);
 | 
|---|
| 847 |           else
 | 
|---|
| 848 |             copy_trans_block(ablock, la->rows, i, ni, k, nk);
 | 
|---|
| 849 |           copy_block(bblock, temp, j, nj, k, nk);
 | 
|---|
| 850 |           mult_block(ablock, bblock, cblock, ni, nj, nk);
 | 
|---|
| 851 |         }
 | 
|---|
| 852 | 
 | 
|---|
| 853 |         if (i==j) {
 | 
|---|
| 854 |           for (ii=0; ii < ni; ii++)
 | 
|---|
| 855 |             for (jj=0; jj <= ii; jj++)
 | 
|---|
| 856 |               rows[i+ii][j+jj] += cblock[ii][jj];
 | 
|---|
| 857 |         } else {
 | 
|---|
| 858 |           for (ii=0; ii < ni; ii++)
 | 
|---|
| 859 |             for (jj=0; jj < nj; jj++)
 | 
|---|
| 860 |               rows[i+ii][j+jj] += cblock[ii][jj];
 | 
|---|
| 861 |         }
 | 
|---|
| 862 |       }
 | 
|---|
| 863 |     }
 | 
|---|
| 864 |     
 | 
|---|
| 865 |     ind=0;
 | 
|---|
| 866 |     for (i=0; i < nr; i += D1) {
 | 
|---|
| 867 |       int ni = nr-i;
 | 
|---|
| 868 |       if (ni > D1) ni = D1;
 | 
|---|
| 869 | 
 | 
|---|
| 870 |       for (j=0; j <= i; j += D1, ind++) {
 | 
|---|
| 871 |         int nj = nr-j;
 | 
|---|
| 872 |         if (nj > D1) nj = D1;
 | 
|---|
| 873 | 
 | 
|---|
| 874 |         int proc = ind%nproc;
 | 
|---|
| 875 | 
 | 
|---|
| 876 |         if (proc==me)
 | 
|---|
| 877 |           copy_sym_block(ablock, rows, i, ni, j, nj);
 | 
|---|
| 878 |           
 | 
|---|
| 879 |         messagegrp()->bcast(ablock[0], D1*D1, proc);
 | 
|---|
| 880 | 
 | 
|---|
| 881 |         if (i==j) {
 | 
|---|
| 882 |           for (ii=0; ii < ni; ii++)
 | 
|---|
| 883 |             for (jj=0; jj <= ii; jj++)
 | 
|---|
| 884 |               rows[i+ii][j+jj] = ablock[ii][jj];
 | 
|---|
| 885 |         } else {
 | 
|---|
| 886 |           for (ii=0; ii < ni; ii++)
 | 
|---|
| 887 |             for (jj=0; jj < nj; jj++)
 | 
|---|
| 888 |               rows[i+ii][j+jj] = ablock[ii][jj];
 | 
|---|
| 889 |         }
 | 
|---|
| 890 |       }
 | 
|---|
| 891 |     }
 | 
|---|
| 892 | 
 | 
|---|
| 893 |     cmat_delete_matrix(temp);
 | 
|---|
| 894 |   }
 | 
|---|
| 895 | 
 | 
|---|
| 896 |   cmat_delete_matrix(ablock);
 | 
|---|
| 897 |   cmat_delete_matrix(bblock);
 | 
|---|
| 898 |   cmat_delete_matrix(cblock);
 | 
|---|
| 899 | }
 | 
|---|
| 900 | 
 | 
|---|
| 901 | // this += a * b * transpose(a)
 | 
|---|
| 902 | void
 | 
|---|
| 903 | ReplSymmSCMatrix::accumulate_transform(SCMatrix*a,DiagSCMatrix*b,
 | 
|---|
| 904 |                                        SCMatrix::Transform t)
 | 
|---|
| 905 | {
 | 
|---|
| 906 |   // do the necessary castdowns
 | 
|---|
| 907 |   ReplSCMatrix*la
 | 
|---|
| 908 |     = require_dynamic_cast<ReplSCMatrix*>(a,"%s::accumulate_transform",
 | 
|---|
| 909 |                                       class_name());
 | 
|---|
| 910 |   ReplDiagSCMatrix*lb
 | 
|---|
| 911 |     = require_dynamic_cast<ReplDiagSCMatrix*>(b,"%s::accumulate_transform",
 | 
|---|
| 912 |                                           class_name());
 | 
|---|
| 913 | 
 | 
|---|
| 914 |   // check the dimensions
 | 
|---|
| 915 |   if (!dim()->equiv(la->rowdim()) || !lb->dim()->equiv(la->coldim())) {
 | 
|---|
| 916 |       ExEnv::errn() << indent << "ReplSymmSCMatrix::accumulate_transform: bad dim\n";
 | 
|---|
| 917 |       abort();
 | 
|---|
| 918 |     }
 | 
|---|
| 919 | 
 | 
|---|
| 920 |   cmat_transform_diagonal_matrix(rows,n(),lb->matrix,lb->n(),la->rows,1);
 | 
|---|
| 921 | }
 | 
|---|
| 922 | 
 | 
|---|
| 923 | void
 | 
|---|
| 924 | ReplSymmSCMatrix::accumulate_transform(SymmSCMatrix*a,SymmSCMatrix*b)
 | 
|---|
| 925 | {
 | 
|---|
| 926 |   SymmSCMatrix::accumulate_transform(a,b);
 | 
|---|
| 927 | }
 | 
|---|
| 928 | 
 | 
|---|
| 929 | double
 | 
|---|
| 930 | ReplSymmSCMatrix::scalar_product(SCVector*a)
 | 
|---|
| 931 | {
 | 
|---|
| 932 |   // make sure that the argument is of the correct type
 | 
|---|
| 933 |   ReplSCVector* la
 | 
|---|
| 934 |     = require_dynamic_cast<ReplSCVector*>(a,"ReplSCVector::scalar_product");
 | 
|---|
| 935 | 
 | 
|---|
| 936 |   // make sure that the dimensions match
 | 
|---|
| 937 |   if (!dim()->equiv(la->dim())) {
 | 
|---|
| 938 |       ExEnv::errn() << indent << "ReplSCVector::scale_product(SCVector*a): "
 | 
|---|
| 939 |            << "dimensions don't match\n";
 | 
|---|
| 940 |       abort();
 | 
|---|
| 941 |     }
 | 
|---|
| 942 | 
 | 
|---|
| 943 |   int nelem = n();
 | 
|---|
| 944 |   double* adat = la->vector;
 | 
|---|
| 945 |   double result = 0.0;
 | 
|---|
| 946 |   for (int i=0; i<nelem; i++) {
 | 
|---|
| 947 |       for (int j=0; j<i; j++) {
 | 
|---|
| 948 |           result += 2.0 * rows[i][j] * adat[i] * adat[j];
 | 
|---|
| 949 |         }
 | 
|---|
| 950 |       result += rows[i][i] * adat[i] * adat[i];
 | 
|---|
| 951 |     }
 | 
|---|
| 952 |   return result;
 | 
|---|
| 953 | }
 | 
|---|
| 954 | 
 | 
|---|
| 955 | void
 | 
|---|
| 956 | ReplSymmSCMatrix::element_op(const Ref<SCElementOp>& op)
 | 
|---|
| 957 | {
 | 
|---|
| 958 |   if (op->has_side_effects()) before_elemop();
 | 
|---|
| 959 |   scmat_perform_op_on_blocks(op, blocklist);
 | 
|---|
| 960 |   if (op->has_side_effects()) after_elemop();
 | 
|---|
| 961 |   if (op->has_collect()) op->collect(messagegrp());
 | 
|---|
| 962 | }
 | 
|---|
| 963 | 
 | 
|---|
| 964 | void
 | 
|---|
| 965 | ReplSymmSCMatrix::element_op(const Ref<SCElementOp2>& op,
 | 
|---|
| 966 |                               SymmSCMatrix* m)
 | 
|---|
| 967 | {
 | 
|---|
| 968 |   ReplSymmSCMatrix *lm
 | 
|---|
| 969 |       = require_dynamic_cast<ReplSymmSCMatrix*>(m,"ReplSymSCMatrix::element_op");
 | 
|---|
| 970 | 
 | 
|---|
| 971 |   if (!dim()->equiv(lm->dim())) {
 | 
|---|
| 972 |       ExEnv::errn() << indent << "ReplSymmSCMatrix: bad element_op\n";
 | 
|---|
| 973 |       abort();
 | 
|---|
| 974 |     }
 | 
|---|
| 975 |   if (op->has_side_effects()) before_elemop();
 | 
|---|
| 976 |   if (op->has_side_effects_in_arg()) lm->before_elemop();
 | 
|---|
| 977 |   SCMatrixBlockListIter i, j;
 | 
|---|
| 978 |   for (i = blocklist->begin(), j = lm->blocklist->begin();
 | 
|---|
| 979 |        i != blocklist->end();
 | 
|---|
| 980 |        i++, j++) {
 | 
|---|
| 981 |       op->process_base(i.block(), j.block());
 | 
|---|
| 982 |     }
 | 
|---|
| 983 |   if (op->has_side_effects()) after_elemop();
 | 
|---|
| 984 |   if (op->has_side_effects_in_arg()) lm->after_elemop();
 | 
|---|
| 985 |   if (op->has_collect()) op->collect(messagegrp());
 | 
|---|
| 986 | }
 | 
|---|
| 987 | 
 | 
|---|
| 988 | void
 | 
|---|
| 989 | ReplSymmSCMatrix::element_op(const Ref<SCElementOp3>& op,
 | 
|---|
| 990 |                               SymmSCMatrix* m,SymmSCMatrix* n)
 | 
|---|
| 991 | {
 | 
|---|
| 992 |   ReplSymmSCMatrix *lm
 | 
|---|
| 993 |       = require_dynamic_cast<ReplSymmSCMatrix*>(m,"ReplSymSCMatrix::element_op");
 | 
|---|
| 994 |   ReplSymmSCMatrix *ln
 | 
|---|
| 995 |       = require_dynamic_cast<ReplSymmSCMatrix*>(n,"ReplSymSCMatrix::element_op");
 | 
|---|
| 996 | 
 | 
|---|
| 997 |   if (!dim()->equiv(lm->dim()) || !dim()->equiv(ln->dim())) {
 | 
|---|
| 998 |       ExEnv::errn() << indent << "ReplSymmSCMatrix: bad element_op\n";
 | 
|---|
| 999 |       abort();
 | 
|---|
| 1000 |     }
 | 
|---|
| 1001 |   if (op->has_side_effects()) before_elemop();
 | 
|---|
| 1002 |   if (op->has_side_effects_in_arg1()) lm->before_elemop();
 | 
|---|
| 1003 |   if (op->has_side_effects_in_arg2()) ln->before_elemop();
 | 
|---|
| 1004 |   SCMatrixBlockListIter i, j, k;
 | 
|---|
| 1005 |   for (i = blocklist->begin(),
 | 
|---|
| 1006 |            j = lm->blocklist->begin(),
 | 
|---|
| 1007 |            k = ln->blocklist->begin();
 | 
|---|
| 1008 |        i != blocklist->end();
 | 
|---|
| 1009 |        i++, j++, k++) {
 | 
|---|
| 1010 |       op->process_base(i.block(), j.block(), k.block());
 | 
|---|
| 1011 |     }
 | 
|---|
| 1012 |   if (op->has_side_effects()) after_elemop();
 | 
|---|
| 1013 |   if (op->has_side_effects_in_arg1()) lm->after_elemop();
 | 
|---|
| 1014 |   if (op->has_side_effects_in_arg2()) ln->after_elemop();
 | 
|---|
| 1015 |   if (op->has_collect()) op->collect(messagegrp());
 | 
|---|
| 1016 | }
 | 
|---|
| 1017 | 
 | 
|---|
| 1018 | // from Ed Seidl at the NIH (with a bit of hacking)
 | 
|---|
| 1019 | void
 | 
|---|
| 1020 | ReplSymmSCMatrix::vprint(const char *title, ostream& os, int prec) const
 | 
|---|
| 1021 | {
 | 
|---|
| 1022 |   int ii,jj,kk,nn;
 | 
|---|
| 1023 |   int i,j;
 | 
|---|
| 1024 |   int lwidth,width;
 | 
|---|
| 1025 |   double max=this->maxabs();
 | 
|---|
| 1026 | 
 | 
|---|
| 1027 |   if (messagegrp()->me() != 0) return;
 | 
|---|
| 1028 | 
 | 
|---|
| 1029 |   max = (max==0.0) ? 1.0 : log10(max);
 | 
|---|
| 1030 |   if (max < 0.0) max=1.0;
 | 
|---|
| 1031 | 
 | 
|---|
| 1032 |   lwidth = prec + 5 + (int) max;
 | 
|---|
| 1033 |   width = 75/(lwidth+SCFormIO::getindent(os));
 | 
|---|
| 1034 | 
 | 
|---|
| 1035 |   os.setf(ios::fixed,ios::floatfield); os.precision(prec);
 | 
|---|
| 1036 |   os.setf(ios::right,ios::adjustfield);
 | 
|---|
| 1037 | 
 | 
|---|
| 1038 |   if (title)
 | 
|---|
| 1039 |     os << endl << indent << title << endl;
 | 
|---|
| 1040 |   else
 | 
|---|
| 1041 |     os << endl;
 | 
|---|
| 1042 | 
 | 
|---|
| 1043 |   if (n()==0) {
 | 
|---|
| 1044 |     os << indent << "empty matrix\n";
 | 
|---|
| 1045 |     return;
 | 
|---|
| 1046 |   }
 | 
|---|
| 1047 | 
 | 
|---|
| 1048 |   for (ii=jj=0;;) {
 | 
|---|
| 1049 |     ii++; jj++;
 | 
|---|
| 1050 |     kk=width*jj;
 | 
|---|
| 1051 |     nn = (n() > kk) ? kk : n();
 | 
|---|
| 1052 | 
 | 
|---|
| 1053 |     // print column indices
 | 
|---|
| 1054 |     os << indent;
 | 
|---|
| 1055 |     for (i=ii; i <= nn; i++)
 | 
|---|
| 1056 |       os << setw(lwidth) << i;
 | 
|---|
| 1057 |     os << endl;
 | 
|---|
| 1058 | 
 | 
|---|
| 1059 |     // print the rows
 | 
|---|
| 1060 |     for (i=ii-1; i < n() ; i++) {
 | 
|---|
| 1061 |       os << indent << setw(5) << i+1;
 | 
|---|
| 1062 |       for (j=ii-1; j<nn && j<=i; j++)
 | 
|---|
| 1063 |         os << setw(lwidth) << rows[i][j];
 | 
|---|
| 1064 |       os << endl;
 | 
|---|
| 1065 |     }
 | 
|---|
| 1066 |     os << endl;
 | 
|---|
| 1067 | 
 | 
|---|
| 1068 |     if (n() <= kk) {
 | 
|---|
| 1069 |       os.flush();
 | 
|---|
| 1070 |       return;
 | 
|---|
| 1071 |     }
 | 
|---|
| 1072 | 
 | 
|---|
| 1073 |     ii=kk;
 | 
|---|
| 1074 |   }
 | 
|---|
| 1075 | }
 | 
|---|
| 1076 | 
 | 
|---|
| 1077 | Ref<SCMatrixSubblockIter>
 | 
|---|
| 1078 | ReplSymmSCMatrix::local_blocks(SCMatrixSubblockIter::Access access)
 | 
|---|
| 1079 | {
 | 
|---|
| 1080 |   return new ReplSCMatrixListSubblockIter(access, blocklist,
 | 
|---|
| 1081 |                                           messagegrp(),
 | 
|---|
| 1082 |                                           matrix, (d->n()*(d->n()+1))/2);
 | 
|---|
| 1083 | }
 | 
|---|
| 1084 | 
 | 
|---|
| 1085 | Ref<SCMatrixSubblockIter>
 | 
|---|
| 1086 | ReplSymmSCMatrix::all_blocks(SCMatrixSubblockIter::Access access)
 | 
|---|
| 1087 | {
 | 
|---|
| 1088 |   if (access == SCMatrixSubblockIter::Write) {
 | 
|---|
| 1089 |       ExEnv::errn() << indent << "ReplSymmSCMatrix::all_blocks: "
 | 
|---|
| 1090 |            << "Write access permitted for local blocks only"
 | 
|---|
| 1091 |            << endl;
 | 
|---|
| 1092 |       abort();
 | 
|---|
| 1093 |     }
 | 
|---|
| 1094 |   Ref<SCMatrixBlockList> allblocklist = new SCMatrixBlockList();
 | 
|---|
| 1095 |   allblocklist->insert(new SCMatrixLTriSubBlock(0, d->n(),
 | 
|---|
| 1096 |                                                 0, d->n(), matrix));
 | 
|---|
| 1097 |   return new ReplSCMatrixListSubblockIter(access, allblocklist,
 | 
|---|
| 1098 |                                           messagegrp(),
 | 
|---|
| 1099 |                                           matrix, (d->n()*(d->n()+1))/2);
 | 
|---|
| 1100 | }
 | 
|---|
| 1101 | 
 | 
|---|
| 1102 | Ref<ReplSCMatrixKit>
 | 
|---|
| 1103 | ReplSymmSCMatrix::skit()
 | 
|---|
| 1104 | {
 | 
|---|
| 1105 |   return dynamic_cast<ReplSCMatrixKit*>(kit().pointer());
 | 
|---|
| 1106 | }
 | 
|---|
| 1107 | 
 | 
|---|
| 1108 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
| 1109 | 
 | 
|---|
| 1110 | // Local Variables:
 | 
|---|
| 1111 | // mode: c++
 | 
|---|
| 1112 | // c-file-style: "CLJ"
 | 
|---|
| 1113 | // End:
 | 
|---|