Heidelberg Educational Numerics Library Version 0.27 (from 15 March 2021)
opcounter.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil -*-
2#ifndef __OPCOUNTER__
3#define __OPCOUNTER__
4
5#include <type_traits>
6#include <iostream>
7#include <cmath>
8#include <cstdlib>
9
14namespace hdnum {
15 namespace oc {
16 template<typename F>
17 class OpCounter;
18 }
19}
20
21namespace hdnum {
22 namespace oc {
28 template<typename F>
30 {
31
32 public:
33
34 using size_type = std::size_t;
35
36 using value_type = F;
37
38 OpCounter()
39 : _v()
40 {}
41
42 template<typename T>
43 OpCounter(const T& t, typename std::enable_if<std::is_same<T,int>::value and !std::is_same<F,int>::value>::type* = nullptr)
44 : _v(t)
45 {}
46
47 OpCounter(const F& f)
48 : _v(f)
49 {}
50
51 OpCounter(F&& f)
52 : _v(f)
53 {}
54
55 explicit OpCounter(const char* s)
56 : _v(strtod(s,nullptr))
57 {}
58
59 OpCounter& operator=(const char* s)
60 {
61 _v = strtod(s,nullptr);
62 return *this;
63 }
64
65 explicit operator F() const
66 {
67 return _v;
68 }
69
70 OpCounter& operator=(const F& f)
71 {
72 _v = f;
73 return *this;
74 }
75
76 OpCounter& operator=(F&& f)
77 {
78 _v = f;
79 return *this;
80 }
81
82 friend std::ostream& operator<<(std::ostream& os, const OpCounter& f)
83 {
84 os << "OC(" << f._v << ")";
85 return os;
86 }
87
88 friend std::istringstream& operator>>(std::istringstream& iss, OpCounter& f)
89 {
90 iss >> f._v;
91 return iss;
92 }
93
94 F* data()
95 {
96 return &_v;
97 }
98
99 const F* data() const
100 {
101 return &_v;
102 }
103
104 F _v;
105
107 struct Counters {
108
109 size_type addition_count;
110 size_type multiplication_count;
111 size_type division_count;
112 size_type exp_count;
113 size_type pow_count;
114 size_type sin_count;
115 size_type sqrt_count;
116 size_type comparison_count;
117
118 Counters()
119 : addition_count(0)
120 , multiplication_count(0)
121 , division_count(0)
122 , exp_count(0)
123 , pow_count(0)
124 , sin_count(0)
125 , sqrt_count(0)
126 , comparison_count(0)
127 {}
128
129 void reset()
130 {
131 addition_count = 0;
132 multiplication_count = 0;
133 division_count = 0;
134 exp_count = 0;
135 pow_count = 0;
136 sin_count = 0;
137 sqrt_count = 0;
138 comparison_count = 0;
139 }
140
142 template<typename Stream>
143 void reportOperations(Stream& os, bool doReset = false)
144 {
145 os << "additions: " << addition_count << std::endl
146 << "multiplications: " << multiplication_count << std::endl
147 << "divisions: " << division_count << std::endl
148 << "exp: " << exp_count << std::endl
149 << "pow: " << pow_count << std::endl
150 << "sin: " << sin_count << std::endl
151 << "sqrt: " << sqrt_count << std::endl
152 << "comparisons: " << comparison_count << std::endl
153 << std::endl
154 << "total: " << addition_count + multiplication_count + division_count + exp_count + pow_count + sin_count + sqrt_count + comparison_count << std::endl;
155
156 if (doReset)
157 reset();
158 }
159
161 size_type totalOperationCount(bool doReset=false)
162 {
163 if (doReset)
164 reset();
165
166 return addition_count + multiplication_count + division_count + exp_count + pow_count + sin_count + sqrt_count + comparison_count;
167 }
168
169 Counters& operator+=(const Counters& rhs)
170 {
171 addition_count += rhs.addition_count;
172 multiplication_count += rhs.multiplication_count;
173 division_count += rhs.division_count;
174 exp_count += rhs.exp_count;
175 pow_count += rhs.pow_count;
176 sin_count += rhs.sin_count;
177 sqrt_count += rhs.sqrt_count;
178 comparison_count += rhs.comparison_count;
179 return *this;
180 }
181
182 Counters operator-(const Counters& rhs)
183 {
184 Counters r;
185 r.addition_count = addition_count - rhs.addition_count;
186 r.multiplication_count = multiplication_count - rhs.multiplication_count;
187 r.division_count = division_count - rhs.division_count;
188 r.exp_count = exp_count - rhs.exp_count;
189 r.pow_count = pow_count - rhs.pow_count;
190 r.sin_count = sin_count - rhs.sin_count;
191 r.sqrt_count = sqrt_count - rhs.sqrt_count;
192 r.comparison_count = comparison_count - rhs.comparison_count;
193 return r;
194 }
195
196 };
197
198 static void additions(std::size_t n)
199 {
200 counters.addition_count += n;
201 }
202
203 static void multiplications(std::size_t n)
204 {
205 counters.multiplication_count += n;
206 }
207
208 static void divisions(std::size_t n)
209 {
210 counters.division_count += n;
211 }
212
213 static void reset()
214 {
215 counters.reset();
216 }
217
219 template<typename Stream>
220 static void reportOperations(Stream& os, bool doReset = false)
221 {
222 counters.reportOperations(os,doReset);
223 }
224
226 static size_type totalOperationCount(bool doReset=false)
227 {
228 return counters.totalOperationCount(doReset);
229 }
230
231 static Counters counters;
232
233 };
234
235 template<typename F>
236 typename OpCounter<F>::Counters OpCounter<F>::counters;
237
238 // ********************************************************************************
239 // negation
240 // ********************************************************************************
241
242 template<typename F>
243 OpCounter<F> operator-(const OpCounter<F>& a)
244 {
245 ++OpCounter<F>::counters.addition_count;
246 return {-a._v};
247 }
248
249
250 // ********************************************************************************
251 // addition
252 // ********************************************************************************
253
254 template<typename F>
255 OpCounter<F> operator+(const OpCounter<F>& a, const OpCounter<F>& b)
256 {
257 ++OpCounter<F>::counters.addition_count;
258 return {a._v + b._v};
259 }
260
261 template<typename F>
262 OpCounter<F> operator+(const OpCounter<F>& a, const F& b)
263 {
264 ++OpCounter<F>::counters.addition_count;
265 return {a._v + b};
266 }
267
268 template<typename F>
269 OpCounter<F> operator+(const F& a, const OpCounter<F>& b)
270 {
271 ++OpCounter<F>::counters.addition_count;
272 return {a + b._v};
273 }
274
275 template<typename F, typename T>
276 typename std::enable_if<
277 std::is_arithmetic<T>::value,
278 OpCounter<F>
279 >::type
280 operator+(const OpCounter<F>& a, const T& b)
281 {
282 ++OpCounter<F>::counters.addition_count;
283 return {a._v + b};
284 }
285
286 template<typename F, typename T>
287 typename std::enable_if<
288 std::is_arithmetic<T>::value,
289 OpCounter<F>
290 >::type
291 operator+(const T& a, const OpCounter<F>& b)
292 {
293 ++OpCounter<F>::counters.addition_count;
294 return {a + b._v};
295 }
296
297 template<typename F>
298 OpCounter<F>& operator+=(OpCounter<F>& a, const OpCounter<F>& b)
299 {
300 ++OpCounter<F>::counters.addition_count;
301 a._v += b._v;
302 return a;
303 }
304
305 template<typename F>
306 OpCounter<F>& operator+=(OpCounter<F>& a, const F& b)
307 {
308 ++OpCounter<F>::counters.addition_count;
309 a._v += b;
310 return a;
311 }
312
313 template<typename F, typename T>
314 typename std::enable_if<
315 std::is_arithmetic<T>::value,
316 OpCounter<F>&
317 >::type
318 operator+=(OpCounter<F>& a, const T& b)
319 {
320 ++OpCounter<F>::counters.addition_count;
321 a._v += b;
322 return a;
323 }
324
325 // ********************************************************************************
326 // subtraction
327 // ********************************************************************************
328
329 template<typename F>
330 OpCounter<F> operator-(const OpCounter<F>& a, const OpCounter<F>& b)
331 {
332 ++OpCounter<F>::counters.addition_count;
333 return {a._v - b._v};
334 }
335
336 template<typename F>
337 OpCounter<F> operator-(const OpCounter<F>& a, const F& b)
338 {
339 ++OpCounter<F>::counters.addition_count;
340 return {a._v - b};
341 }
342
343 template<typename F>
344 OpCounter<F> operator-(const F& a, const OpCounter<F>& b)
345 {
346 ++OpCounter<F>::counters.addition_count;
347 return {a - b._v};
348 }
349
350 template<typename F, typename T>
351 typename std::enable_if<
352 std::is_arithmetic<T>::value,
353 OpCounter<F>
354 >::type
355 operator-(const OpCounter<F>& a, const T& b)
356 {
357 ++OpCounter<F>::counters.addition_count;
358 return {a._v - b};
359 }
360
361 template<typename F, typename T>
362 typename std::enable_if<
363 std::is_arithmetic<T>::value,
364 OpCounter<F>
365 >::type
366 operator-(const T& a, const OpCounter<F>& b)
367 {
368 ++OpCounter<F>::counters.addition_count;
369 return {a - b._v};
370 }
371
372 template<typename F>
373 OpCounter<F>& operator-=(OpCounter<F>& a, const OpCounter<F>& b)
374 {
375 ++OpCounter<F>::counters.addition_count;
376 a._v -= b._v;
377 return a;
378 }
379
380 template<typename F>
381 OpCounter<F>& operator-=(OpCounter<F>& a, const F& b)
382 {
383 ++OpCounter<F>::counters.addition_count;
384 a._v -= b;
385 return a;
386 }
387
388 template<typename F, typename T>
389 typename std::enable_if<
390 std::is_arithmetic<T>::value,
391 OpCounter<F>&
392 >::type
393 operator-=(OpCounter<F>& a, const T& b)
394 {
395 ++OpCounter<F>::counters.addition_count;
396 a._v -= b;
397 return a;
398 }
399
400
401 // ********************************************************************************
402 // multiplication
403 // ********************************************************************************
404
405 template<typename F>
406 OpCounter<F> operator*(const OpCounter<F>& a, const OpCounter<F>& b)
407 {
408 ++OpCounter<F>::counters.multiplication_count;
409 return {a._v * b._v};
410 }
411
412 template<typename F>
413 OpCounter<F> operator*(const OpCounter<F>& a, const F& b)
414 {
415 ++OpCounter<F>::counters.multiplication_count;
416 return {a._v * b};
417 }
418
419 template<typename F>
420 OpCounter<F> operator*(const F& a, const OpCounter<F>& b)
421 {
422 ++OpCounter<F>::counters.multiplication_count;
423 return {a * b._v};
424 }
425
426 template<typename F, typename T>
427 typename std::enable_if<
428 std::is_arithmetic<T>::value,
429 OpCounter<F>
430 >::type
431 operator*(const OpCounter<F>& a, const T& b)
432 {
433 ++OpCounter<F>::counters.multiplication_count;
434 return {a._v * b};
435 }
436
437 template<typename F, typename T>
438 typename std::enable_if<
439 std::is_arithmetic<T>::value,
440 OpCounter<F>
441 >::type
442 operator*(const T& a, const OpCounter<F>& b)
443 {
444 ++OpCounter<F>::counters.multiplication_count;
445 return {a * b._v};
446 }
447
448 template<typename F>
449 OpCounter<F>& operator*=(OpCounter<F>& a, const OpCounter<F>& b)
450 {
451 ++OpCounter<F>::counters.multiplication_count;
452 a._v *= b._v;
453 return a;
454 }
455
456 template<typename F>
457 OpCounter<F>& operator*=(OpCounter<F>& a, const F& b)
458 {
459 ++OpCounter<F>::counters.multiplication_count;
460 a._v *= b;
461 return a;
462 }
463
464 template<typename F, typename T>
465 typename std::enable_if<
466 std::is_arithmetic<T>::value,
467 OpCounter<F>&
468 >::type
469 operator*=(OpCounter<F>& a, const T& b)
470 {
471 ++OpCounter<F>::counters.multiplication_count;
472 a._v *= b;
473 return a;
474 }
475
476
477 // ********************************************************************************
478 // division
479 // ********************************************************************************
480
481 template<typename F>
482 OpCounter<F> operator/(const OpCounter<F>& a, const OpCounter<F>& b)
483 {
484 ++OpCounter<F>::counters.division_count;
485 return {a._v / b._v};
486 }
487
488 template<typename F>
489 OpCounter<F> operator/(const OpCounter<F>& a, const F& b)
490 {
491 ++OpCounter<F>::counters.division_count;
492 return {a._v / b};
493 }
494
495 template<typename F>
496 OpCounter<F> operator/(const F& a, const OpCounter<F>& b)
497 {
498 ++OpCounter<F>::counters.division_count;
499 return {a / b._v};
500 }
501
502 template<typename F, typename T>
503 typename std::enable_if<
504 std::is_arithmetic<T>::value,
505 OpCounter<F>
506 >::type
507 operator/(const OpCounter<F>& a, const T& b)
508 {
509 ++OpCounter<F>::counters.division_count;
510 return {a._v / b};
511 }
512
513 template<typename F, typename T>
514 typename std::enable_if<
515 std::is_arithmetic<T>::value,
516 OpCounter<F>
517 >::type
518 operator/(const T& a, const OpCounter<F>& b)
519 {
520 ++OpCounter<F>::counters.division_count;
521 return {a / b._v};
522 }
523
524 template<typename F>
525 OpCounter<F>& operator/=(OpCounter<F>& a, const OpCounter<F>& b)
526 {
527 ++OpCounter<F>::counters.division_count;
528 a._v /= b._v;
529 return a;
530 }
531
532 template<typename F>
533 OpCounter<F>& operator/=(OpCounter<F>& a, const F& b)
534 {
535 ++OpCounter<F>::counters.division_count;
536 a._v /= b;
537 return a;
538 }
539
540 template<typename F, typename T>
541 typename std::enable_if<
542 std::is_arithmetic<T>::value,
543 OpCounter<F>&
544 >::type
545 operator/=(OpCounter<F>& a, const T& b)
546 {
547 ++OpCounter<F>::counters.division_count;
548 a._v /= b;
549 return a;
550 }
551
552
553
554 // ********************************************************************************
555 // comparisons
556 // ********************************************************************************
557
558
559 // ********************************************************************************
560 // less
561 // ********************************************************************************
562
563 template<typename F>
564 bool operator<(const OpCounter<F>& a, const OpCounter<F>& b)
565 {
566 ++OpCounter<F>::counters.comparison_count;
567 return {a._v < b._v};
568 }
569
570 template<typename F>
571 bool operator<(const OpCounter<F>& a, const F& b)
572 {
573 ++OpCounter<F>::counters.comparison_count;
574 return {a._v < b};
575 }
576
577 template<typename F>
578 bool operator<(const F& a, const OpCounter<F>& b)
579 {
580 ++OpCounter<F>::counters.comparison_count;
581 return {a < b._v};
582 }
583
584 template<typename F, typename T>
585 bool operator<(const OpCounter<F>& a, const T& b)
586 {
587 ++OpCounter<F>::counters.comparison_count;
588 return {a._v < b};
589 }
590
591 template<typename F, typename T>
592 bool operator<(const T& a, const OpCounter<F>& b)
593 {
594 ++OpCounter<F>::counters.comparison_count;
595 return {a < b._v};
596 }
597
598
599 // ********************************************************************************
600 // less_or_equals
601 // ********************************************************************************
602
603 template<typename F>
604 bool operator<=(const OpCounter<F>& a, const OpCounter<F>& b)
605 {
606 ++OpCounter<F>::counters.comparison_count;
607 return {a._v <= b._v};
608 }
609
610 template<typename F>
611 bool operator<=(const OpCounter<F>& a, const F& b)
612 {
613 ++OpCounter<F>::counters.comparison_count;
614 return {a._v <= b};
615 }
616
617 template<typename F>
618 bool operator<=(const F& a, const OpCounter<F>& b)
619 {
620 ++OpCounter<F>::counters.comparison_count;
621 return {a <= b._v};
622 }
623
624 template<typename F, typename T>
625 bool operator<=(const OpCounter<F>& a, const T& b)
626 {
627 ++OpCounter<F>::counters.comparison_count;
628 return {a._v <= b};
629 }
630
631 template<typename F, typename T>
632 bool operator<=(const T& a, const OpCounter<F>& b)
633 {
634 ++OpCounter<F>::counters.comparison_count;
635 return {a <= b._v};
636 }
637
638
639 // ********************************************************************************
640 // greater
641 // ********************************************************************************
642
643 template<typename F>
644 bool operator>(const OpCounter<F>& a, const OpCounter<F>& b)
645 {
646 ++OpCounter<F>::counters.comparison_count;
647 return {a._v > b._v};
648 }
649
650 template<typename F>
651 bool operator>(const OpCounter<F>& a, const F& b)
652 {
653 ++OpCounter<F>::counters.comparison_count;
654 return {a._v > b};
655 }
656
657 template<typename F>
658 bool operator>(const F& a, const OpCounter<F>& b)
659 {
660 ++OpCounter<F>::counters.comparison_count;
661 return {a > b._v};
662 }
663
664 template<typename F, typename T>
665 bool operator>(const OpCounter<F>& a, const T& b)
666 {
667 ++OpCounter<F>::counters.comparison_count;
668 return {a._v > b};
669 }
670
671 template<typename F, typename T>
672 bool operator>(const T& a, const OpCounter<F>& b)
673 {
674 ++OpCounter<F>::counters.comparison_count;
675 return {a > b._v};
676 }
677
678
679 // ********************************************************************************
680 // greater_or_equals
681 // ********************************************************************************
682
683 template<typename F>
684 bool operator>=(const OpCounter<F>& a, const OpCounter<F>& b)
685 {
686 ++OpCounter<F>::counters.comparison_count;
687 return {a._v >= b._v};
688 }
689
690 template<typename F>
691 bool operator>=(const OpCounter<F>& a, const F& b)
692 {
693 ++OpCounter<F>::counters.comparison_count;
694 return {a._v >= b};
695 }
696
697 template<typename F>
698 bool operator>=(const F& a, const OpCounter<F>& b)
699 {
700 ++OpCounter<F>::counters.comparison_count;
701 return {a >= b._v};
702 }
703
704 template<typename F, typename T>
705 bool operator>=(const OpCounter<F>& a, const T& b)
706 {
707 ++OpCounter<F>::counters.comparison_count;
708 return {a._v >= b};
709 }
710
711 template<typename F, typename T>
712 bool operator>=(const T& a, const OpCounter<F>& b)
713 {
714 ++OpCounter<F>::counters.comparison_count;
715 return {a >= b._v};
716 }
717
718
719 // ********************************************************************************
720 // inequals
721 // ********************************************************************************
722
723 template<typename F>
724 bool operator!=(const OpCounter<F>& a, const OpCounter<F>& b)
725 {
726 ++OpCounter<F>::counters.comparison_count;
727 return {a._v != b._v};
728 }
729
730 template<typename F>
731 bool operator!=(const OpCounter<F>& a, const F& b)
732 {
733 ++OpCounter<F>::counters.comparison_count;
734 return {a._v != b};
735 }
736
737 template<typename F>
738 bool operator!=(const F& a, const OpCounter<F>& b)
739 {
740 ++OpCounter<F>::counters.comparison_count;
741 return {a != b._v};
742 }
743
744 template<typename F, typename T>
745 bool operator!=(const OpCounter<F>& a, const T& b)
746 {
747 ++OpCounter<F>::counters.comparison_count;
748 return {a._v != b};
749 }
750
751 template<typename F, typename T>
752 bool operator!=(const T& a, const OpCounter<F>& b)
753 {
754 ++OpCounter<F>::counters.comparison_count;
755 return {a != b._v};
756 }
757
758
759 // ********************************************************************************
760 // equals
761 // ********************************************************************************
762
763 template<typename F>
764 bool operator==(const OpCounter<F>& a, const OpCounter<F>& b)
765 {
766 ++OpCounter<F>::counters.comparison_count;
767 return {a._v == b._v};
768 }
769
770 template<typename F>
771 bool operator==(const OpCounter<F>& a, const F& b)
772 {
773 ++OpCounter<F>::counters.comparison_count;
774 return {a._v == b};
775 }
776
777 template<typename F>
778 bool operator==(const F& a, const OpCounter<F>& b)
779 {
780 ++OpCounter<F>::counters.comparison_count;
781 return {a == b._v};
782 }
783
784 template<typename F, typename T>
785 bool operator==(const OpCounter<F>& a, const T& b)
786 {
787 ++OpCounter<F>::counters.comparison_count;
788 return {a._v == b};
789 }
790
791 template<typename F, typename T>
792 bool operator==(const T& a, const OpCounter<F>& b)
793 {
794 ++OpCounter<F>::counters.comparison_count;
795 return {a == b._v};
796 }
797
798
799
800 // ********************************************************************************
801 // functions
802 // ********************************************************************************
803
804 template<typename F>
805 OpCounter<F> exp(const OpCounter<F>& a)
806 {
807 ++OpCounter<F>::counters.exp_count;
808 return {std::exp(a._v)};
809 }
810
811 template<typename F>
812 OpCounter<F> pow(const OpCounter<F>& a, const OpCounter<F>& b)
813 {
814 ++OpCounter<F>::counters.pow_count;
815 return {std::pow(a._v,b._v)};
816 }
817
818 template<typename F>
819 OpCounter<F> pow(const OpCounter<F>& a, const F& b)
820 {
821 ++OpCounter<F>::counters.pow_count;
822 return {std::pow(a._v,b)};
823 }
824
825 template<typename F, typename T>
826 OpCounter<F> pow(const OpCounter<F>& a, const T& b)
827 {
828 ++OpCounter<F>::counters.pow_count;
829 return {std::pow(a._v,b)};
830 }
831
832 template<typename F>
833 OpCounter<F> pow(const F& a, const OpCounter<F>& b)
834 {
835 ++OpCounter<F>::counters.pow_count;
836 return {std::pow(a,b._v)};
837 }
838
839 template<typename F, typename T>
840 OpCounter<F> pow(const T& a, const OpCounter<F>& b)
841 {
842 ++OpCounter<F>::counters.pow_count;
843 return {std::pow(a,b._v)};
844 }
845
846 template<typename F>
847 OpCounter<F> sin(const OpCounter<F>& a)
848 {
849 ++OpCounter<F>::counters.sin_count;
850 return {std::sin(a._v)};
851 }
852
853 template<typename F>
854 OpCounter<F> cos(const OpCounter<F>& a)
855 {
856 ++OpCounter<F>::counters.sin_count;
857 return {std::cos(a._v)};
858 }
859
860 template<typename F>
861 OpCounter<F> sqrt(const OpCounter<F>& a)
862 {
863 ++OpCounter<F>::counters.sqrt_count;
864 return {std::sqrt(a._v)};
865 }
866
867 template<typename F>
868 OpCounter<F> abs(const OpCounter<F>& a)
869 {
870 ++OpCounter<F>::counters.comparison_count;
871 return {std::abs(a._v)};
872 }
873 }
874}
875
876#endif // __OPCOUNTER__
Class with mathematical matrix operations.
Definition densematrix.hh:33
Definition opcounter.hh:30
static size_type totalOperationCount(bool doReset=false)
Return total number of operations.
Definition opcounter.hh:226
static void reportOperations(Stream &os, bool doReset=false)
Report operations to stream object.
Definition opcounter.hh:220
T abs(const T &t)
our own abs class that works also for multiprecision types
Definition lr.hh:55
Struct storing the number of operations.
Definition opcounter.hh:107
void reportOperations(Stream &os, bool doReset=false)
Report operations to stream object.
Definition opcounter.hh:143
size_type totalOperationCount(bool doReset=false)
Get total number of operations.
Definition opcounter.hh:161