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