1 //
2 // elemop.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 #ifdef __GNUC__
29 #pragma implementation
30 #endif
31 
32 #include <stdexcept>
33 
34 #include <stdlib.h>
35 #include <cmath>
36 
37 #include <util/misc/formio.h>
38 #include <util/state/stateio.h>
39 #include <math/scmat/block.h>
40 #include <math/scmat/blkiter.h>
41 #include <math/scmat/elemop.h>
42 #include <math/scmat/abstract.h>
43 
44 using namespace sc;
45 
46 /////////////////////////////////////////////////////////////////////////////
47 // SCElementOp member functions
48 
49 static ClassDesc SCElementOp_cd(
50   typeid(SCElementOp),"SCElementOp",1,"public SavableState",
51   0, 0, 0);
52 
SCElementOp()53 SCElementOp::SCElementOp()
54 {
55 }
56 
~SCElementOp()57 SCElementOp::~SCElementOp()
58 {
59 }
60 
61 int
has_collect()62 SCElementOp::has_collect()
63 {
64   return 0;
65 }
66 
67 void
defer_collect(int)68 SCElementOp::defer_collect(int)
69 {
70 }
71 
72 int
has_side_effects()73 SCElementOp::has_side_effects()
74 {
75   return 0;
76 }
77 
78 void
collect(const Ref<MessageGrp> &)79 SCElementOp::collect(const Ref<MessageGrp>&)
80 {
81 }
82 
83 bool
threadsafe()84 SCElementOp::threadsafe()
85 {
86   return false;
87 }
88 
89 bool
cloneable()90 SCElementOp::cloneable()
91 {
92   return false;
93 }
94 
95 Ref<SCElementOp>
clone()96 SCElementOp::clone()
97 {
98   throw std::runtime_error("SCElementOp::clone: not implemented");
99 }
100 
101 void
collect(const Ref<SCElementOp> &)102 SCElementOp::collect(const Ref<SCElementOp> &)
103 {
104   throw std::runtime_error("SCElementOp::collect(const Ref<SCElementOp> &): "
105                            "not implemented");
106 }
107 
108 void
process_base(SCMatrixBlock * a)109 SCElementOp::process_base(SCMatrixBlock* a)
110 {
111   if (dynamic_cast<SCMatrixRectBlock*>(a))
112     process_spec_rect(dynamic_cast<SCMatrixRectBlock*>(a));
113   else if (dynamic_cast<SCMatrixLTriBlock*>(a))
114     process_spec_ltri(dynamic_cast<SCMatrixLTriBlock*>(a));
115   else if (dynamic_cast<SCMatrixDiagBlock*>(a))
116     process_spec_diag(dynamic_cast<SCMatrixDiagBlock*>(a));
117   else if (dynamic_cast<SCVectorSimpleBlock*>(a))
118     process_spec_vsimp(dynamic_cast<SCVectorSimpleBlock*>(a));
119   else if (dynamic_cast<SCMatrixRectSubBlock*>(a))
120     process_spec_rectsub(dynamic_cast<SCMatrixRectSubBlock*>(a));
121   else if (dynamic_cast<SCMatrixLTriSubBlock*>(a))
122     process_spec_ltrisub(dynamic_cast<SCMatrixLTriSubBlock*>(a));
123   else if (dynamic_cast<SCMatrixDiagSubBlock*>(a))
124     process_spec_diagsub(dynamic_cast<SCMatrixDiagSubBlock*>(a));
125   else if (dynamic_cast<SCVectorSimpleSubBlock*>(a))
126     process_spec_vsimpsub(dynamic_cast<SCVectorSimpleSubBlock*>(a));
127   else
128     a->process(this);
129 }
130 
131 // If specializations of SCElementOp do not handle a particle
132 // block type, then these functions will be called and will
133 // set up an appropiate block iterator which specializations
134 // of SCElementOp must handle since it is pure virtual.
135 
136 void
process_spec_rect(SCMatrixRectBlock * a)137 SCElementOp::process_spec_rect(SCMatrixRectBlock* a)
138 {
139   SCMatrixBlockIter*i = new SCMatrixRectBlockIter(a);
140   SCMatrixBlockIter&r=*i;
141   process(r);
142   // this causes a SCMatrixRectBlock::operator int() to be
143   // called with this = 0x0 using gcc 2.5.6
144   // process(*i,b);
145   delete i;
146 }
147 void
process_spec_ltri(SCMatrixLTriBlock * a)148 SCElementOp::process_spec_ltri(SCMatrixLTriBlock* a)
149 {
150   SCMatrixBlockIter*i = new SCMatrixLTriBlockIter(a);
151   process(*i);
152   delete i;
153 }
154 void
process_spec_diag(SCMatrixDiagBlock * a)155 SCElementOp::process_spec_diag(SCMatrixDiagBlock* a)
156 {
157   SCMatrixBlockIter*i = new SCMatrixDiagBlockIter(a);
158   process(*i);
159   delete i;
160 }
161 void
process_spec_vsimp(SCVectorSimpleBlock * a)162 SCElementOp::process_spec_vsimp(SCVectorSimpleBlock* a)
163 {
164   SCMatrixBlockIter*i = new SCVectorSimpleBlockIter(a);
165   process(*i);
166   delete i;
167 }
168 void
process_spec_rectsub(SCMatrixRectSubBlock * a)169 SCElementOp::process_spec_rectsub(SCMatrixRectSubBlock* a)
170 {
171   SCMatrixBlockIter*i = new SCMatrixRectSubBlockIter(a);
172   SCMatrixBlockIter&r=*i;
173   process(r);
174   // this causes a SCMatrixRectBlock::operator int() to be
175   // called with this = 0x0 using gcc 2.5.6
176   // process(*i,b);
177   delete i;
178 }
179 void
process_spec_ltrisub(SCMatrixLTriSubBlock * a)180 SCElementOp::process_spec_ltrisub(SCMatrixLTriSubBlock* a)
181 {
182   SCMatrixBlockIter*i = new SCMatrixLTriSubBlockIter(a);
183   process(*i);
184   delete i;
185 }
186 void
process_spec_diagsub(SCMatrixDiagSubBlock * a)187 SCElementOp::process_spec_diagsub(SCMatrixDiagSubBlock* a)
188 {
189   SCMatrixBlockIter*i = new SCMatrixDiagSubBlockIter(a);
190   process(*i);
191   delete i;
192 }
193 void
process_spec_vsimpsub(SCVectorSimpleSubBlock * a)194 SCElementOp::process_spec_vsimpsub(SCVectorSimpleSubBlock* a)
195 {
196   SCMatrixBlockIter*i = new SCVectorSimpleSubBlockIter(a);
197   process(*i);
198   delete i;
199 }
200 
201 /////////////////////////////////////////////////////////////////////////////
202 // SCElementOp2 member functions
203 
204 static ClassDesc SCElementOp2_cd(
205   typeid(SCElementOp2),"SCElementOp2",1,"public SavableState",
206   0, 0, 0);
207 
SCElementOp2()208 SCElementOp2::SCElementOp2()
209 {
210 }
211 
~SCElementOp2()212 SCElementOp2::~SCElementOp2()
213 {
214 }
215 
216 int
has_collect()217 SCElementOp2::has_collect()
218 {
219   return 0;
220 }
221 
222 void
defer_collect(int)223 SCElementOp2::defer_collect(int)
224 {
225 }
226 
227 int
has_side_effects()228 SCElementOp2::has_side_effects()
229 {
230   return 0;
231 }
232 
233 int
has_side_effects_in_arg()234 SCElementOp2::has_side_effects_in_arg()
235 {
236   return 0;
237 }
238 
239 void
collect(const Ref<MessageGrp> &)240 SCElementOp2::collect(const Ref<MessageGrp>&)
241 {
242 }
243 
244 void
process_base(SCMatrixBlock * a,SCMatrixBlock * b)245 SCElementOp2::process_base(SCMatrixBlock* a, SCMatrixBlock* b)
246 {
247   a->process(this, b);
248 }
249 
250 // If specializations of SCElementOp2 do not handle a particle
251 // block type, then these functions will be called and will
252 // set up an appropiate block iterator which specializations
253 // of SCElementOp2 must handle since it is pure virtual.
254 
255 void
process_spec_rect(SCMatrixRectBlock * a,SCMatrixRectBlock * b)256 SCElementOp2::process_spec_rect(SCMatrixRectBlock* a,SCMatrixRectBlock* b)
257 {
258   SCMatrixBlockIter*i = new SCMatrixRectBlockIter(a);
259   SCMatrixBlockIter*j = new SCMatrixRectBlockIter(b);
260   process(*i,*j);
261   // this causes a SCMatrixRectBlock::operator int() to be
262   // called with this = 0x0 using gcc 2.5.6
263   // process(*i,b);
264   delete i;
265   delete j;
266 }
267 void
process_spec_ltri(SCMatrixLTriBlock * a,SCMatrixLTriBlock * b)268 SCElementOp2::process_spec_ltri(SCMatrixLTriBlock* a,SCMatrixLTriBlock* b)
269 {
270   SCMatrixBlockIter*i = new SCMatrixLTriBlockIter(a);
271   SCMatrixBlockIter*j = new SCMatrixLTriBlockIter(b);
272   process(*i,*j);
273   delete i;
274   delete j;
275 }
276 void
process_spec_diag(SCMatrixDiagBlock * a,SCMatrixDiagBlock * b)277 SCElementOp2::process_spec_diag(SCMatrixDiagBlock* a,SCMatrixDiagBlock* b)
278 {
279   SCMatrixBlockIter*i = new SCMatrixDiagBlockIter(a);
280   SCMatrixBlockIter*j = new SCMatrixDiagBlockIter(b);
281   process(*i,*j);
282   delete i;
283   delete j;
284 }
285 void
process_spec_vsimp(SCVectorSimpleBlock * a,SCVectorSimpleBlock * b)286 SCElementOp2::process_spec_vsimp(SCVectorSimpleBlock* a,SCVectorSimpleBlock* b)
287 {
288   SCMatrixBlockIter*i = new SCVectorSimpleBlockIter(a);
289   SCMatrixBlockIter*j = new SCVectorSimpleBlockIter(b);
290   process(*i,*j);
291   delete i;
292   delete j;
293 }
294 
295 /////////////////////////////////////////////////////////////////////////////
296 // SCElementOp3 member functions
297 
298 static ClassDesc SCElementOp3_cd(
299   typeid(SCElementOp3),"SCElementOp3",1,"public SavableState",
300   0, 0, 0);
301 
SCElementOp3()302 SCElementOp3::SCElementOp3()
303 {
304 }
305 
~SCElementOp3()306 SCElementOp3::~SCElementOp3()
307 {
308 }
309 
310 int
has_collect()311 SCElementOp3::has_collect()
312 {
313   return 0;
314 }
315 
316 void
defer_collect(int)317 SCElementOp3::defer_collect(int)
318 {
319 }
320 
321 int
has_side_effects()322 SCElementOp3::has_side_effects()
323 {
324   return 0;
325 }
326 
327 int
has_side_effects_in_arg1()328 SCElementOp3::has_side_effects_in_arg1()
329 {
330   return 0;
331 }
332 
333 int
has_side_effects_in_arg2()334 SCElementOp3::has_side_effects_in_arg2()
335 {
336   return 0;
337 }
338 
339 void
collect(const Ref<MessageGrp> &)340 SCElementOp3::collect(const Ref<MessageGrp>&)
341 {
342 }
343 
344 void
process_base(SCMatrixBlock * a,SCMatrixBlock * b,SCMatrixBlock * c)345 SCElementOp3::process_base(SCMatrixBlock* a,
346                            SCMatrixBlock* b,
347                            SCMatrixBlock* c)
348 {
349   a->process(this, b, c);
350 }
351 
352 // If specializations of SCElementOp3 do not handle a particle
353 // block type, then these functions will be called and will
354 // set up an appropiate block iterator which specializations
355 // of SCElementOp3 must handle since it is pure virtual.
356 
357 void
process_spec_rect(SCMatrixRectBlock * a,SCMatrixRectBlock * b,SCMatrixRectBlock * c)358 SCElementOp3::process_spec_rect(SCMatrixRectBlock* a,
359                                 SCMatrixRectBlock* b,
360                                 SCMatrixRectBlock* c)
361 {
362   SCMatrixBlockIter*i = new SCMatrixRectBlockIter(a);
363   SCMatrixBlockIter*j = new SCMatrixRectBlockIter(b);
364   SCMatrixBlockIter*k = new SCMatrixRectBlockIter(c);
365   process(*i,*j,*k);
366   delete i;
367   delete j;
368   delete k;
369 }
370 void
process_spec_ltri(SCMatrixLTriBlock * a,SCMatrixLTriBlock * b,SCMatrixLTriBlock * c)371 SCElementOp3::process_spec_ltri(SCMatrixLTriBlock* a,
372                                 SCMatrixLTriBlock* b,
373                                 SCMatrixLTriBlock* c)
374 {
375   SCMatrixBlockIter*i = new SCMatrixLTriBlockIter(a);
376   SCMatrixBlockIter*j = new SCMatrixLTriBlockIter(b);
377   SCMatrixBlockIter*k = new SCMatrixLTriBlockIter(c);
378   process(*i,*j,*k);
379   delete i;
380   delete j;
381   delete k;
382 }
383 void
process_spec_diag(SCMatrixDiagBlock * a,SCMatrixDiagBlock * b,SCMatrixDiagBlock * c)384 SCElementOp3::process_spec_diag(SCMatrixDiagBlock* a,
385                                 SCMatrixDiagBlock* b,
386                                 SCMatrixDiagBlock* c)
387 {
388   SCMatrixBlockIter*i = new SCMatrixDiagBlockIter(a);
389   SCMatrixBlockIter*j = new SCMatrixDiagBlockIter(b);
390   SCMatrixBlockIter*k = new SCMatrixDiagBlockIter(c);
391   process(*i,*j,*k);
392   delete i;
393   delete j;
394   delete k;
395 }
396 void
process_spec_vsimp(SCVectorSimpleBlock * a,SCVectorSimpleBlock * b,SCVectorSimpleBlock * c)397 SCElementOp3::process_spec_vsimp(SCVectorSimpleBlock* a,
398                                  SCVectorSimpleBlock* b,
399                                  SCVectorSimpleBlock* c)
400 {
401   SCMatrixBlockIter*i = new SCVectorSimpleBlockIter(a);
402   SCMatrixBlockIter*j = new SCVectorSimpleBlockIter(b);
403   SCMatrixBlockIter*k = new SCVectorSimpleBlockIter(c);
404   process(*i,*j,*k);
405   delete i;
406   delete j;
407   delete k;
408 }
409 
410 /////////////////////////////////////////////////////////////////////////
411 // SCElementScale members
412 
413 static ClassDesc SCElementScale_cd(
414   typeid(SCElementScale),"SCElementScale",1,"public SCElementOp",
415   0, 0, create<SCElementScale>);
SCElementScale(double a)416 SCElementScale::SCElementScale(double a):scale(a) {}
SCElementScale(StateIn & s)417 SCElementScale::SCElementScale(StateIn&s):
418   SCElementOp(s)
419 {
420   s.get(scale);
421 }
422 void
save_data_state(StateOut & s)423 SCElementScale::save_data_state(StateOut&s)
424 {
425   s.put(scale);
426 }
~SCElementScale()427 SCElementScale::~SCElementScale() {}
428 void
process(SCMatrixBlockIter & i)429 SCElementScale::process(SCMatrixBlockIter&i)
430 {
431   for (i.reset(); i; ++i) {
432       i.set(scale*i.get());
433     }
434 }
435 
436 int
has_side_effects()437 SCElementScale::has_side_effects()
438 {
439   return 1;
440 }
441 
442 /////////////////////////////////////////////////////////////////////////
443 // SCElementScalarProduct members
444 
445 static ClassDesc SCElementScalarProduct_cd(
446   typeid(SCElementScalarProduct),"SCElementScalarProduct",1,"public SCElementOp2",
447   0, 0, create<SCElementScalarProduct>);
448 
SCElementScalarProduct()449 SCElementScalarProduct::SCElementScalarProduct():
450   deferred_(0), product(0.0)
451 {
452 }
453 
SCElementScalarProduct(StateIn & s)454 SCElementScalarProduct::SCElementScalarProduct(StateIn&s):
455   SCElementOp2(s)
456 {
457   s.get(product);
458   s.get(deferred_);
459 }
460 
461 void
save_data_state(StateOut & s)462 SCElementScalarProduct::save_data_state(StateOut&s)
463 {
464   s.put(product);
465   s.put(deferred_);
466 }
467 
~SCElementScalarProduct()468 SCElementScalarProduct::~SCElementScalarProduct()
469 {
470 }
471 
472 void
process(SCMatrixBlockIter & i,SCMatrixBlockIter & j)473 SCElementScalarProduct::process(SCMatrixBlockIter&i,
474                                 SCMatrixBlockIter&j)
475 {
476   for (i.reset(),j.reset(); i; ++i,++j) {
477       product += i.get()*j.get();
478     }
479 }
480 
481 int
has_collect()482 SCElementScalarProduct::has_collect()
483 {
484   return 1;
485 }
486 
487 void
defer_collect(int h)488 SCElementScalarProduct::defer_collect(int h)
489 {
490   deferred_=h;
491 }
492 
493 void
collect(const Ref<MessageGrp> & grp)494 SCElementScalarProduct::collect(const Ref<MessageGrp>&grp)
495 {
496   if (!deferred_)
497     grp->sum(product);
498 }
499 
500 double
result()501 SCElementScalarProduct::result()
502 {
503   return product;
504 }
505 
506 /////////////////////////////////////////////////////////////////////////
507 // SCDestructiveElementProduct members
508 
509 static ClassDesc SCDestructiveElementProduct_cd(
510   typeid(SCDestructiveElementProduct),"SCDestructiveElementProduct",1,"public SCElementOp2",
511   0, 0, create<SCDestructiveElementProduct>);
SCDestructiveElementProduct()512 SCDestructiveElementProduct::SCDestructiveElementProduct() {}
SCDestructiveElementProduct(StateIn & s)513 SCDestructiveElementProduct::SCDestructiveElementProduct(StateIn&s):
514   SCElementOp2(s)
515 {
516 }
517 void
save_data_state(StateOut & s)518 SCDestructiveElementProduct::save_data_state(StateOut&s)
519 {
520 }
~SCDestructiveElementProduct()521 SCDestructiveElementProduct::~SCDestructiveElementProduct() {}
522 void
process(SCMatrixBlockIter & i,SCMatrixBlockIter & j)523 SCDestructiveElementProduct::process(SCMatrixBlockIter&i,
524                                      SCMatrixBlockIter&j)
525 {
526   for (i.reset(),j.reset(); i; ++i,++j) {
527       i.set(i.get()*j.get());
528     }
529 }
530 
531 int
has_side_effects()532 SCDestructiveElementProduct::has_side_effects()
533 {
534   return 1;
535 }
536 
537 /////////////////////////////////////////////////////////////////////////
538 // SCElementInvert members
539 
540 static ClassDesc SCElementInvert_cd(
541   typeid(SCElementInvert),"SCElementInvert",1,"public SCElementOp",
542   0, 0, create<SCElementInvert>);
SCElementInvert(double threshold)543 SCElementInvert::SCElementInvert(double threshold):
544   threshold_(threshold),
545   nbelowthreshold_(0),
546   deferred_(0)
547 {}
SCElementInvert(StateIn & s)548 SCElementInvert::SCElementInvert(StateIn&s):
549   SCElementOp(s)
550 {
551   s.get(threshold_);
552   s.get(nbelowthreshold_);
553   s.get(deferred_);
554 }
555 void
save_data_state(StateOut & s)556 SCElementInvert::save_data_state(StateOut&s)
557 {
558   s.put(threshold_);
559   s.put(nbelowthreshold_);
560   s.put(deferred_);
561 }
~SCElementInvert()562 SCElementInvert::~SCElementInvert() {}
563 void
process(SCMatrixBlockIter & i)564 SCElementInvert::process(SCMatrixBlockIter&i)
565 {
566   for (i.reset(); i; ++i) {
567       double val = i.get();
568       if (fabs(val) > threshold_) val = 1.0/val;
569       else { val = 0.0; nbelowthreshold_++; }
570       i.set(val);
571     }
572 }
573 
574 int
has_side_effects()575 SCElementInvert::has_side_effects()
576 {
577   return 1;
578 }
579 int
has_collect()580 SCElementInvert::has_collect()
581 {
582   return 1;
583 }
584 void
defer_collect(int h)585 SCElementInvert::defer_collect(int h)
586 {
587   deferred_=h;
588 }
589 void
collect(const Ref<MessageGrp> & msg)590 SCElementInvert::collect(const Ref<MessageGrp>&msg)
591 {
592   if (!deferred_)
593     msg->sum(nbelowthreshold_);
594 }
595 void
collect(const Ref<SCElementOp> & op)596 SCElementInvert::collect(const Ref<SCElementOp>&op)
597 {
598   throw std::runtime_error(
599       "SCElementInvert::collect(const Ref<SCElementOp> &): not implemented");
600 }
601 
602 /////////////////////////////////////////////////////////////////////////
603 // SCElementSquareRoot members
604 
605 static ClassDesc SCElementSquareRoot_cd(
606   typeid(SCElementSquareRoot),"SCElementSquareRoot",1,"public SCElementOp",
607   0, 0, create<SCElementSquareRoot>);
SCElementSquareRoot()608 SCElementSquareRoot::SCElementSquareRoot() {}
SCElementSquareRoot(double a)609 SCElementSquareRoot::SCElementSquareRoot(double a) {}
SCElementSquareRoot(StateIn & s)610 SCElementSquareRoot::SCElementSquareRoot(StateIn&s):
611   SCElementOp(s)
612 {
613 }
614 void
save_data_state(StateOut & s)615 SCElementSquareRoot::save_data_state(StateOut&s)
616 {
617 }
~SCElementSquareRoot()618 SCElementSquareRoot::~SCElementSquareRoot() {}
619 void
process(SCMatrixBlockIter & i)620 SCElementSquareRoot::process(SCMatrixBlockIter&i)
621 {
622   for (i.reset(); i; ++i) {
623       double val = i.get();
624       if (val > 0.0) i.set(sqrt(i.get()));
625       else i.set(0.0);
626     }
627 }
628 
629 int
has_side_effects()630 SCElementSquareRoot::has_side_effects()
631 {
632   return 1;
633 }
634 
635 /////////////////////////////////////////////////////////////////////////
636 // SCElementMaxAbs members
637 
638 static ClassDesc SCElementMaxAbs_cd(
639   typeid(SCElementMaxAbs),"SCElementMaxAbs",1,"public SCElementOp",
640   0, 0, create<SCElementMaxAbs>);
641 
SCElementMaxAbs()642 SCElementMaxAbs::SCElementMaxAbs():deferred_(0), r(0.0) {}
SCElementMaxAbs(StateIn & s)643 SCElementMaxAbs::SCElementMaxAbs(StateIn&s):
644   SCElementOp(s)
645 {
646   s.get(r);
647   s.get(deferred_);
648 }
649 void
save_data_state(StateOut & s)650 SCElementMaxAbs::save_data_state(StateOut&s)
651 {
652   s.put(r);
653   s.put(deferred_);
654 }
~SCElementMaxAbs()655 SCElementMaxAbs::~SCElementMaxAbs() {}
656 void
process(SCMatrixBlockIter & i)657 SCElementMaxAbs::process(SCMatrixBlockIter&i)
658 {
659   for (i.reset(); i; ++i) {
660       if (fabs(i.get()) > r) r = fabs(i.get());
661     }
662 }
663 double
result()664 SCElementMaxAbs::result()
665 {
666   return r;
667 }
668 int
has_collect()669 SCElementMaxAbs::has_collect()
670 {
671   return 1;
672 }
673 void
defer_collect(int h)674 SCElementMaxAbs::defer_collect(int h)
675 {
676   deferred_=h;
677 }
678 void
collect(const Ref<MessageGrp> & msg)679 SCElementMaxAbs::collect(const Ref<MessageGrp>&msg)
680 {
681   if (!deferred_)
682     msg->max(r);
683 }
684 void
collect(const Ref<SCElementOp> & op)685 SCElementMaxAbs::collect(const Ref<SCElementOp>&op)
686 {
687   throw std::runtime_error(
688       "SCElementMaxAbs::collect(const Ref<SCElementOp> &): not implemented");
689 }
690 
691 /////////////////////////////////////////////////////////////////////////
692 // SCElementKNorm members
693 
694 static ClassDesc SCElementKNorm_cd(
695   typeid(SCElementKNorm),"SCElementKNorm",1,"public SCElementOp",
696   0, 0, create<SCElementKNorm>);
697 
SCElementKNorm(double k)698 SCElementKNorm::SCElementKNorm(double k):deferred_(0), r_(0.0), k_(k) {}
SCElementKNorm(StateIn & s)699 SCElementKNorm::SCElementKNorm(StateIn&s):
700   SCElementOp(s)
701 {
702   s.get(k_);
703   s.get(r_);
704   s.get(deferred_);
705 }
706 void
save_data_state(StateOut & s)707 SCElementKNorm::save_data_state(StateOut&s)
708 {
709   s.put(r_);
710   s.put(deferred_);
711 }
~SCElementKNorm()712 SCElementKNorm::~SCElementKNorm() {}
713 void
process(SCMatrixBlockIter & i)714 SCElementKNorm::process(SCMatrixBlockIter&i)
715 {
716   for (i.reset(); i; ++i) {
717     r_ += std::pow(std::abs(i.get()),k_);
718   }
719 }
720 double
result()721 SCElementKNorm::result()
722 {
723   return r_;
724 }
725 int
has_collect()726 SCElementKNorm::has_collect()
727 {
728   return 1;
729 }
730 void
defer_collect(int h)731 SCElementKNorm::defer_collect(int h)
732 {
733   deferred_=h;
734 }
735 void
collect(const Ref<MessageGrp> & msg)736 SCElementKNorm::collect(const Ref<MessageGrp>&msg)
737 {
738   if (!deferred_)
739     msg->sum(r_);
740   r_ = std::pow(r_,1.0/k_);
741 }
742 void
collect(const Ref<SCElementOp> & op)743 SCElementKNorm::collect(const Ref<SCElementOp>&op)
744 {
745   throw std::runtime_error(
746       "SCElementKNorm::collect(const Ref<SCElementOp> &): not implemented");
747 }
748 
749 /////////////////////////////////////////////////////////////////////////
750 // SCElementMin members
751 
752 static ClassDesc SCElementMinAbs_cd(
753   typeid(SCElementMinAbs),"SCElementMinAbs",1,"public SCElementOp",
754   0, 0, create<SCElementMinAbs>);
SCElementMinAbs(double rinit)755 SCElementMinAbs::SCElementMinAbs(double rinit):deferred_(0), r(rinit) {}
SCElementMinAbs(StateIn & s)756 SCElementMinAbs::SCElementMinAbs(StateIn&s):
757   SCElementOp(s)
758 {
759   s.get(r);
760   s.get(deferred_);
761 }
762 void
save_data_state(StateOut & s)763 SCElementMinAbs::save_data_state(StateOut&s)
764 {
765   s.put(r);
766   s.put(deferred_);
767 }
~SCElementMinAbs()768 SCElementMinAbs::~SCElementMinAbs() {}
769 void
process(SCMatrixBlockIter & i)770 SCElementMinAbs::process(SCMatrixBlockIter&i)
771 {
772   for (i.reset(); i; ++i) {
773       if (fabs(i.get()) < r) r = fabs(i.get());
774     }
775 }
776 double
result()777 SCElementMinAbs::result()
778 {
779   return r;
780 }
781 int
has_collect()782 SCElementMinAbs::has_collect()
783 {
784   return 1;
785 }
786 void
defer_collect(int h)787 SCElementMinAbs::defer_collect(int h)
788 {
789   deferred_=h;
790 }
791 void
collect(const Ref<MessageGrp> & msg)792 SCElementMinAbs::collect(const Ref<MessageGrp>&msg)
793 {
794   if (!deferred_)
795     msg->min(r);
796 }
797 void
collect(const Ref<SCElementOp> & op)798 SCElementMinAbs::collect(const Ref<SCElementOp>&op)
799 {
800   throw std::runtime_error(
801       "SCElementMinAbs::collect(const Ref<SCElementOp> &): not implemented");
802 }
803 
804 /////////////////////////////////////////////////////////////////////////
805 // SCElementSumAbs members
806 
807 static ClassDesc SCElementSumAbs_cd(
808   typeid(SCElementSumAbs),"SCElementSumAbs",1,"public SCElementOp",
809   0, 0, create<SCElementSumAbs>);
SCElementSumAbs()810 SCElementSumAbs::SCElementSumAbs():deferred_(0), r(0.0) {}
SCElementSumAbs(StateIn & s)811 SCElementSumAbs::SCElementSumAbs(StateIn&s):
812   SCElementOp(s)
813 {
814   s.get(r);
815   s.get(deferred_);
816 }
817 void
save_data_state(StateOut & s)818 SCElementSumAbs::save_data_state(StateOut&s)
819 {
820   s.put(r);
821   s.put(deferred_);
822 }
~SCElementSumAbs()823 SCElementSumAbs::~SCElementSumAbs() {}
824 void
process(SCMatrixBlockIter & i)825 SCElementSumAbs::process(SCMatrixBlockIter&i)
826 {
827   for (i.reset(); i; ++i) {
828       r += fabs(i.get());
829     }
830 }
831 double
result()832 SCElementSumAbs::result()
833 {
834   return r;
835 }
836 int
has_collect()837 SCElementSumAbs::has_collect()
838 {
839   return 1;
840 }
841 void
defer_collect(int h)842 SCElementSumAbs::defer_collect(int h)
843 {
844   deferred_=h;
845 }
846 void
collect(const Ref<MessageGrp> & msg)847 SCElementSumAbs::collect(const Ref<MessageGrp>&msg)
848 {
849   if (!deferred_)
850     msg->sum(r);
851 }
852 void
collect(const Ref<SCElementOp> & op)853 SCElementSumAbs::collect(const Ref<SCElementOp>&op)
854 {
855   throw std::runtime_error(
856       "SCElementSumAbs::collect(const Ref<SCElementOp> &): not implemented");
857 }
858 
859 /////////////////////////////////////////////////////////////////////////
860 // SCElementAssign members
861 
862 static ClassDesc SCElementAssign_cd(
863   typeid(SCElementAssign),"SCElementAssign",1,"public SCElementOp",
864   0, 0, create<SCElementAssign>);
SCElementAssign(double a)865 SCElementAssign::SCElementAssign(double a):assign(a) {}
SCElementAssign(StateIn & s)866 SCElementAssign::SCElementAssign(StateIn&s):
867   SCElementOp(s)
868 {
869   s.get(assign);
870 }
871 void
save_data_state(StateOut & s)872 SCElementAssign::save_data_state(StateOut&s)
873 {
874   s.put(assign);
875 }
~SCElementAssign()876 SCElementAssign::~SCElementAssign() {}
877 void
process(SCMatrixBlockIter & i)878 SCElementAssign::process(SCMatrixBlockIter&i)
879 {
880   for (i.reset(); i; ++i) {
881       i.set(assign);
882     }
883 }
884 
885 int
has_side_effects()886 SCElementAssign::has_side_effects()
887 {
888   return 1;
889 }
890 
891 /////////////////////////////////////////////////////////////////////////
892 // SCElementRandomize members
893 
894 static ClassDesc SCElementRandomize_cd(
895   typeid(SCElementRandomize),"SCElementRandomize",1,"public SCElementOp",
896   0, 0, create<SCElementRandomize>);
SCElementRandomize()897 SCElementRandomize::SCElementRandomize() {}
SCElementRandomize(StateIn & s)898 SCElementRandomize::SCElementRandomize(StateIn&s):
899   SCElementOp(s)
900 {
901 }
902 void
save_data_state(StateOut & s)903 SCElementRandomize::save_data_state(StateOut&s)
904 {
905 }
~SCElementRandomize()906 SCElementRandomize::~SCElementRandomize() {}
907 void
process(SCMatrixBlockIter & i)908 SCElementRandomize::process(SCMatrixBlockIter&i)
909 {
910   for (i.reset(); i; ++i) {
911 #ifdef HAVE_DRAND48
912       i.set(drand48()*(drand48()<0.5?1.0:-1.0));
913 #else
914       int r=rand();
915       double dr = (double) r / 32767.0;
916       i.set(dr*(dr<0.5?1.0:-1.0));
917 #endif
918     }
919 }
920 
921 int
has_side_effects()922 SCElementRandomize::has_side_effects()
923 {
924   return 1;
925 }
926 
927 /////////////////////////////////////////////////////////////////////////
928 // SCElementShiftDiagonal members
929 
930 static ClassDesc SCElementShiftDiagonal_cd(
931   typeid(SCElementShiftDiagonal),"SCElementShiftDiagonal",1,"public SCElementOp",
932   0, 0, create<SCElementShiftDiagonal>);
SCElementShiftDiagonal(double a)933 SCElementShiftDiagonal::SCElementShiftDiagonal(double a):shift_diagonal(a) {}
SCElementShiftDiagonal(StateIn & s)934 SCElementShiftDiagonal::SCElementShiftDiagonal(StateIn&s):
935   SCElementOp(s)
936 {
937   s.get(shift_diagonal);
938 }
939 void
save_data_state(StateOut & s)940 SCElementShiftDiagonal::save_data_state(StateOut&s)
941 {
942   s.put(shift_diagonal);
943 }
~SCElementShiftDiagonal()944 SCElementShiftDiagonal::~SCElementShiftDiagonal() {}
945 void
process(SCMatrixBlockIter & i)946 SCElementShiftDiagonal::process(SCMatrixBlockIter&i)
947 {
948   for (i.reset(); i; ++i) {
949       if (i.i() == i.j()) i.set(shift_diagonal+i.get());
950     }
951 }
952 
953 int
has_side_effects()954 SCElementShiftDiagonal::has_side_effects()
955 {
956   return 1;
957 }
958 
959 /////////////////////////////////////////////////////////////////////////
960 // SCElementScaleDiagonal members
961 
962 static ClassDesc SCElementScaleDiagonal_cd(
963   typeid(SCElementScaleDiagonal),"SCElementScaleDiagonal",1,"public SCElementOp",
964   0, 0, create<SCElementScaleDiagonal>);
SCElementScaleDiagonal(double a)965 SCElementScaleDiagonal::SCElementScaleDiagonal(double a):scale_diagonal(a) {}
SCElementScaleDiagonal(StateIn & s)966 SCElementScaleDiagonal::SCElementScaleDiagonal(StateIn&s):
967   SCElementOp(s)
968 {
969   s.get(scale_diagonal);
970 }
971 void
save_data_state(StateOut & s)972 SCElementScaleDiagonal::save_data_state(StateOut&s)
973 {
974   s.put(scale_diagonal);
975 }
~SCElementScaleDiagonal()976 SCElementScaleDiagonal::~SCElementScaleDiagonal() {}
977 void
process(SCMatrixBlockIter & i)978 SCElementScaleDiagonal::process(SCMatrixBlockIter&i)
979 {
980   for (i.reset(); i; ++i) {
981       if (i.i() == i.j()) i.set(scale_diagonal*i.get());
982     }
983 }
984 
985 int
has_side_effects()986 SCElementScaleDiagonal::has_side_effects()
987 {
988   return 1;
989 }
990 
991 /////////////////////////////////////////////////////////////////////////
992 // SCElementDot members
993 
994 static ClassDesc SCElementDot_cd(
995   typeid(SCElementDot),"SCElementDot",1,"public SCElementOp",
996   0, 0, create<SCElementDot>);
997 
SCElementDot(double ** a,double ** b,int n)998 SCElementDot::SCElementDot(double**a, double**b, int n):
999   avects(a),
1000   bvects(b),
1001   length(n)
1002 {
1003 }
1004 
SCElementDot(StateIn & s)1005 SCElementDot::SCElementDot(StateIn&s)
1006 {
1007   ExEnv::errn() << indent << "SCElementDot does not permit StateIn CTOR\n";
1008   abort();
1009 }
1010 
1011 void
save_data_state(StateOut & s)1012 SCElementDot::save_data_state(StateOut&s)
1013 {
1014   ExEnv::errn() << indent << "SCElementDot does not permit save_data_state\n";
1015   abort();
1016 }
1017 
1018 int
has_side_effects()1019 SCElementDot::has_side_effects()
1020 {
1021   return 1;
1022 }
1023 
1024 void
process(SCMatrixBlockIter & i)1025 SCElementDot::process(SCMatrixBlockIter&i)
1026 {
1027   for (i.reset(); i; ++i) {
1028       double tmp = i.get();
1029       double* a = avects[i.i()];
1030       double* b = bvects[i.j()];
1031       for (int j = length; j; j--, a++, b++) {
1032           tmp += *a * *b;
1033         }
1034       i.accum(tmp);
1035     }
1036 }
1037 
1038 /////////////////////////////////////////////////////////////////////////
1039 // SCElementAccumulateSCMatrix members
1040 
1041 static ClassDesc SCElementAccumulateSCMatrix_cd(
1042   typeid(SCElementAccumulateSCMatrix),"SCElementAccumulateSCMatrix",1,"public SCElementOp",
1043   0, 0, 0);
1044 
SCElementAccumulateSCMatrix(SCMatrix * a)1045 SCElementAccumulateSCMatrix::SCElementAccumulateSCMatrix(SCMatrix*a):
1046   m(a)
1047 {
1048 }
1049 
1050 int
has_side_effects()1051 SCElementAccumulateSCMatrix::has_side_effects()
1052 {
1053   return 1;
1054 }
1055 
1056 void
process(SCMatrixBlockIter & i)1057 SCElementAccumulateSCMatrix::process(SCMatrixBlockIter&i)
1058 {
1059   for (i.reset(); i; ++i) {
1060       i.accum(m->get_element(i.i(), i.j()));
1061     }
1062 }
1063 
1064 /////////////////////////////////////////////////////////////////////////
1065 // SCElementAccumulateSymmSCMatrix members
1066 
1067 static ClassDesc SCElementAccumulateSymmSCMatrix_cd(
1068   typeid(SCElementAccumulateSymmSCMatrix),"SCElementAccumulateSymmSCMatrix",1,"public SCElementOp",
1069   0, 0, 0);
1070 
SCElementAccumulateSymmSCMatrix(SymmSCMatrix * a)1071 SCElementAccumulateSymmSCMatrix::SCElementAccumulateSymmSCMatrix(
1072     SymmSCMatrix*a):
1073   m(a)
1074 {
1075 }
1076 
1077 int
has_side_effects()1078 SCElementAccumulateSymmSCMatrix::has_side_effects()
1079 {
1080   return 1;
1081 }
1082 
1083 void
process(SCMatrixBlockIter & i)1084 SCElementAccumulateSymmSCMatrix::process(SCMatrixBlockIter&i)
1085 {
1086   for (i.reset(); i; ++i) {
1087       i.accum(m->get_element(i.i(), i.j()));
1088     }
1089 }
1090 
1091 /////////////////////////////////////////////////////////////////////////
1092 // SCElementAccumulateDiagSCMatrix members
1093 
1094 static ClassDesc SCElementAccumulateDiagSCMatrix_cd(
1095   typeid(SCElementAccumulateDiagSCMatrix),"SCElementAccumulateDiagSCMatrix",1,"public SCElementOp",
1096   0, 0, 0);
1097 
SCElementAccumulateDiagSCMatrix(DiagSCMatrix * a)1098 SCElementAccumulateDiagSCMatrix::SCElementAccumulateDiagSCMatrix(
1099     DiagSCMatrix*a):
1100   m(a)
1101 {
1102 }
1103 
1104 int
has_side_effects()1105 SCElementAccumulateDiagSCMatrix::has_side_effects()
1106 {
1107   return 1;
1108 }
1109 
1110 void
process(SCMatrixBlockIter & i)1111 SCElementAccumulateDiagSCMatrix::process(SCMatrixBlockIter&i)
1112 {
1113   for (i.reset(); i; ++i) {
1114       i.accum(m->get_element(i.i()));
1115     }
1116 }
1117 
1118 /////////////////////////////////////////////////////////////////////////
1119 // SCElementAccumulateSCVector members
1120 
1121 static ClassDesc SCElementAccumulateSCVector_cd(
1122   typeid(SCElementAccumulateSCVector),"SCElementAccumulateSCVector",1,"public SCElementOp",
1123   0, 0, 0);
1124 
SCElementAccumulateSCVector(SCVector * a)1125 SCElementAccumulateSCVector::SCElementAccumulateSCVector(SCVector*a):
1126   m(a)
1127 {
1128 }
1129 
1130 int
has_side_effects()1131 SCElementAccumulateSCVector::has_side_effects()
1132 {
1133   return 1;
1134 }
1135 
1136 void
process(SCMatrixBlockIter & i)1137 SCElementAccumulateSCVector::process(SCMatrixBlockIter&i)
1138 {
1139   for (i.reset(); i; ++i) {
1140       i.accum(m->get_element(i.i()));
1141     }
1142 }
1143 
1144 /////////////////////////////////////////////////////////////////////////////
1145 
1146 // Local Variables:
1147 // mode: c++
1148 // c-file-style: "CLJ"
1149 // End:
1150