1 // 2 // elemop.h 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 #ifndef _math_scmat_elemop_h 29 #define _math_scmat_elemop_h 30 31 #ifdef __GNUC__ 32 #pragma interface 33 #endif 34 35 #include <util/state/state.h> 36 #include <util/group/message.h> 37 38 namespace sc { 39 40 class SCMatrixBlock; 41 class SCMatrixBlockIter; 42 class SCMatrixRectBlock; 43 class SCMatrixLTriBlock; 44 class SCMatrixDiagBlock; 45 class SCVectorSimpleBlock; 46 class SCMatrixRectSubBlock; 47 class SCMatrixLTriSubBlock; 48 class SCMatrixDiagSubBlock; 49 class SCVectorSimpleSubBlock; 50 51 class SCMatrix; 52 class SymmSCMatrix; 53 class DiagSCMatrix; 54 class SCVector; 55 56 /** Objects of class SCElementOp are used to perform operations on the 57 elements of matrices. When the SCElementOp object is given to the 58 element_op member of a matrix, each block the matrix is passed to one 59 of the process, process_base, or process_base members. */ 60 class SCElementOp: public SavableState { 61 public: 62 SCElementOp(); SCElementOp(StateIn & s)63 SCElementOp(StateIn&s): SavableState(s) {} 64 virtual ~SCElementOp(); 65 /** If duplicates of the SCElementOp exist (that is, there is more than 66 one node), then if has_collect returns nonzero then collect is 67 called with a MessageGrp reference after all of the blocks have 68 been processed. The default return value of has_collect is 0 and 69 collect's default action is do nothing. If defer_collect member is 70 called with nonzero, collect will do nothing (this is only used by 71 the blocked matrices). */ 72 virtual int has_collect(); 73 virtual void defer_collect(int); 74 virtual void collect(const Ref<MessageGrp>&); 75 /** Multithreaded use of cloneable SCElementOp objects requires that 76 data from cloned objects be collected. The default implementation 77 will throw an exception. */ 78 virtual void collect(const Ref<SCElementOp>&); 79 /** By default this returns nonzero. If the ElementOp specialization 80 will change any elements of the matrix, then this must be 81 overridden to return nonzero. */ 82 virtual int has_side_effects(); 83 84 /** Returns true if this SCElementOp is threadsafe. The default 85 * implementation returns false. */ 86 virtual bool threadsafe(); 87 88 /** Returns true if this SCElementOp supports the cloneable member. The 89 * default implmentation returns false. */ 90 virtual bool cloneable(); 91 92 /** Returns a clone of this object. This is needed for multithreaded 93 use of SCElementOp objects that are not thread safe. The default 94 implemenation throws an exception. */ 95 virtual Ref<SCElementOp> clone(); 96 97 /** This is the fallback routine to process blocks and is called 98 by process_spec members that are not overridden. */ 99 virtual void process(SCMatrixBlockIter&) = 0; 100 101 /** Lazy matrix implementors can call this member when the 102 type of block specialization is unknown. However, this 103 will attempt to dynamic_cast block to a block specialization 104 and will thus be less efficient. */ 105 void process_base(SCMatrixBlock*block); 106 107 /** Matrices should call these members when the type of block is known. 108 ElementOp specializations should override these when 109 efficiency is important, since these give the most efficient access 110 to the elements of the block. */ 111 virtual void process_spec_rect(SCMatrixRectBlock*); 112 virtual void process_spec_ltri(SCMatrixLTriBlock*); 113 virtual void process_spec_diag(SCMatrixDiagBlock*); 114 virtual void process_spec_vsimp(SCVectorSimpleBlock*); 115 virtual void process_spec_rectsub(SCMatrixRectSubBlock*); 116 virtual void process_spec_ltrisub(SCMatrixLTriSubBlock*); 117 virtual void process_spec_diagsub(SCMatrixDiagSubBlock*); 118 virtual void process_spec_vsimpsub(SCVectorSimpleSubBlock*); 119 }; 120 121 /** The SCElementOp2 class is very similar to the SCElementOp class except 122 that pairs of blocks are treated simultaneously. The two matrices 123 involved must have identical storage layout, which will be the case if 124 both matrices are of the same type and dimensions. */ 125 class SCElementOp2: public SavableState { 126 public: 127 SCElementOp2(); SCElementOp2(StateIn & s)128 SCElementOp2(StateIn&s): SavableState(s) {} 129 virtual ~SCElementOp2(); 130 virtual int has_collect(); 131 virtual void defer_collect(int); 132 virtual int has_side_effects(); 133 virtual int has_side_effects_in_arg(); 134 virtual void collect(const Ref<MessageGrp>&); 135 virtual void process(SCMatrixBlockIter&,SCMatrixBlockIter&) = 0; 136 void process_base(SCMatrixBlock*,SCMatrixBlock*); 137 virtual void process_spec_rect(SCMatrixRectBlock*,SCMatrixRectBlock*); 138 virtual void process_spec_ltri(SCMatrixLTriBlock*,SCMatrixLTriBlock*); 139 virtual void process_spec_diag(SCMatrixDiagBlock*,SCMatrixDiagBlock*); 140 virtual void process_spec_vsimp(SCVectorSimpleBlock*,SCVectorSimpleBlock*); 141 }; 142 143 /** The SCElementOp3 class is very similar to the SCElementOp class except 144 that a triplet of blocks is treated simultaneously. The three matrices 145 involved must have identical storage layout, which will be the case if 146 all matrices are of the same type and dimensions. */ 147 class SCElementOp3: public SavableState { 148 public: 149 SCElementOp3(); SCElementOp3(StateIn & s)150 SCElementOp3(StateIn&s): SavableState(s) {} 151 virtual ~SCElementOp3(); 152 virtual int has_collect(); 153 virtual void defer_collect(int); 154 virtual int has_side_effects(); 155 virtual int has_side_effects_in_arg1(); 156 virtual int has_side_effects_in_arg2(); 157 virtual void collect(const Ref<MessageGrp>&); 158 virtual void process(SCMatrixBlockIter&, 159 SCMatrixBlockIter&, 160 SCMatrixBlockIter&) = 0; 161 void process_base(SCMatrixBlock*,SCMatrixBlock*,SCMatrixBlock*); 162 virtual void process_spec_rect(SCMatrixRectBlock*, 163 SCMatrixRectBlock*, 164 SCMatrixRectBlock*); 165 virtual void process_spec_ltri(SCMatrixLTriBlock*, 166 SCMatrixLTriBlock*, 167 SCMatrixLTriBlock*); 168 virtual void process_spec_diag(SCMatrixDiagBlock*, 169 SCMatrixDiagBlock*, 170 SCMatrixDiagBlock*); 171 virtual void process_spec_vsimp(SCVectorSimpleBlock*, 172 SCVectorSimpleBlock*, 173 SCVectorSimpleBlock*); 174 }; 175 176 class SCElementScalarProduct: public SCElementOp2 { 177 private: 178 int deferred_; 179 double product; 180 public: 181 SCElementScalarProduct(); 182 SCElementScalarProduct(StateIn&); 183 ~SCElementScalarProduct(); 184 void save_data_state(StateOut&); 185 void process(SCMatrixBlockIter&,SCMatrixBlockIter&); 186 int has_collect(); 187 void defer_collect(int); 188 void collect(const Ref<MessageGrp>&); 189 double result(); init()190 void init() { product = 0.0; } 191 }; 192 193 194 class SCDestructiveElementProduct: public SCElementOp2 { 195 public: 196 SCDestructiveElementProduct(); 197 SCDestructiveElementProduct(StateIn&); 198 ~SCDestructiveElementProduct(); 199 int has_side_effects(); 200 void save_data_state(StateOut&); 201 void process(SCMatrixBlockIter&,SCMatrixBlockIter&); 202 }; 203 204 class SCElementScale: public SCElementOp { 205 private: 206 double scale; 207 public: 208 SCElementScale(double a); 209 SCElementScale(StateIn&); 210 ~SCElementScale(); 211 int has_side_effects(); 212 void save_data_state(StateOut&); 213 void process(SCMatrixBlockIter&); 214 }; 215 216 class SCElementRandomize: public SCElementOp { 217 private: 218 double assign; 219 public: 220 SCElementRandomize(); 221 SCElementRandomize(StateIn&); 222 ~SCElementRandomize(); 223 int has_side_effects(); 224 void save_data_state(StateOut&); 225 void process(SCMatrixBlockIter&); 226 }; 227 228 class SCElementAssign: public SCElementOp { 229 private: 230 double assign; 231 public: 232 SCElementAssign(double a); 233 SCElementAssign(StateIn&); 234 ~SCElementAssign(); 235 int has_side_effects(); 236 void save_data_state(StateOut&); 237 void process(SCMatrixBlockIter&); 238 }; 239 240 class SCElementSquareRoot: public SCElementOp { 241 public: 242 SCElementSquareRoot(); 243 SCElementSquareRoot(double a); 244 SCElementSquareRoot(StateIn&); 245 ~SCElementSquareRoot(); 246 int has_side_effects(); 247 void save_data_state(StateOut&); 248 void process(SCMatrixBlockIter&); 249 }; 250 251 class SCElementInvert: public SCElementOp { 252 private: 253 double threshold_; 254 int nbelowthreshold_; 255 int deferred_; 256 public: 257 SCElementInvert(double threshold = 0.0); 258 SCElementInvert(StateIn&); 259 ~SCElementInvert(); 260 int has_side_effects(); 261 void save_data_state(StateOut&); 262 void process(SCMatrixBlockIter&); 263 int has_collect(); 264 void defer_collect(int); 265 void collect(const Ref<MessageGrp>&); 266 void collect(const Ref<SCElementOp>&); result()267 int result() { return nbelowthreshold_; } 268 }; 269 270 271 class SCElementScaleDiagonal: public SCElementOp { 272 private: 273 double scale_diagonal; 274 public: 275 SCElementScaleDiagonal(double a); 276 SCElementScaleDiagonal(StateIn&); 277 ~SCElementScaleDiagonal(); 278 int has_side_effects(); 279 void save_data_state(StateOut&); 280 void process(SCMatrixBlockIter&); 281 }; 282 283 class SCElementShiftDiagonal: public SCElementOp { 284 private: 285 double shift_diagonal; 286 public: 287 SCElementShiftDiagonal(double a); 288 SCElementShiftDiagonal(StateIn&); 289 ~SCElementShiftDiagonal(); 290 int has_side_effects(); 291 void save_data_state(StateOut&); 292 void process(SCMatrixBlockIter&); 293 }; 294 295 class SCElementMaxAbs: public SCElementOp { 296 private: 297 int deferred_; 298 double r; 299 public: 300 SCElementMaxAbs(); 301 SCElementMaxAbs(StateIn&); 302 ~SCElementMaxAbs(); 303 void save_data_state(StateOut&); 304 void process(SCMatrixBlockIter&); 305 int has_collect(); 306 void defer_collect(int); 307 void collect(const Ref<MessageGrp>&); 308 void collect(const Ref<SCElementOp>&); 309 double result(); 310 }; 311 312 313 class SCElementMinAbs: public SCElementOp { 314 private: 315 int deferred_; 316 double r; 317 public: 318 // rinit must be greater than the magnitude of the smallest element 319 SCElementMinAbs(double rinit); 320 SCElementMinAbs(StateIn&); 321 ~SCElementMinAbs(); 322 void save_data_state(StateOut&); 323 void process(SCMatrixBlockIter&); 324 int has_collect(); 325 void defer_collect(int); 326 void collect(const Ref<MessageGrp>&); 327 void collect(const Ref<SCElementOp>&); 328 double result(); 329 }; 330 331 332 class SCElementSumAbs: public SCElementOp { 333 private: 334 int deferred_; 335 double r; 336 public: 337 SCElementSumAbs(); 338 SCElementSumAbs(StateIn&); 339 ~SCElementSumAbs(); 340 void save_data_state(StateOut&); 341 void process(SCMatrixBlockIter&); 342 int has_collect(); 343 void defer_collect(int); 344 void collect(const Ref<MessageGrp>&); 345 void collect(const Ref<SCElementOp>&); 346 double result(); init()347 void init() { r = 0.0; } 348 }; 349 350 /// Computed k-norm of matrix. 351 class SCElementKNorm: public SCElementOp { 352 private: 353 int deferred_; 354 double r_; // result 355 double k_; // norm parameter 356 public: 357 /// by default compute 2-norm 358 SCElementKNorm(double k = 2.0); 359 SCElementKNorm(StateIn&); 360 ~SCElementKNorm(); 361 void save_data_state(StateOut&); 362 void process(SCMatrixBlockIter&); 363 int has_collect(); 364 void defer_collect(int); 365 void collect(const Ref<MessageGrp>&); 366 void collect(const Ref<SCElementOp>&); 367 double result(); init()368 void init() { r_ = 0.0; } 369 }; 370 371 class SCElementDot: public SCElementOp { 372 private: 373 double** avects; 374 double** bvects; 375 int length; 376 public: 377 SCElementDot(StateIn&); 378 void save_data_state(StateOut&); 379 SCElementDot(double**a, double**b, int length); 380 void process(SCMatrixBlockIter&); 381 int has_side_effects(); 382 }; 383 384 class SCElementAccumulateSCMatrix: public SCElementOp { 385 private: 386 SCMatrix *m; 387 public: 388 SCElementAccumulateSCMatrix(SCMatrix *); 389 int has_side_effects(); 390 void process(SCMatrixBlockIter&); 391 }; 392 393 class SCElementAccumulateSymmSCMatrix: public SCElementOp { 394 private: 395 SymmSCMatrix *m; 396 public: 397 SCElementAccumulateSymmSCMatrix(SymmSCMatrix *); 398 int has_side_effects(); 399 void process(SCMatrixBlockIter&); 400 }; 401 402 class SCElementAccumulateDiagSCMatrix: public SCElementOp { 403 private: 404 DiagSCMatrix *m; 405 public: 406 SCElementAccumulateDiagSCMatrix(DiagSCMatrix *); 407 int has_side_effects(); 408 void process(SCMatrixBlockIter&); 409 }; 410 411 class SCElementAccumulateSCVector: public SCElementOp { 412 private: 413 SCVector *m; 414 public: 415 SCElementAccumulateSCVector(SCVector *); 416 int has_side_effects(); 417 void process(SCMatrixBlockIter&); 418 }; 419 420 } 421 422 #endif 423 424 // Local Variables: 425 // mode: c++ 426 // c-file-style: "CLJ" 427 // End: 428