| [0b990d] | 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:
 | 
|---|