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