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 
12 namespace bpp
13 {
20 
21 template<typename Derived>
24 {
25 private:
26  Derived& der_;
27 
28 public:
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 
54 template< int R, int C>
55 using EFMatrix = Eigen::Matrix<double, R, C>;
56 
57 template< int R, int C>
58 using EFArray = Eigen::Array<double, R, C>;
59 
60 /*
61  * Class associating Eigen::Matrix & exponent to hanble underflow.
62  *
63  *
64  */
65 
66 template< int R, int C, template< int R2, int C2> class EigenType>
67 class 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 
84 protected:
87 
88  // For specific output without too many creations
90  {
91 private:
93 
94  void set_float_part(double x)
95  {
96  f_ = x;
97  }
99  {
100  exp_ = x;
101  }
102 
103 public:
105  ExtendedFloat(),
106  eigen_(eigen) {}
107 
109  {
110  return eigen_.exponent_part();
111  }
112 
113  friend class ExtendedFloatEigen;
114  };
115 
117 
118 public:
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 
181  mat_(MatType::Zero(rows, cols)),
182  exp_(0),
183  EFtmp_(*this) {}
184 
187  mat_(MatType::Zero(cols)),
188  exp_(0),
189  EFtmp_(*this) {}
190 
191  virtual ~ExtendedFloatEigen() {}
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  {
327  normalize_small();
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 
696  auto rcoeff = ExtendedFloat(max / ExtendedFloat::ln_radix, exponent_part()).lround();
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 
878 template< int R, int C>
880 
881 template< int R, int C>
883 
884 template< int R>
886 
887 template< int C>
889 
891 
893 
895 
897 
898 
899 /* Extern Methods */
900 
901 template< int R, int C>
903 {
904  return arr.log();
905 }
906 
907 
908 template< int R, int C, template< int R2 = R, int C2 = C> class MatType>
910 {
911  return arr.exp();
912 }
913 
914 template< int R, int C>
916 {
918  r.normalize ();
919  return r;
920 }
921 
922 template< int R, int C>
924 {
926  r.normalize ();
927  return r;
928 }
929 
930 
931 template<int R, int C, template< int R2 = R, int C2 = C> class MatType, typename T>
932 typename 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
935 inline operator+(const T& d, const ExtendedFloatEigen<R, C, MatType> rhs)
936 {
937  return rhs + d;
938 }
939 
940 template<int R, int C, template< int R2 = R, int C2 = C> class MatType, typename T>
941 typename 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
944 inline operator-(const T& d, const ExtendedFloatEigen<R, C, MatType> rhs)
945 {
946  return -(rhs - d);
947 }
948 
949 template<int R, int C, template< int R2 = R, int C2 = C> class MatType, typename T>
950 typename 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
953 inline operator*(const T& fact, const ExtendedFloatEigen<R, C, MatType> mat)
954 {
956  r.normalize ();
957  return r;
958 }
959 
960 template<typename Derived, typename EFType>
961 inline 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 
970 template< int R, int C>
972 {
974 
976 
977  using ExtType = int;
978 
980 
981 private:
983 
984 public:
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 
1006  Self operator+=(const Array& rhs)
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 
1025  Self operator*=(const Array& rhs)
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 };
1048 
1049 template<int R, int C>
1052 {
1053  return rhs * lhs; // cwise * is commutative
1054 }
1055 }
1056 #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_
ExtendedFloatNoAlias< Derived > noalias()
const Derived & derived() const
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)
static Self denorm_pow(const Self &arr, int exp)
std::enable_if< std::is_floating_point< T >::value||std::is_integral< T >::value, Self & >::type operator/=(const T &div)
virtual const ExtType & exponent_part() const
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
static Self denorm_mul(const Self &lhs, const ExtendedFloat &rhs)
std::enable_if< std::is_floating_point< T >::value||std::is_integral< T >::value, Self & >::type operator-=(const T &rhs)
bool operator==(const Self &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
Eigen::Ref< EigenType< R, C > > RefMatType
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)
Self & operator*=(const Eigen::DenseBase< Derived > &div)
bool operator!=(const Self &rhs) const
virtual const MatType & float_part() const
ExtendedFloatEigen< R, C2, EigenType > operator*(const ExtendedFloatEigen< R2, C2, EigenType2 > &rhs) const
ExtendedFloatMatrix< C, R > transpose() const
static Self Zero(Eigen::Index rows, Eigen::Index cols)
const ExtendedFloat & operator()(Eigen::Index c) const
std::enable_if< std::is_same< M, EFArray< R, C > >::value, const ExtendedFloat & >::type operator[](Eigen::Index pos) const
std::enable_if< std::is_same< M, EFMatrix< R, C > >::value, ExtendedFloatRow< R, C, EigenType > >::type row(Eigen::Index pos)
ExtendedFloatEigen(const Eigen::internal::traits< MatType > &mat, ExtType exp=0)
ExtendedFloatEigen< R, C, EigenType > Self
ExtendedFloatEigen< R, 1, EigenType > col(Eigen::Index col) const
Eigen::Index size() const
static Self denorm_div(const Self &lhs, const ExtendedFloatEigenBase< Derived > &rhs)
static Self denorm_mul(const Eigen::EigenBase< Derived > &lhs, const Self &rhs)
static Self Zero(Eigen::Index rows)
static Self Constant(Eigen::Index rows, const ExtendedFloat &value)
static Self Ones(Eigen::Index rows)
ExtendedFloat dot(const Eigen::DenseBase< Derived > &rhs) const
ExtendedFloatVectorwiseOp< Self, MatType, Eigen::Vertical > colwise()
ExtendedFloatEigen(const MatType &mat, ExtType exp=0)
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)
ExtendedFloatEigen & operator=(const ExtendedFloatEigen &other)
ExtendedFloatEigen(MatType &mat, ExtType exp=0)
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)
ExtendedFloatVectorwiseOp< const Self, const MatType, Eigen::Vertical > colwise() const
std::enable_if< std::is_base_of< ExtendedFloatEigenCore, T >::value||std::is_same< T, ExtendedFloat >::value, Self & >::type operator+=(const T &rhs)
ExtendedFloatEigen(const Eigen::DenseBase< MatType > &mat, ExtType exp=0)
static Self Constant(Eigen::Index rows, Eigen::Index cols, const ExtendedFloat &value)
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)
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
virtual MatType & float_part()
std::enable_if< std::is_same< T, Self >::value||std::is_same< T, ExtendedFloat >::value, Self & >::type operator*=(const T &rhs)
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(Eigen::DenseBase< MatType > &mat, ExtType exp=0)
static Self denorm_pow(const Self &arr, double exp)
const ExtendedFloat & operator()(Eigen::Index r, Eigen::Index c) const
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)
ExtendedFloat dot(const Eigen::Ref< Obj > &rhs) const
ExtendedFloatEigen & operator=(const MatType &other)
std::enable_if< std::is_same< T, Self >::value||std::is_same< T, ExtendedFloat >::value, Self & >::type operator-=(const T &rhs)
Eigen::Index rows() const
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)
ExtendedFloatEigen(const ExtendedFloatEigen &other)
std::enable_if< std::is_same< M, EFMatrix< R, C > >::value, ExtendedFloatCol< R, C, EigenType > >::type col(Eigen::Index pos)
static Self NullaryExpr(Eigen::Index rows, Eigen::Index cols, const CustomNullaryOp &func)
ExtendedFloat dot(const ExtendedFloatEigenBase< Derived > &rhs) const
std::enable_if< std::is_floating_point< T >::value||std::is_integral< T >::value, Self & >::type operator*=(const T &div)
virtual ExtType & exponent_part()
OwnedExtendedFloat EFtmp_
EigenType< R, C > MatType
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)
Self & operator=(const ExtendedFloatEigenBase< Derived > &other)
ExtendedFloatEigen(int rows, int cols)
static Self Constant(Eigen::Index rows, double value)
friend std::ostream & operator<<(std::ostream &out, const Self &ef)
const ExtendedFloat & maxCoeff(size_t *pos=0) const
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_floating_point< T >::value||std::is_integral< T >::value, Self >::type denorm_mul(const Self &lhs, const T &rhs)
static Self denorm_mul(const Self &lhs, const Eigen::EigenBase< Derived > &rhs)
static ExtendedFloatEigen< R, C2, EigenType > denorm_mul(const Self &lhs, const ExtendedFloatEigen< R2, C2, EigenType > &rhs)
ExtendedFloatVectorwiseOp< Self, MatType, Eigen::Horizontal > rowwise()
const ExtendedFloat & sum() const
void resize(Eigen::Index rows)
Self & operator*=(const ExtendedFloatEigenBase< Derived > &div)
const ExtendedFloat & mean() const
Self operator/(const ExtendedFloatEigenBase< Derived > &rhs) const
ExtendedFloatVectorwiseOp< const Self, const MatType, Eigen::Horizontal > rowwise() const
static const double ln_radix
Definition: ExtendedFloat.h:51
static constexpr FloatType normalize_big_factor
Definition: ExtendedFloat.h:77
std::tuple< int, double > lround() const
static constexpr FloatType smallest_normalized_value
Definition: ExtendedFloat.h:73
static constexpr FloatType normalize_small_factor
Definition: ExtendedFloat.h:78
const FloatType & float_part() const noexcept
Definition: ExtendedFloat.h:88
const ExtType & exponent_part() const noexcept
Definition: ExtendedFloat.h:89
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
ExtendedFloatArray< R, C > pow(const ExtendedFloatArray< R, C > &obj, int exp)
Eigen::Array< double, R, C > EFArray
ExtendedFloat pow(const ExtendedFloat &ef, double exp)
ExtendedFloatRowVector< Eigen::Dynamic > ExtendedFloatRowVectorXd
Eigen::Matrix< double, R, C > EFMatrix
ExtendedFloatMatrix< Eigen::Dynamic, Eigen::Dynamic > ExtendedFloatMatrixXd
ExtendedFloatVector< Eigen::Dynamic > ExtendedFloatVectorXd