bpp-phyl3 3.0.0
ExtendedFloatEigen.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: The Bio++ Development Group
2//
3// SPDX-License-Identifier: CECILL-2.1
4
5#ifndef BPP_PHYL_LIKELIHOOD_DATAFLOW_EXTENDEDFLOATEIGEN_H
6#define BPP_PHYL_LIKELIHOOD_DATAFLOW_EXTENDEDFLOATEIGEN_H
7
8
9#include "ExtendedFloat.h"
11
12namespace bpp
13{
20
21template<typename Derived>
24{
25private:
26 Derived& der_;
27
28public:
30 using RealScalar = double;
31
32 ExtendedFloatEigenBase(Derived& der) :
33 der_(der) {}
34
35 Derived& derived()
36 {
37 return der_;
38 }
39
40 const Derived& derived() const
41 {
42 return der_;
43 }
44
45 // No Alias
46
48 {
50 }
51};
52
53
54template< int R, int C>
55using EFMatrix = Eigen::Matrix<double, R, C>;
56
57template< int R, int C>
58using EFArray = Eigen::Array<double, R, C>;
59
60/*
61 * Class associating Eigen::Matrix & exponent to hanble underflow.
62 *
63 *
64 */
65
66template< int R, int C, template< int R2, int C2> class EigenType>
67class ExtendedFloatEigen : public ExtendedFloatEigenBase<ExtendedFloatEigen<R, C, EigenType>>
68{
69 using ExtType = int;
70 using MatType = EigenType<R, C>;
71
72 using RefMatType = Eigen::Ref<EigenType<R, C>>;
73
75
77
78 template< int R2, int C2>
80
81 template< int R2, int C2>
83
84protected:
87
88 // For specific output without too many creations
90 {
91private:
93
94 void set_float_part(double x)
95 {
96 f_ = x;
97 }
99 {
100 exp_ = x;
101 }
102
103public:
106 eigen_(eigen) {}
107
109 {
110 return eigen_.exponent_part();
111 }
112
113 friend class ExtendedFloatEigen;
114 };
115
117
118public:
121 mat_(MatType()),
122 exp_(0),
123 EFtmp_(*this)
124 {}
125
126 ExtendedFloatEigen(Eigen::DenseBase<MatType>& mat,
127 ExtType exp = 0) :
129 mat_(mat.derived()),
130 exp_(exp),
131 EFtmp_(*this)
132 {}
133
135 ExtType exp = 0) :
137 mat_(mat),
138 exp_(exp),
139 EFtmp_(*this)
140 {}
141
142 ExtendedFloatEigen(const Eigen::DenseBase<MatType>& mat,
143 ExtType exp = 0) :
145 mat_(mat.derived()),
146 exp_(exp),
147 EFtmp_(*this)
148 {}
149
150 ExtendedFloatEigen(const Eigen::internal::traits<MatType>& mat,
151 ExtType exp = 0) :
153 mat_(mat),
154 exp_(exp),
155 EFtmp_(*this)
156 {}
157
158 template<class Other>
161 mat_(other.derived().float_part()),
162 exp_(other.derived().exponent_part()),
163 EFtmp_(*this) {}
164
167 mat_(other.float_part()),
168 exp_(other.exponent_part()),
169 EFtmp_(*this) {}
170
172 ExtType exp = 0) :
174 mat_(mat),
175 exp_(exp),
176 EFtmp_(*this)
177 {}
178
182 exp_(0),
183 EFtmp_(*this) {}
184
188 exp_(0),
189 EFtmp_(*this) {}
190
192
193 // Specific constructors
194
195 static Self Zero(Eigen::Index rows, Eigen::Index cols)
196 {
197 return Self(MatType::Zero(rows, cols), 0);
198 }
199
200 static Self Zero(Eigen::Index rows)
201 {
202 return Self(MatType::Zero(rows), 0);
203 }
204
205 static Self Ones(Eigen::Index rows, Eigen::Index cols)
206 {
207 return Self(MatType::Ones(rows, cols), 0);
208 }
209
210 static Self Ones(Eigen::Index rows)
211 {
212 return Self(MatType::Ones(rows), 0);
213 }
214
215 static Self Identity(Eigen::Index rows)
216 {
217 return Self(MatType::Identity(rows, rows), 0);
218 }
219
220 static Self Constant(Eigen::Index rows, Eigen::Index cols, double value)
221 {
222 return Self(MatType::Constant(rows, cols, value), 0);
223 }
224
225 static Self Constant(Eigen::Index rows, Eigen::Index cols, const ExtendedFloat& value)
226 {
227 return Self(MatType::Constant(rows, cols, value.float_part()), value.exponent_part());
228 }
229
230 static Self Constant(Eigen::Index rows, double value)
231 {
232 return Self(MatType::Constant(rows, value), 0);
233 }
234
235 static Self Constant(Eigen::Index rows, const ExtendedFloat& value)
236 {
237 return Self(MatType::Constant(rows, value.float_part()), value.exponent_part());
238 }
239
240 // operators
241
243 {
244 mat_ = other.mat_;
245 exp_ = other.exp_;
246 return *this;
247 }
248
250 {
251 mat_ = other;
252 exp_ = 0;
253 return *this;
254 }
255
256 template<typename Derived>
258 {
259 mat_ = other.derived().float_part();
260 exp_ = other.derived().exponent_part();
261 return *this;
262 }
263
264 // access members
265
266 virtual const ExtType& exponent_part () const { return exp_; }
267
268 virtual const MatType& float_part () const { return mat_; }
269
270 virtual ExtType& exponent_part () { return exp_; }
271
272 virtual MatType& float_part () { return mat_; }
273
274 // Normalization methods
275
276 bool normalize_big () noexcept
277 {
278 using namespace std;
279
280 auto max = float_part().cwiseAbs().maxCoeff();
281 if (isfinite(max))
282 {
283 bool normalized = false;
285 {
289 normalized = true;
290 }
291 return normalized;
292 }
293 return false;
294 }
295
297 {
298 const auto& fabs = float_part().cwiseAbs();
299 auto max = fabs.maxCoeff();
300 if (max > 0)
301 {
302 // not a vector of zeros
303 auto min = fabs.unaryExpr([max](double d){return d > 0 ? d : max;}).minCoeff();
304 bool normalized = false;
306 {
307 // to prevent overflow
309 {
310 break;
311 }
316 normalized = true;
317 }
318 return normalized;
319 }
320 return false;
321 }
322
323 void normalize () noexcept
324 {
325 if (!normalize_big())
326 {
328 }
329 }
330
331 // Static methods without normalization
332 template< int R2, int C2>
334 {
335 return {lhs.float_part () * rhs.float_part (), lhs.exponent_part () + rhs.exponent_part ()};
336 }
337
338 template< typename Derived>
339 inline static Self denorm_mul(const Self& lhs, const Eigen::EigenBase<Derived>& rhs)
340 {
341 return {lhs.float_part () * rhs.derived(), lhs.exponent_part ()};
342 }
343
344 template< typename Derived>
345 inline static Self denorm_mul(const Eigen::EigenBase<Derived>& lhs, const Self& rhs)
346 {
347 return {lhs.derived() * rhs.float_part (), rhs.exponent_part ()};
348 }
349
350 template<typename T>
351 typename std::enable_if< std::is_floating_point<T>::value || std::is_integral<T>::value, Self>::type
352 inline static denorm_mul (const Self& lhs, const T& rhs)
353 {
354 return {lhs.float_part () * rhs, lhs.exponent_part ()};
355 }
356
357 inline static Self denorm_mul (const Self& lhs, const double& rhs)
358 {
359 return {lhs.float_part () * rhs, lhs.exponent_part ()};
360 }
361
362 inline static Self denorm_mul (const Self& lhs, const ExtendedFloat& rhs)
363 {
364 return {lhs.float_part () * rhs.float_part (), lhs.exponent_part () + rhs.exponent_part ()};
365 }
366
367 template<typename T>
368 typename std::enable_if<std::is_same<T, Self>::value || std::is_same<T, ExtendedFloat>::value, Self>::type
369 inline static denorm_div (const Self& lhs, const T& rhs)
370 {
371 return {lhs.float_part () / rhs.float_part (), lhs.exponent_part () - rhs.exponent_part ()};
372 }
373
374 template<typename Derived>
375 inline Self static denorm_div (const Self& lhs, const ExtendedFloatEigenBase<Derived>& rhs)
376 {
377 return {lhs.float_part () / rhs.derived().float_part (), lhs.exponent_part () - rhs.derived().exponent_part ()};
378 }
379
380 template<typename T>
381 typename std::enable_if<std::is_floating_point<T>::value || std::is_integral<T>::value, Self>::type
382 inline static denorm_add (const Self& lhs, const T& rhs)
383 {
384 return (lhs.exponent_part () >= 0) ?
385 Self(lhs.float_part () + rhs * constexpr_power<double>(ExtendedFloat::radix, -lhs.exponent_part ()), lhs.exponent_part ()) :
386 Self(rhs + lhs.float_part () * constexpr_power<double>(ExtendedFloat::radix, lhs.exponent_part ()), 0);
387 }
388
389 template<typename T>
390 typename std::enable_if<std::is_same<T, Self>::value || std::is_same<T, ExtendedFloat>::value, Self>::type
391 inline static denorm_add (const Self& lhs, const T& rhs)
392 {
393 return (lhs.exponent_part () >= rhs.exponent_part ()) ?
394 Self(lhs.float_part () + rhs.float_part () * constexpr_power<double>(ExtendedFloat::radix, rhs.exponent_part () - lhs.exponent_part ()), lhs.exponent_part ()) :
395 Self(rhs.float_part () + lhs.float_part () * constexpr_power<double>(ExtendedFloat::radix, lhs.exponent_part () - rhs.exponent_part ()), rhs.exponent_part ());
396 }
397
398 template<typename T>
399 typename std::enable_if<std::is_same<T, Self>::value || std::is_same<T, ExtendedFloat>::value, Self>::type
400 inline static denorm_sub (const Self& lhs, const T& rhs)
401 {
402 return (lhs.exponent_part () >= rhs.exponent_part ()) ?
403 Self(lhs.float_part () - rhs.float_part () * constexpr_power<double>(ExtendedFloat::radix, rhs.exponent_part () - lhs.exponent_part ()), lhs.exponent_part ()) :
404 Self(rhs.float_part () - lhs.float_part () * constexpr_power<double>(ExtendedFloat::radix, lhs.exponent_part () - rhs.exponent_part ()), rhs.exponent_part ());
405 }
406
407
408 template<typename T>
409 typename std::enable_if<std::is_floating_point<T>::value || std::is_integral<T>::value, Self>::type
410 inline static denorm_sub (const Self& lhs, const T& rhs)
411 {
412 return (lhs.exponent_part () >= 0) ?
413 Self(lhs.float_part () - rhs * constexpr_power<double>(ExtendedFloat::radix, -lhs.exponent_part ()), lhs.exponent_part ()) :
414 Self(rhs - lhs.float_part () * constexpr_power<double>(ExtendedFloat::radix, lhs.exponent_part ()), 0);
415 }
416
417 inline static Self denorm_pow (const Self& arr, double exp)
418 {
419 double b = arr.exponent_part() * exp;
421 double rs = std::pow(ExtendedFloat::radix, (b - e));
422 return Self(arr.float_part().unaryExpr([exp, rs](double x){return std::pow(x, exp) * rs;}), e);
423 }
424
425 inline static Self denorm_pow (const Self& arr, int exp)
426 {
427 if (exp == 0)
428 return Self::Ones(arr.rows(), arr.cols);
429 if (exp & 1)
430 return exp > 0 ? denorm_mul(arr, denorm_pow(arr, exp - 1)) : denorm_div(denorm_pow(arr, exp + 1), arr);
431 else
432 {
433 ExtendedFloatArray<R, C> r2(arr.float_part().square());
434 r2.normalize();
435 auto r2k = denorm_pow(r2, exp >> 1);
436 r2k.normalize();
437 return Self(r2k.float_part(), r2k.exponent_part() + arr.exponent_part() * exp);
438 }
439 }
440
441 /*********************************
442 ** Utilities
443 *********************************/
444
445 /***
446 * Operators
447 *
448 */
449 template<typename T>
450 typename std::enable_if<std::is_same<T, Self>::value || std::is_same<T, ExtendedFloat>::value
451 || std::is_floating_point<T>::value || std::is_integral<T>::value, Self>::type
452 inline operator+(const T& rhs) const
453 {
454 auto r = denorm_add (*this, rhs);
455 r.normalize ();
456 return r;
457 }
458
459 template<template<int R2 = R, int C2 = C> class EigenType2>
461 {
462 auto r = denorm_add (*this, rhs);
463 r.normalize ();
464 return r;
465 }
466
467 template<typename T>
468 typename std::enable_if<std::is_same<T, Self>::value || std::is_same<T, ExtendedFloat>::value
469 || std::is_floating_point<T>::value || std::is_integral<T>::value, Self>::type
470 inline operator-(const T& rhs) const
471 {
472 auto r = denorm_sub (*this, rhs);
473 r.normalize ();
474 return r;
475 }
476
477 template<int R2 = C, int C2, template<int R3 = R2, int C3 = C2> class EigenType2>
479 {
480 auto r = denorm_mul (*this, rhs);
481 r.normalize ();
482 return r;
483 }
484
485 // Not sure the product will be fine, in case of dimension mismatch
486 template<typename Derived>
487 inline Self operator*(const Eigen::EigenBase<Derived>& rhs) const
488 {
489 auto r = denorm_mul(*this, rhs);
490 r.normalize ();
491 return r;
492 }
493
494 template<typename T>
495 typename std::enable_if<std::is_floating_point<T>::value || std::is_integral<T>::value || std::is_same<T, ExtendedFloat>::value, Self>::type
496 inline operator*(const T& fact) const
497 {
498 auto r = denorm_mul(*this, fact);
499 r.normalize ();
500 return r;
501 }
502
503 template<typename T>
504 typename std::enable_if<std::is_floating_point<T>::value || std::is_integral<T>::value || std::is_same<T, ExtendedFloat>::value, Self>::type
505 inline operator/(const T& fact) const
506 {
507 auto r = denorm_div(*this, fact);
508 r.normalize ();
509 return r;
510 }
511
512 template<typename Derived>
514 {
515 auto r = denorm_div(*this, rhs);
516 r.normalize ();
517 return r;
518 }
519
520 template<typename Derived>
522 {
523 auto r = ExtendedFloat(float_part().dot(rhs.derived().float_part ()), exponent_part () + rhs.derived().exponent_part ());
524 r.normalize();
525 return r;
526 }
527
528 template<typename Derived>
529 inline ExtendedFloat dot (const Eigen::DenseBase<Derived>& rhs) const
530 {
531 auto r = ExtendedFloat(float_part().dot(rhs.derived ()), exponent_part ());
532 r.normalize();
533 return r;
534 }
535
536 template<typename Obj>
537 inline ExtendedFloat dot (const Eigen::Ref<Obj>& rhs) const
538 {
539 auto r = ExtendedFloat(float_part().dot(rhs.derived ()), exponent_part ());
540 r.normalize();
541 return r;
542 }
543
544 inline Self operator-() const
545 {
546 return Self(-float_part(), exponent_part());
547 }
548
549 inline Self eval() const
550 {
551 return Self(float_part().eval(), exponent_part());
552 }
553
554
555 /*
556 * Modifying operators
557 *
558 */
559 template<typename T>
560 typename std::enable_if<std::is_same<T, Self>::value || std::is_same<T, ExtendedFloat>::value, Self&>::type
561 inline operator*=(const T& rhs)
562 {
563 float_part () *= rhs.float_part ();
564 exponent_part () += rhs.exponent_part ();
565 normalize();
566 return *this;
567 }
568
569 template<typename T>
570 typename std::enable_if<std::is_floating_point<T>::value || std::is_integral<T>::value, Self&>::type
571 inline operator*=(const T& div)
572 {
573 float_part () *= div;
574 normalize();
575 return *this;
576 }
577
578 template<typename Derived>
579 inline Self& operator*=(const Eigen::DenseBase<Derived>& div)
580 {
581 float_part () *= div.derived();
582 normalize();
583 return *this;
584 }
585
586 template<typename Derived>
588 {
589 float_part () *= div.derived().float_part();
590 exponent_part () += div.derived().exponent_part ();
591 normalize();
592 return *this;
593 }
594
595
596 template<typename T>
597 typename std::enable_if<std::is_same<T, Self>::value || std::is_same<T, ExtendedFloat>::value, Self&>::type
598 inline operator/=(const T& rhs)
599 {
600 float_part () /= rhs.float_part ();
601 exponent_part () -= rhs.exponent_part ();
602 normalize();
603 return *this;
604 }
605
606 template<typename T>
607 typename std::enable_if<std::is_floating_point<T>::value || std::is_integral<T>::value, Self&>::type
608 inline operator/=(const T& div)
609 {
610 float_part () /= div;
611 return *this;
612 }
613
614
615 template<typename T>
616 typename std::enable_if<std::is_base_of<ExtendedFloatEigenCore, T>::value || std::is_same<T, ExtendedFloat>::value, Self&>::type
617 inline operator+=(const T& rhs)
618 {
619 if (exponent_part () >= rhs.exponent_part ())
620 {
621 float_part() += rhs.float_part () * constexpr_power<double>(ExtendedFloat::radix, rhs.exponent_part () - exponent_part ());
622 }
623 else
624 {
625 float_part() = rhs.float_part () + float_part () * constexpr_power<double>(ExtendedFloat::radix, exponent_part () - rhs.exponent_part ());
626 exponent_part() = rhs.exponent_part ();
627 }
628 normalize ();
629 return *this;
630 }
631
632 template<typename T>
633 typename std::enable_if<std::is_floating_point<T>::value || std::is_integral<T>::value, Self&>::type
634 inline operator+=(const T& rhs)
635 {
636 if (exponent_part () >= 0)
637 {
638 float_part() += rhs * constexpr_power<double>(ExtendedFloat::radix, -exponent_part ());
639 }
640 else
641 {
642 float_part() = rhs.float_part () + float_part () * constexpr_power<double>(ExtendedFloat::radix, exponent_part ());
643 exponent_part() = 0;
644 }
645 normalize ();
646 return *this;
647 }
648
649 template<typename T>
650 typename std::enable_if<std::is_same<T, Self>::value || std::is_same<T, ExtendedFloat>::value, Self&>::type
651 inline operator-=(const T& rhs)
652 {
653 if (exponent_part () >= rhs.exponent_part ())
654 {
655 float_part() -= rhs.float_part () * constexpr_power<double>(ExtendedFloat::radix, rhs.exponent_part () - exponent_part ());
656 }
657 else
658 {
659 float_part() = rhs.float_part () - float_part () * constexpr_power<double>(ExtendedFloat::radix, exponent_part () - rhs.exponent_part ());
660 exponent_part() = rhs.exponent_part ();
661 }
662 normalize ();
663 return *this;
664 }
665
666 template<typename T>
667 typename std::enable_if<std::is_floating_point<T>::value || std::is_integral<T>::value, Self&>::type
668 inline operator-=(const T& rhs)
669 {
670 if (exponent_part () >= 0)
671 {
672 float_part() -= rhs * constexpr_power<double>(ExtendedFloat::radix, -exponent_part ());
673 }
674 else
675 {
676 float_part() = float_part () * constexpr_power<double>(ExtendedFloat::radix, exponent_part ()) - rhs.float_part ();
677 exponent_part() = 0;
678 }
679 normalize ();
680 return *this;
681 }
682
683
684 inline Self log () const
685 {
686 return Self(float_part ().log() + static_cast<double>(exponent_part ()) * ExtendedFloat::ln_radix, 0);
687 }
688
689 inline Self exp () const
690 {
691 // look for max, ie most important exp
692 Eigen::Index maxRow, maxCol;
693 const auto& arrf = float_part();
694 auto max = arrf.maxCoeff(&maxRow, &maxCol);
695
697
699 c.unaryExpr([rcoeff](double x){return std::pow(ExtendedFloat::radix, x - (double)std::get<0>(rcoeff));});
700
701 // more precision for the max
702 c(maxRow, maxCol) = std::pow(ExtendedFloat::radix, std::get<1>(rcoeff));
703
704 Self expM(c, std::get<0>(rcoeff));
705 expM.normalize();
706 return expM;
707 }
708
709 /*
710 * Tests
711 *
712 */
713 inline bool operator==(const Self& rhs) const
714 {
715 return float_part() == rhs.float_part() && exponent_part() == rhs.exponent_part();
716 }
717
718 inline bool operator!=(const Self& rhs) const
719 {
720 return float_part() != rhs.float_part() || exponent_part() != rhs.exponent_part();
721 }
722
723 /*
724 * Eigen like operators
725 *
726 */
727 void fill(double val)
728 {
729 float_part().fill(val);
730 exponent_part() = 0;
731 }
732
733 Eigen::Index cols() const
734 {
735 return float_part().cols();
736 }
737
738 Eigen::Index rows() const
739 {
740 return float_part().rows();
741 }
742
743 template<typename CustomNullaryOp>
744 static Self NullaryExpr(Eigen::Index rows, Eigen::Index cols, const CustomNullaryOp& func)
745 {
746 return Self(MatType::NullaryExpr(rows, cols, func), func.exponent_part());
747 }
748
750 {
752 }
753
755 {
757 }
758
759 template<typename M = MatType>
760 typename std::enable_if<std::is_same<M, EFMatrix<R, C>>::value, ExtendedFloatCol<R, C, EigenType >>::type
761 col(Eigen::Index pos)
762 {
763 return ExtendedFloatCol<R, C, EigenType>(*this, pos);
764 }
765
767 {
769 }
770
771 template<typename M = MatType>
772 typename std::enable_if<std::is_same<M, EFMatrix<R, C>>::value, ExtendedFloatRow<R, C, EigenType >>::type
773 row(Eigen::Index pos)
774 {
775 return ExtendedFloatRow<R, C, EigenType>(*this, pos);
776 }
777
779 {
781 }
782
784 {
786 }
787
788
789 /****
790 * @brief Access to elements of the matrix
791 *
792 */
793 const ExtendedFloat& operator()(Eigen::Index c) const
794 {
797 return EFtmp_;
798 }
799
800 const ExtendedFloat& operator()(Eigen::Index r, Eigen::Index c) const
801 {
804 return EFtmp_;
805 }
806
807 template<typename M = MatType>
808 typename std::enable_if<std::is_same<M, EFArray<R, C>>::value, const ExtendedFloat&>::type
809 operator[](Eigen::Index pos) const
810 {
813 return EFtmp_;
814 }
815
816 const ExtendedFloat& sum() const
817 {
820 return EFtmp_;
821 }
822
823 const ExtendedFloat& mean() const
824 {
827 return EFtmp_;
828 }
829
830 const ExtendedFloat& maxCoeff(size_t* pos = 0) const
831 {
833 if (pos)
835 else
837 return EFtmp_;
838 }
839
840 /*********************************************/
841 /*** Modifications ******/
842
844 {
846 }
847
848 void resize(Eigen::Index rows, Eigen::Index cols)
849 {
850 float_part().resize(rows, cols);
851 }
852
853 void resize(Eigen::Index rows)
854 {
855 float_part().resize(rows);
856 }
857
858 Eigen::Index size() const
859 {
860 return float_part().size();
861 }
862
863 /**************************************/
864 /* Output */
865
866 friend std::ostream& operator<<(std::ostream& out, const Self& ef)
867 {
868 return out << "( " << ef.float_part() << " ) * 2^" << ef.exponent_part();
869 }
870};
871
872
873/*
874 * Convenient shortnames.
875 *
876 */
877
878template< int R, int C>
880
881template< int R, int C>
883
884template< int R>
886
887template< int C>
889
891
893
895
897
898
899/* Extern Methods */
900
901template< int R, int C>
903{
904 return arr.log();
905}
906
907
908template< int R, int C, template< int R2 = R, int C2 = C> class MatType>
910{
911 return arr.exp();
912}
913
914template< int R, int C>
916{
918 r.normalize ();
919 return r;
920}
921
922template< int R, int C>
924{
926 r.normalize ();
927 return r;
928}
929
930
931template<int R, int C, template< int R2 = R, int C2 = C> class MatType, typename T>
932typename std::enable_if<std::is_same<T, ExtendedFloat>::value
933 || std::is_floating_point<T>::value || std::is_integral<T>::value,
934 ExtendedFloatEigen<R, C, MatType>>::type
935inline operator+(const T& d, const ExtendedFloatEigen<R, C, MatType> rhs)
936{
937 return rhs + d;
938}
939
940template<int R, int C, template< int R2 = R, int C2 = C> class MatType, typename T>
941typename std::enable_if<std::is_same<T, ExtendedFloat>::value
942 || std::is_floating_point<T>::value || std::is_integral<T>::value,
943 ExtendedFloatEigen<R, C, MatType>>::type
944inline operator-(const T& d, const ExtendedFloatEigen<R, C, MatType> rhs)
945{
946 return -(rhs - d);
947}
948
949template<int R, int C, template< int R2 = R, int C2 = C> class MatType, typename T>
950typename std::enable_if<std::is_same<T, ExtendedFloat>::value
951 || std::is_floating_point<T>::value || std::is_integral<T>::value,
952 ExtendedFloatEigen<R, C, MatType>>::type
953inline operator*(const T& fact, const ExtendedFloatEigen<R, C, MatType> mat)
954{
956 r.normalize ();
957 return r;
958}
959
960template<typename Derived, typename EFType>
961inline EFType operator*(const Eigen::EigenBase<Derived>& lhs,
963{
964 auto r = EFType::denorm_mul(lhs.derived(), rhs);
965 r.normalize ();
966 return r;
967}
968
969
970template< int R, int C>
972{
974
976
977 using ExtType = int;
978
980
981private:
983
984public:
986 efm_(&other) {}
987
989 {
990 return efm_->exponent_part();
991 }
992
994 {
995 return efm_->float_part();
996 }
997
998
999 Self operator=(const Array& rhs)
1000 {
1001 efm_->float_part().array() = rhs.float_part();
1002 efm_->exponent_part() = rhs.exponent_part();
1003 return *this;
1004 }
1005
1007 {
1008 if (efm_->float_part().isZero())
1009 return operator=(rhs);
1010
1011 if (efm_->exponent_part () >= rhs.exponent_part ())
1012 {
1013 efm_->float_part().array() += rhs.float_part() * constexpr_power<double>(ExtendedFloat::radix, rhs.exponent_part () - efm_->exponent_part ());
1014 }
1015 else
1016 {
1017 efm_->float_part().array() = rhs.float_part () + efm_->float_part ().array() * constexpr_power<double>(ExtendedFloat::radix, efm_->exponent_part () - rhs.exponent_part ());
1018 efm_->exponent_part() = rhs.exponent_part ();
1019 }
1020 efm_->normalize ();
1021
1022 return *this;
1023 }
1024
1026 {
1027 efm_->float_part().array() *= rhs.float_part ();
1028 efm_->exponent_part() += rhs.exponent_part ();
1029 efm_->normalize ();
1030 return *this;
1031 }
1032
1033 Array operator*(const Array& rhs) const
1034 {
1035 Array r(efm_->float_part().array() * rhs.float_part (), efm_->exponent_part () + rhs.exponent_part ());
1036 r.normalize();
1037 return r;
1038 }
1039
1040 Array operator*(const Self& rhs) const
1041 {
1042 Array r(efm_->float_part().array() * rhs.float_part (), efm_->exponent_part () + rhs.exponent_part ());
1043 r.normalize();
1044 return r;
1045 }
1046};
1047
1048template<int R, int C>
1051{
1052 return rhs * lhs; // cwise * is commutative
1053}
1054}
1055#endif // BPP_PHYL_LIKELIHOOD_DATAFLOW_EXTENDEDFLOATEIGEN_H
Self operator+=(const Array &rhs)
Array operator*(const Self &rhs) const
ExtendedFloatArrayWrapper(ExtendedFloatMatrix< R, C > &other)
Self operator=(const Array &rhs)
Self operator*=(const Array &rhs)
Array operator*(const Array &rhs) const
ExtendedFloatMatrix< R, C > *const efm_
const Derived & derived() const
ExtendedFloatNoAlias< Derived > noalias()
OwnedExtendedFloat(const ExtendedFloatEigen &eigen)
void set_exponent_part(ExtendedFloat::ExtType x)
const ExtendedFloat::ExtType & exponent_part() const
static Self Constant(Eigen::Index rows, Eigen::Index cols, double value)
std::enable_if< std::is_floating_point< T >::value||std::is_integral< T >::value, Self & >::type operator/=(const T &div)
std::enable_if< std::is_floating_point< T >::value||std::is_integral< T >::value, Self & >::type operator-=(const T &rhs)
static Self denorm_pow(const Self &arr, int exp)
std::enable_if< std::is_same< M, EFArray< R, C > >::value, constExtendedFloat & >::type operator[](Eigen::Index pos) const
static Self denorm_mul(const Self &lhs, const ExtendedFloat &rhs)
bool operator==(const Self &rhs) const
ExtendedFloatEigen< R, C2, EigenType > operator*(const ExtendedFloatEigen< R2, C2, EigenType2 > &rhs) const
static ExtendedFloatEigen< R, C2, EigenType > denorm_mul(const Self &lhs, const ExtendedFloatEigen< R2, C2, EigenType > &rhs)
static std::enable_if< std::is_floating_point< T >::value||std::is_integral< T >::value, Self >::type denorm_add(const Self &lhs, const T &rhs)
const ExtendedFloat & operator()(Eigen::Index c) const
Eigen::Ref< EigenType< R, C > > RefMatType
Self & operator=(const ExtendedFloatEigenBase< Derived > &other)
bool operator!=(const Self &rhs) const
ExtendedFloatVectorwiseOp< const Self, const MatType, Eigen::Vertical > colwise() const
static Self Zero(Eigen::Index rows, Eigen::Index cols)
ExtendedFloatEigen(const Eigen::internal::traits< MatType > &mat, ExtType exp=0)
std::enable_if< std::is_floating_point< T >::value||std::is_integral< T >::value||std::is_same< T, ExtendedFloat >::value, Self >::type operator/(const T &fact) const
ExtendedFloatEigen< R, C, EigenType > Self
Eigen::Index size() const
ExtendedFloatEigen & operator=(const MatType &other)
static Self denorm_div(const Self &lhs, const ExtendedFloatEigenBase< Derived > &rhs)
static Self denorm_mul(const Eigen::EigenBase< Derived > &lhs, const Self &rhs)
virtual const MatType & float_part() const
static Self Zero(Eigen::Index rows)
static Self Constant(Eigen::Index rows, const ExtendedFloat &value)
static Self Ones(Eigen::Index rows)
std::enable_if< std::is_same< T, Self >::value||std::is_same< T, ExtendedFloat >::value||std::is_floating_point< T >::value||std::is_integral< T >::value, Self >::type operator-(const T &rhs) const
ExtendedFloat dot(const Eigen::DenseBase< Derived > &rhs) const
ExtendedFloatEigen(const MatType &mat, ExtType exp=0)
virtual ExtType & exponent_part()
ExtendedFloatEigen(MatType &mat, ExtType exp=0)
static std::enable_if< std::is_floating_point< T >::value||std::is_integral< T >::value, Self >::type denorm_sub(const Self &lhs, const T &rhs)
virtual MatType & float_part()
ExtendedFloatEigen(const Eigen::DenseBase< MatType > &mat, ExtType exp=0)
ExtendedFloatEigen & operator=(const ExtendedFloatEigen &other)
static Self Constant(Eigen::Index rows, Eigen::Index cols, const ExtendedFloat &value)
std::enable_if< std::is_same< M, EFMatrix< R, C > >::value, ExtendedFloatCol< R, C, EigenType > >::type col(Eigen::Index pos)
static std::enable_if< std::is_same< T, Self >::value||std::is_same< T, ExtendedFloat >::value, Self >::type denorm_sub(const Self &lhs, const T &rhs)
const ExtendedFloat & maxCoeff(size_t *pos=0) const
const ExtendedFloat & mean() const
std::enable_if< std::is_base_of< ExtendedFloatEigenCore, T >::value||std::is_same< T, ExtendedFloat >::value, Self & >::type operator+=(const T &rhs)
const ExtendedFloat & sum() const
ExtendedFloatEigen(Eigen::DenseBase< MatType > &mat, ExtType exp=0)
Self & operator*=(const Eigen::DenseBase< Derived > &div)
static Self denorm_pow(const Self &arr, double exp)
std::enable_if< std::is_floating_point< T >::value||std::is_integral< T >::value, Self & >::type operator+=(const T &rhs)
Self operator*(const Eigen::EigenBase< Derived > &rhs) const
Eigen::Index cols() const
ExtendedFloatEigen(const ExtendedFloatEigenBase< Other > &other)
friend std::ostream & operator<<(std::ostream &out, const Self &ef)
ExtendedFloatEigen< R, 1, EigenType > col(Eigen::Index col) const
ExtendedFloat dot(const Eigen::Ref< Obj > &rhs) const
Eigen::Index rows() const
ExtendedFloatEigen(const ExtendedFloatEigen &other)
static Self NullaryExpr(Eigen::Index rows, Eigen::Index cols, const CustomNullaryOp &func)
ExtendedFloat dot(const ExtendedFloatEigenBase< Derived > &rhs) const
Self & operator*=(const ExtendedFloatEigenBase< Derived > &div)
OwnedExtendedFloat EFtmp_
std::enable_if< std::is_same< T, Self >::value||std::is_same< T, ExtendedFloat >::value, Self & >::type operator-=(const T &rhs)
EigenType< R, C > MatType
virtual const ExtType & exponent_part() const
std::enable_if< std::is_same< T, Self >::value||std::is_same< T, ExtendedFloat >::value, Self & >::type operator*=(const T &rhs)
static Self Identity(Eigen::Index rows)
static Self denorm_mul(const Self &lhs, const double &rhs)
ExtendedFloatVectorwiseOp< const Self, const MatType, Eigen::Horizontal > rowwise() const
ExtendedFloatVectorwiseOp< Self, MatType, Eigen::Horizontal > rowwise()
ExtendedFloatEigen(int rows, int cols)
static Self Constant(Eigen::Index rows, double value)
ExtendedFloatMatrix< C, R > transpose() const
std::enable_if< std::is_floating_point< T >::value||std::is_integral< T >::value, Self & >::type operator*=(const T &div)
void resize(Eigen::Index rows, Eigen::Index cols)
Self operator+(const ExtendedFloatEigen< R, C, EigenType2 > &rhs) const
static Self Ones(Eigen::Index rows, Eigen::Index cols)
static std::enable_if< std::is_same< T, Self >::value||std::is_same< T, ExtendedFloat >::value, Self >::type denorm_add(const Self &lhs, const T &rhs)
static Self denorm_mul(const Self &lhs, const Eigen::EigenBase< Derived > &rhs)
std::enable_if< std::is_same< M, EFMatrix< R, C > >::value, ExtendedFloatRow< R, C, EigenType > >::type row(Eigen::Index pos)
std::enable_if< std::is_floating_point< T >::value||std::is_integral< T >::value||std::is_same< T, ExtendedFloat >::value, Self >::type operator*(const T &fact) const
std::enable_if< std::is_same< T, Self >::value||std::is_same< T, ExtendedFloat >::value, Self & >::type operator/=(const T &rhs)
void resize(Eigen::Index rows)
const ExtendedFloat & operator()(Eigen::Index r, Eigen::Index c) const
static std::enable_if< std::is_same< T, Self >::value||std::is_same< T, ExtendedFloat >::value, Self >::type denorm_div(const Self &lhs, const T &rhs)
static std::enable_if< std::is_floating_point< T >::value||std::is_integral< T >::value, Self >::type denorm_mul(const Self &lhs, const T &rhs)
Self operator/(const ExtendedFloatEigenBase< Derived > &rhs) const
std::enable_if< std::is_same< T, Self >::value||std::is_same< T, ExtendedFloat >::value||std::is_floating_point< T >::value||std::is_integral< T >::value, Self >::type operator+(const T &rhs) const
ExtendedFloatVectorwiseOp< Self, MatType, Eigen::Vertical > colwise()
std::tuple< int, double > lround() const
const ExtType & exponent_part() const noexcept
Definition: ExtendedFloat.h:89
static const double ln_radix
Definition: ExtendedFloat.h:51
const FloatType & float_part() const noexcept
Definition: ExtendedFloat.h:88
static constexpr FloatType normalize_big_factor
Definition: ExtendedFloat.h:77
static constexpr FloatType smallest_normalized_value
Definition: ExtendedFloat.h:73
static constexpr FloatType normalize_small_factor
Definition: ExtendedFloat.h:78
static constexpr FloatType biggest_normalized_value
Definition: ExtendedFloat.h:62
static constexpr int biggest_normalized_radix_power
Definition: ExtendedFloat.h:57
static constexpr int smallest_normalized_radix_power
Definition: ExtendedFloat.h:69
static constexpr int radix
Definition: ExtendedFloat.h:49
Defines the basic types of data flow nodes.
ExtendedFloatArray< Eigen::Dynamic, 1 > ExtendedFloatArrayXd
double log(const ExtendedFloat &ef)
ExtendedFloat exp(const ExtendedFloat &ef)
std::vector< T > operator-(const std::vector< T > &v1, const std::vector< T > &v2)
Eigen::Array< double, R, C > EFArray
ExtendedFloat pow(const ExtendedFloat &ef, double exp)
std::vector< T > operator*(const std::vector< T > &v1, const std::vector< T > &v2)
std::vector< T > operator+(const std::vector< T > &v1, const std::vector< T > &v2)
ExtendedFloatRowVector< Eigen::Dynamic > ExtendedFloatRowVectorXd
Eigen::Matrix< double, R, C > EFMatrix
ExtendedFloatArray< R, C > pow(const ExtendedFloatArray< R, C > &obj, int exp)
ExtendedFloatMatrix< Eigen::Dynamic, Eigen::Dynamic > ExtendedFloatMatrixXd
ExtendedFloatVector< Eigen::Dynamic > ExtendedFloatVectorXd