bpp-phyl3  3.0.0
DataFlowNumeric.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_DATAFLOWNUMERIC_H
6 #define BPP_PHYL_LIKELIHOOD_DATAFLOW_DATAFLOWNUMERIC_H
7 
13 #include <Eigen/Core>
14 #include <algorithm>
15 #include <cassert>
16 #include <string>
17 #include <tuple>
18 #include <type_traits>
19 
20 #include "DataFlow.h"
21 #include "Definitions.h"
22 
23 /* For now copy matrix cell by cell.
24  * TODO use eigen internally in SubstitutionModel ! (not perf critical for now though)
25  * FIXME if multithreading, internal model state must be removed !
26  */
27 
28 namespace bpp
29 {
30 /******************/
31 
32 template<typename eVector, typename bVector>
33 using ForConvert = typename std::enable_if< ((std::is_same<bVector, Vdouble>::value
34  || std::is_same<bVector, std::vector<ExtendedFloat>>::value)
35  &&
36  (std::is_same<eVector, Eigen::RowVectorXd>::value
37  || std::is_same<eVector, Eigen::VectorXd>::value)), bool>::type;
38 
39 template<typename eVector,
40  typename bVector, ForConvert<eVector, bVector> = true>
41 void copyBppToEigen (const bVector& bppVector, eVector& eigenVector)
42 {
43  const auto eigenRows = static_cast<Eigen::Index>(bppVector.size());
44  eigenVector.resize (eigenRows);
45  for (Eigen::Index i = 0; i < eigenRows; ++i)
46  {
47  eigenVector (i) = convert(bppVector[size_t(i)]);
48  }
49 }
50 
51 extern template void copyBppToEigen (const std::vector<ExtendedFloat>& bppVector, Eigen::VectorXd& eigenVector);
52 extern template void copyBppToEigen (const std::vector<ExtendedFloat>& bppVector, Eigen::RowVectorXd& eigenVector);
53 extern template void copyBppToEigen (const bpp::Vdouble& bppVector, Eigen::RowVectorXd& eigenVector);
54 extern template void copyBppToEigen (const bpp::Vdouble& bppVector, Eigen::VectorXd& eigenVector);
55 
56 
57 /*****************/
58 
59 template<typename eVector>
60 using EFVector = typename std::enable_if<(std::is_same<eVector, ExtendedFloatRowVectorXd>::value
61  || std::is_same<eVector, ExtendedFloatVectorXd>::value), bool>::type;
62 
63 template<typename eVector, EFVector<eVector> = true>
64 void copyBppToEigen (const std::vector<ExtendedFloat>& bppVector, eVector& eigenVector)
65 {
66  // Look for largest extendedfloat
67  ExtendedFloat::ExtType maxE = std::max_element(bppVector.begin(), bppVector.end(), [](const ExtendedFloat& lhs, const ExtendedFloat& rhs){
68  return lhs.exponent_part() < rhs.exponent_part();
69  })->exponent_part();
70 
71  eigenVector.exponent_part() = maxE;
72  eigenVector.float_part() = Eigen::RowVectorXd::NullaryExpr(static_cast<Eigen::Index>(bppVector.size()),
73  [&maxE, &bppVector](int i){
74  return bppVector[(size_t)i].float_part() * bpp::constexpr_power<double>(bpp::ExtendedFloat::radix, bppVector[(size_t)i].exponent_part () - maxE);
75  });
76 }
77 
78 
79 extern template void copyBppToEigen (const std::vector<ExtendedFloat>& bppVector, ExtendedFloatRowVectorXd& eigenVector);
80 extern template void copyBppToEigen (const std::vector<ExtendedFloat>& bppVector, ExtendedFloatVectorXd& eigenVector);
81 
82 
83 /****************/
84 
85 template<typename eVector>
86 using EFoutput = typename std::enable_if<(std::is_same<eVector, ExtendedFloatRowVectorXd>::value
87  || std::is_same<eVector, ExtendedFloatVectorXd>::value), bool>::type;
88 
89 template<typename eVector,
90  EFoutput<eVector> = true>
91 void copyBppToEigen (const Vdouble& bppVector, eVector& eigenVector)
92 {
93  // Look for largest extendedfloat
94  eigenVector.exponent_part() = 0;
95  copyBppToEigen(bppVector, eigenVector.float_part());
96  eigenVector.normalize();
97 }
98 
99 
100 extern template void copyBppToEigen (const bpp::Vdouble& bppVector, ExtendedFloatRowVectorXd& eigenVector);
101 extern template void copyBppToEigen (const bpp::Vdouble& bppVector, ExtendedFloatVectorXd& eigenVector);
102 
103 
104 /********************************/
105 
106 extern void copyBppToEigen (const bpp::Matrix<double>& bppMatrix, Eigen::MatrixXd& eigenMatrix);
107 extern void copyBppToEigen (const bpp::Matrix<double>& bppMatrix, ExtendedFloatMatrixXd& eigenMatrix);
108 
109 extern void copyBppToEigen (const std::vector<Eigen::VectorXd>& bppVector, Eigen::MatrixXd& eigenMatrix);
110 extern void copyBppToEigen (const std::vector<ExtendedFloatVectorXd>& bppVector, ExtendedFloatMatrixXd& eigenMatrix);
111 
112 
113 /****************/
114 /* copyEigenToBpp */
115 
116 
117 template<typename eType,
118  typename = typename std::enable_if<(std::is_same<eType, double>::value
119  || std::is_same<eType, ExtendedFloat>::value)>::type>
120 void copyEigenToBpp (const ExtendedFloatMatrixXd& eigenMatrix, std::vector<std::vector<eType>>& bppMatrix)
121 {
122  const auto eigenRows = static_cast<std::size_t>(eigenMatrix.rows());
123  const auto eigenCols = static_cast<std::size_t>(eigenMatrix.cols());
124 
125  bppMatrix.resize (eigenRows);
126  for (size_t i = 0; i < eigenRows; ++i)
127  {
128  bppMatrix[i].resize (eigenCols);
129  auto bMi = &bppMatrix[i];
130  for (size_t j = 0; j < eigenCols; ++j)
131  {
132  (*bMi)[j] = convert(eigenMatrix (static_cast<Eigen::Index>(i), static_cast<Eigen::Index>(j)));
133  }
134  }
135 }
136 
137 
138 extern template void copyEigenToBpp(const ExtendedFloatMatrixXd& eigenMatrix, std::vector<std::vector<double>>& bppMatrix);
139 extern template void copyEigenToBpp(const ExtendedFloatMatrixXd& eigenMatrix, std::vector<std::vector<bpp::ExtendedFloat>>& bppMatrix);
140 
141 template<typename eType,
142  typename = typename std::enable_if<(std::is_same<eType, double>::value
143  || std::is_same<eType, ExtendedFloat>::value)>::type>
144 void copyEigenToBpp (const Eigen::MatrixXd& eigenMatrix, std::vector<std::vector<eType>>& bppMatrix)
145 {
146  const auto eigenRows = static_cast<std::size_t>(eigenMatrix.rows());
147  const auto eigenCols = static_cast<std::size_t>(eigenMatrix.cols());
148 
149  bppMatrix.resize (eigenRows);
150  for (size_t i = 0; i < eigenRows; ++i)
151  {
152  bppMatrix[i].resize (eigenCols);
153  auto bMi = &bppMatrix[i];
154  for (size_t j = 0; j < eigenCols; ++j)
155  {
156  (*bMi)[j] = eigenMatrix (static_cast<Eigen::Index>(i), static_cast<Eigen::Index>(j));
157  }
158  }
159 }
160 
161 
162 extern template void copyEigenToBpp(const Eigen::MatrixXd& eigenMatrix, std::vector<std::vector<double>>& bppMatrix);
163 extern template void copyEigenToBpp(const Eigen::MatrixXd& eigenMatrix, std::vector<std::vector<bpp::ExtendedFloat>>& bppMatrix);
164 
165 
166 extern void copyEigenToBpp(const MatrixLik& eigenMatrix, Matrix<double>& bppMatrix);
167 
168 
169 template<typename eVector, typename bVector>
170 using ForConvert2 = typename std::enable_if< ((std::is_same<bVector, Vdouble>::value
171  || std::is_same<bVector, std::vector<ExtendedFloat>>::value)
172  &&
173  (std::is_same<eVector, Eigen::RowVectorXd>::value
174  || std::is_same<eVector, Eigen::VectorXd>::value
175  || std::is_same<eVector, ExtendedFloatVectorXd>::value
176  || std::is_same<eVector, ExtendedFloatRowVectorXd>::value)), bool>::type;
177 
178 
179 template<typename eVector,
180  typename bVector, ForConvert2<bVector, eVector> = true>
181 void copyEigenToBpp (const bVector& eigenVector, eVector& bppVector)
182 {
183  bppVector.resize(size_t(eigenVector.size()));
184  for (auto i = 0; i < eigenVector.size(); i++)
185  {
186  bppVector[(size_t)i] = convert(eigenVector(i));
187  }
188 }
189 
190 extern template void copyEigenToBpp (const RowLik& eigenVector, Vdouble& bppVector);
191 extern template void copyEigenToBpp (const VectorLik& eigenVector, Vdouble& bppVector);
192 extern template void copyEigenToBpp (const RowLik& eigenVector, std::vector<ExtendedFloat>& bppVector);
193 extern template void copyEigenToBpp (const VectorLik& eigenVector, std::vector<ExtendedFloat>& bppVector);
194 
195 /*******************************************/
196 /*** Definition of function from (const Eigen::Vector&) -> const Eigen::Vector& ***/
197 
198 using TransitionFunction = std::function<VectorLik (const VectorLik&)>;
199 
200 /*
201  * The same but with constant result
202  *
203  */
204 
206  public TransitionFunction
207 {
208 private:
210 
211 public:
212  ConstantTransitionFunction(double val, int row) :
213  result_(row)
214  {
215  result_.fill(val);
216  }
217 
219  result_(res){}
220 
222  {
223  return result_;
224  }
225 };
226 
227 /******************************************************************************
228  * Dimension
229  */
230 
232 struct NoDimension {};
233 
234 std::string to_string (const NoDimension&);
235 inline std::size_t hash (const NoDimension&) { return 0; }
236 inline bool operator==(const NoDimension&, const NoDimension&) { return true; }
237 inline bool operator!=(const NoDimension&, const NoDimension&) { return false; }
238 
241 {
242  Eigen::Index rows{};
243  Eigen::Index cols{};
244 
245  MatrixDimension () = default;
246  MatrixDimension (Eigen::Index rows_, Eigen::Index cols_) : rows (rows_),
247  cols (cols_)
248  {}
249  MatrixDimension (int rows_, int cols_) : rows (Eigen::Index(rows_)),
250  cols (Eigen::Index(cols_))
251  {}
252  MatrixDimension (size_t rows_, size_t cols_) : rows (Eigen::Index(rows_)),
253  cols (Eigen::Index(cols_))
254  {}
255 
256  // Get dimensions of any matrix-like eigen object.
257  template<typename Derived>
258  MatrixDimension (const Eigen::MatrixBase<Derived>& m) : MatrixDimension (m.rows (), m.cols ())
259  {}
260 
261  template<typename Derived>
262  MatrixDimension (const ExtendedFloatEigenBase<Derived>& m) : MatrixDimension (m.derived().float_part().rows (), m.derived().float_part().cols ())
263  {}
264 };
265 
267  public MatrixDimension
268 {
270  VectorDimension(Eigen::Index rows_) : MatrixDimension(rows_, Eigen::Index(1))
271  {}
272  VectorDimension(int rows_) : MatrixDimension(rows_, 1)
273  {}
274  VectorDimension(size_t rows_) : MatrixDimension(rows_, (size_t)1)
275  {}
276 };
277 
279  public MatrixDimension
280 {
282  RowVectorDimension(Eigen::Index cols_) : MatrixDimension(Eigen::Index(1), cols_)
283  {}
284  RowVectorDimension(int cols_) : MatrixDimension(1, cols_)
285  {}
286  RowVectorDimension(size_t cols_) : MatrixDimension((size_t)1, cols_)
287  {}
288 };
289 
290 std::string to_string (const MatrixDimension& dim);
291 
292 std::size_t hash (const MatrixDimension& dim);
293 
294 inline bool operator==(const MatrixDimension& lhs, const MatrixDimension& rhs)
295 {
296  return lhs.rows == rhs.rows && lhs.cols == rhs.cols;
297 }
298 inline bool operator!=(const MatrixDimension& lhs, const MatrixDimension& rhs) { return !(lhs == rhs); }
299 
307 template<typename T> struct Dimension;
308 
310 template<> struct Dimension<double> : NoDimension
311 {
312  Dimension () = default;
313  Dimension (const double&)
314  {}
315 };
316 
317 template<> struct Dimension<uint> : NoDimension
318 {
319  Dimension () = default;
320  Dimension (const uint&)
321  {}
322 };
323 
324 template<> struct Dimension<char> : NoDimension
325 {
326  Dimension () = default;
327  Dimension (const char&)
328  {}
329 };
330 
331 template<> struct Dimension<std::string> : NoDimension
332 {
333  Dimension () = default;
334  Dimension (const std::string&)
335  {}
336 };
337 
338 template<> struct Dimension<size_t> : NoDimension
339 {
340  Dimension () = default;
341  Dimension (const size_t&)
342  {}
343 };
344 template<> struct Dimension<float> : NoDimension
345 {
346  Dimension () = default;
347  Dimension (const float&)
348  {}
349 };
350 
351 template<> struct Dimension<ExtendedFloat> : NoDimension
352 {
353  Dimension () = default;
355  {}
356 };
357 
358 template<> struct Dimension<Parameter> : NoDimension
359 {
360  Dimension () = default;
362  {}
363 };
364 
371 template<typename T, int Rows, int Cols> struct Dimension<Eigen::Matrix<T, Rows, Cols>> : MatrixDimension
372 {
373  using MatrixDimension::MatrixDimension; // Have the same constructors as MatrixDimension
375  {} // From MatrixDimension
376 };
377 
378 
379 template< int R, int C, template< int R2 = R, int C2 = C> class EigenType > struct Dimension<ExtendedFloatEigen<R, C, EigenType>> : MatrixDimension
380 {
383  {} // From MatrixDimension
384 };
385 
386 
387 template<> struct Dimension<TransitionFunction> : Dimension<VectorLik>
388 {
389 public:
390  Dimension () = default;
391  Dimension (Eigen::Index rows_) : Dimension<VectorLik>(rows_, (Eigen::Index)1)
392  {}
393 };
394 
395 
396 /******************************************************************************
397  * Collection of overloaded numerical functions.
398  * Not documented with doxygen, as this is only intended for use in dataflow nodes.
399  */
400 namespace numeric
401 {
402 // Error util
403 void checkDimensionIsSquare (const MatrixDimension& dim);
404 
405 // Create a zero value of the given dimension
406 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
407 T zero (const Dimension<T>&)
408 {
409  return T (0);
410 }
411 
412 template<typename T = void>
413 char zero (const Dimension<char>&)
414 {
415  return '0';
416 }
417 
418 template<typename T = void>
419 std::string zero (const Dimension<std::string>&)
420 {
421  return "zero";
422 }
423 
424 template<typename T = void>
426 {
427  return *std::make_shared<Parameter>("Zero", 0);
428 }
429 
430 template<typename T = void>
432 {
433  return ExtendedFloat(0);
434 }
435 
436 template<typename T, int Rows, int Cols>
437 auto zero (const Dimension<Eigen::Matrix<T, Rows, Cols>>& dim)
438 -> decltype (Eigen::Matrix<T, Rows, Cols>::Zero (dim.rows, dim.cols))
439 {
440  return Eigen::Matrix<T, Rows, Cols>::Zero (dim.rows, dim.cols);
441 }
442 
443 template< int R, int C, template< int R2 = R, int C2 = C> class MatType >
445 -> decltype (ExtendedFloatEigen<R, C, MatType>::Zero (dim.rows, dim.cols))
446 {
447  return ExtendedFloatEigen<R, C, MatType>::Zero (dim.rows, dim.cols);
448 }
449 
450 template<typename T = void>
452 {
453  return TransitionFunction([dim](const VectorLik& x){
454  return VectorLik::Zero(dim.cols);
455  });
456 }
457 
458 
459 // Create a one value of the given dimension
460 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
461 T one (const Dimension<T>&)
462 {
463  return T (1);
464 }
465 
466 template<typename T = void>
467 char one (const Dimension<char>&)
468 {
469  return '1';
470 }
471 
472 template<typename T = void>
473 std::string one (const Dimension<std::string>&)
474 {
475  return "one";
476 }
477 
478 template<typename T = void>
480 {
481  return *std::make_shared<Parameter>("One", 1);
482 }
483 
484 template<typename T = void>
486 {
487  return ExtendedFloat(1);
488 }
489 
490 template<typename T, int Rows, int Cols>
491 auto one (const Dimension<Eigen::Matrix<T, Rows, Cols>>& dim)
492 -> decltype (Eigen::Matrix<T, Rows, Cols>::Ones (dim.rows, dim.cols))
493 {
494  return Eigen::Matrix<T, Rows, Cols>::Ones (dim.rows, dim.cols);
495 }
496 
497 template< int R, int C, template< int R2 = 2, int C2 = C> class MatType>
499 -> decltype (ExtendedFloatEigen<R, C, MatType>::Ones (dim.rows, dim.cols))
500 {
501  return ExtendedFloatEigen<R, C, MatType>::Ones (dim.rows, dim.cols);
502 }
503 
504 template<typename T = void>
506 {
507  return TransitionFunction([dim](const VectorLik& x){
508  return VectorLik::Ones(dim.cols);
509  });
510 }
511 
512 // Create an identity value of the given dimension (fails if not a square matrix)
513 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
515 {
516  return T (1); // Equivalent to matrix of size 1x1
517 }
518 
519 template<typename T, typename = typename std::enable_if<std::is_same<T, ExtendedFloat>::value>::type>
521 {
522  return T (1); // Equivalent to matrix of size 1x1
523 }
524 
525 template<typename T, int Rows, int Cols>
526 auto identity (const Dimension<Eigen::Matrix<T, Rows, Cols>>& dim)
527 -> decltype (Eigen::Matrix<T, Rows, Cols>::Identity (dim.rows, dim.cols))
528 {
530  return Eigen::Matrix<T, Rows, Cols>::Identity (dim.rows, dim.cols);
531 }
532 
533 template< int R, int C, template< int R2 = R, int C2 = C> class MatType>
535 -> decltype (ExtendedFloatEigen<R, C, MatType>::Identity (dim.rows))
536 {
539 }
540 
541 
542 // Check if value is Infinity
543 inline bool isinf(const double& d)
544 {
545  return std::isinf(d);
546 }
547 
548 inline bool isinf(const ExtendedFloat& d)
549 {
550  return std::isinf(d.float_part()) || std::isinf(d.exponent_part());
551 }
552 
553 // Check if value is identity itself
554 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value || std::is_same<T, ExtendedFloat>::value>::type>
555 bool isIdentity (const T& t)
556 {
557  return t == T (1);
558 }
559 
560 template<typename T = void>
561 bool isIdentity (const std::string& t)
562 {
563  return t == "Id";
564 }
565 
566 template<typename Derived>
567 bool isIdentity (const Eigen::MatrixBase<Derived>& m)
568 {
569  auto dim = Dimension<Derived>(m.derived ());
570  return dim.rows == dim.cols && m == identity (dim);
571 }
572 
573 template< int R, int C, template< int R2 = R, int C2 = C> class MatType>
575 {
576  return isIdentity(efm.float_part()) && efm.exponent_part() == 0;
577 }
578 
579 
580 /********************************************************/
581 /*** CONVERSI0N ***/
582 
583 /* Convert from F to R (with specific dimension).
584  * scalar -> scalar: simple cast.
585  * scalar -> matrix: fill the matrix with scalar value.
586  * matrix -> matrix: copy values, size must match (conversion between eigen dynamic/fixed)
587  *
588  * Two APIs:
589  * r = convert(f, dim); -> convert returns a "converted" result
590  * convert (r, f, dim); -> convert does the assignment directly
591  */
592 
593 /*************************/
594 /*** From arithmetic ***/
595 
596 template<typename R, typename F, typename = typename std::enable_if<std::is_arithmetic<R>::value || std::is_same<R, ExtendedFloat>::value>::type>
597 R convert (const F& from, const Dimension<R>&)
598 {
599  return R (from); // scalar -> scalar
600 }
601 
602 template<typename T, int Rows, int Cols, typename F,
603  typename = typename std::enable_if<std::is_arithmetic<F>::value>::type>
604 auto convert (const F& from, const Dimension<Eigen::Matrix<T, Rows, Cols>>& dim)
605 -> decltype (Eigen::Matrix<T, Rows, Cols>::Constant (dim.rows, dim.cols, from))
606 {
607  // scalar -> matrix
608  return Eigen::Matrix<T, Rows, Cols>::Constant (dim.rows, dim.cols, from);
609 }
610 
611 template< int R, int C, template< int R2 = R, int C2 = C> class MatType, typename F,
612  typename = typename std::enable_if<std::is_same<F, ExtendedFloat>::value || std::is_arithmetic<F>::value>::type>
613 auto convert (const F& from, const Dimension<ExtendedFloatEigen<R, C, MatType>>& dim)
614 -> decltype (ExtendedFloatEigen<R, C, MatType>::Constant (dim.rows, dim.cols, from))
615 {
616  // scalar -> efmatrix
617  return ExtendedFloatEigen<R, C, MatType>::Constant (dim.rows, dim.cols, from);
618 }
619 
621 {
622  return ConstantTransitionFunction(from, (int)dim.cols);
623 }
624 
625 /**************************************/
627 /**************************************/
628 
629 template<typename T, int R, int C, typename DerivedF>
630 const Eigen::Matrix<T, R, C> convert (const Eigen::MatrixBase<DerivedF>& from,
631  const Dimension<Eigen::Matrix<T, R, C>>& dim,
632  typename std::enable_if<std::is_same<DerivedF, Eigen::RowVectorXi>::value || std::is_same<DerivedF, Eigen::VectorXi>::value>::type* = 0)
633 {
634  return from.derived().template cast<T>(); // matrixXi -> matrix
635 }
636 
637 
638 template< int R, int C, typename DerivedF>
639 const ExtendedFloatMatrix<R, C> convert (const Eigen::MatrixBase<DerivedF>& from,
641  typename std::enable_if<std::is_same<DerivedF, Eigen::RowVectorXi>::value || std::is_same<DerivedF, Eigen::VectorXi>::value>::type* = 0)
642 
643 {
644  return ExtendedFloatMatrix<R, C>(from.derived().template cast<double>(), 0); // matrixXi -> efmatrix
645 }
646 
647 
648 /**************************************/
650 /**************************************/
651 
652 template<typename T, int Rows, int Cols, typename DerivedF>
653 const DerivedF& convert (const Eigen::MatrixBase<DerivedF>& from,
654  const Dimension<Eigen::Matrix<T, Rows, Cols>>& dim,
655  typename std::enable_if<!(std::is_same<DerivedF, Eigen::RowVectorXi>::value || std::is_same<DerivedF, Eigen::VectorXi>::value)>::type* = 0)
656 {
657  return from.derived (); // matrix -> matrix, conversion will be done in the assignment
658 }
659 
660 template< int R, int C, typename DerivedF>
661 const ExtendedFloatMatrix<R, C> convert (const Eigen::MatrixBase<DerivedF>& from,
663  typename std::enable_if<!(std::is_same<DerivedF, Eigen::RowVectorXi>::value || std::is_same<DerivedF, Eigen::VectorXi>::value)>::type* = 0)
664 {
665  return ExtendedFloatMatrix<R, C>(from.derived (), 0); // matrix -> matrix, conversion will be done in the assignment
666 }
667 
668 /**************************************/
670 /**************************************/
671 
672 template< int R, int C, typename DerivedF>
673 const DerivedF& convert (const ExtendedFloatEigenBase<DerivedF>& from,
675 {
676  return from.derived(); // efmatrix -> efmatrix
677 }
678 
679 template< int R, int C>
680 const Eigen::Matrix<double, R, C> convert (const ExtendedFloatMatrix<R, C>& from,
681  const Dimension<Eigen::Matrix<double, R, C>>& dim)
682 {
683  return from.float_part() * constexpr_power<double>(ExtendedFloat::radix, from.exponent_part()); // efmatrix -> matrix
684 }
685 
686 
687 /***********************/
690 template<typename R, typename F>
691 void convert (R& r, const F& from, const Dimension<R>& dim)
692 {
693  r = convert (from, dim);
694 }
695 
696 template<typename R>
697 void convert (R& r, const R& from, const Dimension<R>& dim)
698 {
699  r = R(from);
700 }
701 
702 // template<typename R, typename F>
703 // typename std::enable_if<!((std::is_base_of<R, Eigen::MatrixXd>::value) && (std::is_base_of<F, ExtendedFloatMatrixXd>::value)), const R>::type
704 // convert (const F& from, const Dimension<R>& dim)
705 // {
706 // const R result = convert (from, dim);
707 // return result;
708 // }
709 
710 /*******************************************/
711 /*** Simple operators ***/
712 
713 
714 // 1/x
715 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
716 T inverse (T t)
717 {
718  return T (1) / t;
719 }
720 
722 {
723  return ExtendedFloat{1 / t.float_part(), -t.exponent_part()};
724 }
725 
726 using Eigen::inverse;
727 
728 template<typename Derived>
730 {
731  return Derived(base.derived().float_part().inverse(), -base.derived().exponent_part());
732 }
733 
734 // x^y
735 using Eigen::pow;
736 using std::pow;
737 
738 // log
739 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
740 T log (T t)
741 {
742  return T(std::log(t));
743 }
744 
745 // exp
746 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
747 T exp (T t)
748 {
749  return T(std::exp(t));
750 }
751 
752 // template <typename Derived>
753 // Derived exp (const Eigen::DenseBase<Derived>& T) {
754 // return T.derived().exp();
755 // }
756 using Eigen::exp;
757 
758 /*******************************************/
759 /*** Debug/Output ***/
760 /*******************************************/
761 
762 // Numerical information as text
763 template<typename T>
764 std::string debug (const T& t, typename std::enable_if<std::is_arithmetic<T>::value>::type* = 0)
765 {
766  // For basic arithmetic scalar types, just print the value itself
767  using std::to_string;
768  return "value=" + to_string_with_precision<T>(t, 20);
769 }
770 
771 template<typename T>
772 std::string debug (const Parameter& t)
773 {
774  // For basic arithmetic scalar types, just print the value itself
775  using std::to_string;
776  return "value=" + to_string_with_precision<double>(t.getValue(), 20);
777 }
778 
779 template<typename T = std::string>
780 std::string debug (const std::string& t)
781 {
782  // For basic arithmetic scalar types, just print the value itself
783  return "value=" + t;
784 }
785 
786 template<typename T = ExtendedFloat>
787 std::string debug (const ExtendedFloat& t)
788 {
789  // For basic arithmetic scalar types, just print the value itself
790  return "value=" + to_string(t);
791 }
792 
793 template<typename Derived>
794 std::string debug (const Eigen::MatrixBase<Derived>& m) // , typename std::enable_if<!std::is_same<Derived, Parameter const&>::value>::type* = 0) {
795 // With matrices, check some numeric properties and encode results as text
796 {
797  using std::to_string;
798  const auto dim = Dimension<Derived>(m.derived ());
799  std::string props = "dim=" + to_string (dim) + " props={";
800  const auto zero_value = zero (dim);
801  // Properties on all elements
802  if (m == zero_value)
803  props += "[0]";
804  if (m == one (dim))
805  props += "[1]";
806  if (isIdentity (m))
807  props += "[I]";
808  // Properties on any element
809  if (m.array ().isNaN ().any ())
810  props += "N";
811  if (m.array ().isInf ().any ())
812  props += "i";
813  if ((m.array () == zero_value.array ()).any ())
814  props += "0";
815  if ((m.array () > zero_value.array ()).any ())
816  props += "+";
817  if ((m.array () < zero_value.array ()).any ())
818  props += "-";
819  props += "}";
820  return props;
821 }
822 
823 template<typename Derived>
825 {
826  // For basic arithmetic scalar types, just print the value itself
827  using std::to_string;
828  return debug(m.derived().float_part()) + " 2^ " + debug(m.derived().exponent_part());
829 }
830 
831 template<typename T = TransitionFunction>
832 std::string debug (const TransitionFunction& f) // , typename std::enable_if<!std::is_same<Derived, Parameter const&>::value>::type* = 0) {
833 // With matrices, check some numeric properties and encode results as text
834 {
835  return "TransitionFunction";
836 }
837 
838 /**************************************************/
839 /* HASH */
840 
841 // Hash of numerical value
842 template<typename T>
843 std::size_t hash (T t, typename std::enable_if<std::is_floating_point<T>::value || std::is_integral<T>::value>::type* = 0)
844 {
845  return std::hash<T>{}(t);
846 }
847 
848 inline std::size_t hash (const ExtendedFloat& ef)
849 {
850  std::size_t seed = hash(ef.float_part());
851  combineHash(seed, ef.exponent_part());
852  return seed;
853 }
854 
855 template<typename T = std::string>
856 std::size_t hash (const std::string& t)
857 {
858  return std::hash<std::string>{}(t);
859 }
860 
861 template<typename Derived> std::size_t hash (const Eigen::MatrixBase<Derived>& m)
862 {
863  std::size_t seed = 0;
864  for (Eigen::Index j = 0; j < m.cols (); ++j)
865  {
866  for (Eigen::Index i = 0; i < m.rows (); ++i)
867  {
868  combineHash (seed, m (i, j));
869  }
870  }
871  return seed;
872 }
873 
874 template<typename Derived>
875 std::size_t hash (const ExtendedFloatEigenBase<Derived>& efm)
876 {
877  std::size_t seed = hash(efm.derived().float_part());
878  combineHash(seed, efm.derived().exponent_part());
879  return seed;
880 }
881 } // namespace numeric
882 
883 
884 /******************************************************************************
885  * Data flow nodes for those numerical functions.
886  *
887  * TODO numerical simplification:
888  * add(x,x) -> 2*x ? (and similar for mul, ...)
889  * all deps constant => return constant ?
890  */
891 
892 // Error utils
893 [[noreturn]] void failureDeltaNotDerivable (const std::type_info& contextNodeType);
894 [[noreturn]] void failureNumericalDerivationNotConfigured ();
895 void checkRecreateWithoutDependencies (const std::type_info& contextNodeType, const NodeRefVec& deps);
896 
897 // Type tag to indicate a reduction operation (for +,*,...).
898 template<typename T> struct ReductionOf;
899 
900 // Declaration of all defined nodes, in order of implementation.
901 template<typename T> class ConstantZero;
902 template<typename T> class ConstantOne;
903 template<typename T> class NumericConstant;
904 template<typename T> class NumericMutable;
905 template<typename Result, typename From> class Convert;
906 
907 // Utilities
908 template<typename Predicate> void removeDependenciesIf (NodeRefVec& deps, Predicate p)
909 {
910  auto new_end = std::remove_if (deps.begin (), deps.end (), std::move (p));
911  deps.erase (new_end, deps.end ()); // Truncate vector storage
912 }
913 
942 template<typename T> struct NumericalDependencyTransform
943 {
945  using DepType = T;
947  static const DepType& transform (const DepType& d) { return d; }
948 };
949 
951 template<typename T> struct Transposed;
953 template<typename T> struct NumericalDependencyTransform<Transposed<T>>
954 {
955  // Get DepType by recursion
957 
958  // Perform inner transformation for T, then transpose. Only for Eigen types.
959  static auto transform (const DepType& d)
960  -> decltype (NumericalDependencyTransform<T>::transform (d).transpose ())
961  {
962  return NumericalDependencyTransform<T>::transform (d).transpose ();
963  }
964 };
965 
972 template<typename T> class ConstantZero : public Value<T>
973 {
974 public:
976 
978  static std::shared_ptr<Self> create (Context& c, const Dimension<T>& dim)
979  {
980  return cachedAs<Self>(c, std::make_shared<Self>(dim));
981  }
982 
983  explicit ConstantZero (const Dimension<T>& dim) : Value<T>(NodeRefVec{}), targetDimension_ (dim)
984  {}
985 
986  std::string debugInfo () const override { return "targetDim=" + to_string (targetDimension_); }
987 
988  bool hasNumericalProperty (NumericalProperty prop) const final
989  {
990  switch (prop)
991  {
993  return true;
995  return true;
996  default:
997  return false;
998  }
999  }
1000 
1001  // ConstantZero<T> additional arguments = (targetDimension_).
1002  bool compareAdditionalArguments (const Node_DF& other) const final
1003  {
1004  const auto* derived = dynamic_cast<const Self*>(&other);
1005  return derived != nullptr && targetDimension_ == derived->targetDimension_;
1006  }
1007  std::size_t hashAdditionalArguments () const final { return hash (targetDimension_); }
1008 
1009  NodeRef derive (Context& c, const Node_DF& node) final
1010  {
1011  if (&node == this)
1012  {
1014  }
1015  return this->shared_from_this (); // Return handle to self, as d(0)/dx = 0
1016  }
1017 
1019  {
1020  checkRecreateWithoutDependencies (typeid (Self), deps);
1021  return this->shared_from_this ();
1022  }
1023 
1024 private:
1025  void compute () final
1026  {
1027  using namespace numeric;
1029  }
1030 
1032 };
1033 
1040 template<typename T> class ConstantOne : public Value<T>
1041 {
1042 public:
1044 
1046  static std::shared_ptr<Self> create (Context& c, const Dimension<T>& dim)
1047  {
1048  return cachedAs<Self>(c, std::make_shared<Self>(dim));
1049  }
1050 
1051  explicit ConstantOne (const Dimension<T>& dim) : Value<T>(NodeRefVec{}), targetDimension_ (dim) {}
1052 
1053  std::string debugInfo () const override { return "targetDim=" + to_string (targetDimension_); }
1054 
1055  bool hasNumericalProperty (NumericalProperty prop) const final
1056  {
1057  switch (prop)
1058  {
1060  return true;
1062  return true;
1063  default:
1064  return false;
1065  }
1066  }
1067 
1068  // ConstantOne<T> additional arguments = (targetDimension_).
1069  bool compareAdditionalArguments (const Node_DF& other) const final
1070  {
1071  const auto* derived = dynamic_cast<const Self*>(&other);
1072  return derived != nullptr && targetDimension_ == derived->targetDimension_;
1073  }
1074  std::size_t hashAdditionalArguments () const final { return hash (targetDimension_); }
1075 
1076  NodeRef derive (Context& c, const Node_DF& node) final
1077  {
1078  if (&node == this)
1079  {
1081  }
1083  }
1084 
1086  {
1087  checkRecreateWithoutDependencies (typeid (Self), deps);
1088  return this->shared_from_this ();
1089  }
1090 
1091 private:
1092  void compute () final
1093  {
1094  using namespace numeric;
1096  }
1097 
1099 };
1100 
1108 template<typename T> class NumericConstant : public Value<T>
1109 {
1110 public:
1112 
1114  template<typename ... Args> static std::shared_ptr<Self> create (Context& c, Args&&... args)
1115  {
1116  return cachedAs<Self>(c, std::make_shared<Self>(std::forward<Args>(args)...));
1117  }
1118 
1119  template<typename ... Args>
1120  explicit NumericConstant (Args&&... args) : Value<T>(NodeRefVec{}, std::forward<Args>(args)...)
1121  {
1122  this->makeValid (); // Always valid
1123  }
1124 
1125  std::string debugInfo () const override
1126  {
1127  using namespace numeric;
1128  return debug (this->accessValueConst ());
1129  }
1130 
1131  std::string description() const override
1132  {
1133  using namespace numeric;
1134  return Node_DF::description() + "\n" + debug (this->accessValueConst ());
1135  }
1136 
1137  std::string color () const override
1138  {
1139  return "grey";
1140  }
1141 
1142  bool hasNumericalProperty (NumericalProperty prop) const final
1143  {
1144  using namespace numeric;
1145  const auto& value = this->accessValueConst ();
1146  switch (prop)
1147  {
1149  return true;
1151  return value == zero (Dimension<T>(value));
1153  return value == one (Dimension<T>(value));
1155  return isIdentity (value);
1156  default:
1157  return false;
1158  }
1159  }
1160 
1161  // NumericConstant<T> additional arguments = (value).
1162  bool compareAdditionalArguments (const Node_DF& other) const override
1163  {
1164  const auto* derived = dynamic_cast<const Self*>(&other);
1165  return derived != nullptr && this->accessValueConst () == derived->accessValueConst ();
1166  }
1167 
1168  std::size_t hashAdditionalArguments () const override
1169  {
1170  using namespace numeric;
1171  return hash (this->accessValueConst ());
1172  }
1173 
1174  NodeRef derive (Context& c, const Node_DF& node) final
1175  {
1176  const auto dim = Dimension<T>(this->accessValueConst ());
1177  if (&node == this)
1178  {
1179  return ConstantOne<T>::create (c, dim);
1180  }
1181  return ConstantZero<T>::create (c, dim);
1182  }
1183 
1184  NodeRef recreate (Context&, NodeRefVec&& deps) override
1185  {
1186  checkRecreateWithoutDependencies (typeid (Self), deps);
1187  return this->shared_from_this ();
1188  }
1189 
1190 private:
1191  void compute () final
1192  {
1193  // Constant is valid from construction
1194  failureComputeWasCalled (typeid (*this));
1195  }
1196 };
1197 
1206 template<typename T> class NumericMutable : public Value<T>
1207 {
1208 public:
1210 
1212  template<typename ... Args> static std::shared_ptr<Self> create (Context&, Args&&... args)
1213  {
1214  return std::make_shared<Self>(std::forward<Args>(args)...);
1215  }
1216 
1217  template<typename ... Args>
1218  explicit NumericMutable (Args&&... args) : Value<T>(NodeRefVec{}, std::forward<Args>(args)...)
1219  {
1220  this->makeValid (); // Initial value is valid
1221  }
1222 
1224  void setValue (const T& t)
1225  {
1226  this->modify ([&t](T& v) { v = t; }, true);
1227  }
1228 
1230  void setValue (T&& t)
1231  {
1232  this->modify ([&t](T& v) { v = std::move (t); }, true);
1233  }
1234 
1235  std::string debugInfo () const override
1236  {
1237  using namespace numeric;
1238  return debug (this->accessValueConst ());
1239  }
1240 
1241  std::string description() const override
1242  {
1243  using namespace numeric;
1244  return Node_DF::description() + "\n" + debug (this->accessValueConst ());
1245  }
1246 
1247  NodeRef derive (Context& c, const Node_DF& node) final
1248  {
1249  const auto dim = Dimension<T>(this->accessValueConst ());
1250  if (&node == this)
1251  {
1252  return ConstantOne<T>::create (c, dim);
1253  }
1254  return ConstantZero<T>::create (c, dim);
1255  }
1256 
1258  {
1259  checkRecreateWithoutDependencies (typeid (Self), deps);
1260  return this->shared_from_this ();
1261  }
1262 
1263 private:
1264  void compute () final
1265  {
1266  // Mutable is always valid
1267  failureComputeWasCalled (typeid (*this));
1268  }
1269 };
1270 
1278 template<typename R, typename F> class Convert : public Value<R>
1279 {
1280 public:
1281  using Self = Convert;
1283 
1285  static ValueRef<R> create (Context& c, NodeRefVec&& deps, const Dimension<R>& dim)
1286  {
1287  // Check dependencies
1288  checkDependenciesNotNull (typeid (Self), deps);
1289  checkDependencyVectorSize (typeid (Self), deps, 1);
1290  checkNthDependencyIsValue<DepF>(typeid (Self), deps, 0);
1291  // Select node
1292  if (std::is_same<R, F>::value)
1293  {
1294  return convertRef<Value<R>>(deps[0]);
1295  }
1297  {
1298  return ConstantZero<R>::create (c, dim);
1299  }
1301  {
1302  return ConstantOne<R>::create (c, dim);
1303  }
1304  else
1305  {
1306  return cachedAs<Value<R>>(c, std::make_shared<Self>(std::move (deps), dim));
1307  }
1308  }
1309 
1310  Convert (NodeRefVec&& deps, const Dimension<R>& dim)
1311  : Value<R>(std::move (deps)), targetDimension_ (dim) {}
1312 
1313  std::string debugInfo () const override
1314  {
1315  using namespace numeric;
1316  return debug (this->accessValueConst ()) + " targetDim=" + to_string (targetDimension_);
1317  }
1318 
1319  // Convert<T> additional arguments = ().
1320  bool compareAdditionalArguments (const Node_DF& other) const final
1321  {
1322  return dynamic_cast<const Self*>(&other) != nullptr;
1323  }
1324 
1325  NodeRef derive (Context& c, const Node_DF& node) final
1326  {
1327  if (&node == this)
1328  {
1330  }
1331  return Self::create (c, {this->dependency (0)->derive (c, node)}, targetDimension_);
1332  }
1333 
1334  NodeRef recreate (Context& c, NodeRefVec&& deps) final
1335  {
1336  return Self::create (c, std::move (deps), targetDimension_);
1337  }
1338 
1339 private:
1340  void compute () final
1341  {
1342  using namespace numeric;
1343  auto& result = this->accessValueMutable ();
1344  const auto& arg = accessValueConstCast<DepF>(*this->dependency (0));
1346  }
1347 
1349 };
1350 
1360 template<typename R> class Identity : public Value<R>
1361 {
1362 public:
1363  using Self = Identity;
1364 
1366  static ValueRef<R> create (Context& c, NodeRefVec&& deps, const Dimension<R>& dim, size_t id = 0)
1367  {
1368  // Check dependencies
1369  checkDependenciesNotNull (typeid (Self), deps);
1370  checkDependencyVectorSize (typeid (Self), deps, 1);
1371  checkNthDependencyIsValue<R>(typeid (Self), deps, 0);
1372 
1373  return cachedAs<Value<R>>(c, std::make_shared<Self>(std::move (deps), dim, id));
1374  }
1375 
1376  Identity (NodeRefVec&& deps, const Dimension<R>& dim, size_t id)
1377  : Value<R>(std::move (deps)), targetDimension_ (dim), id_(id) {}
1378 
1379  std::string debugInfo () const override
1380  {
1381  using namespace numeric;
1382  return debug (this->accessValueConst ()) + " id_=" + std::to_string (id_) + " targetDim=" + to_string (targetDimension_);
1383  }
1384 
1385  // Convert<T> additional arguments = ().
1386  bool compareAdditionalArguments (const Node_DF& other) const final
1387  {
1388  auto oself = dynamic_cast<const Self*>(&other);
1389  if (oself == nullptr)
1390  return false;
1391 
1392  return id_ == oself->id_;
1393  }
1394 
1395  NodeRef derive (Context& c, const Node_DF& node) final
1396  {
1397  if (&node == this)
1398  {
1400  }
1401  return Self::create (c, {this->dependency (0)->derive (c, node)}, targetDimension_, id_);
1402  }
1403 
1404  NodeRef recreate (Context& c, NodeRefVec&& deps) final
1405  {
1406  return Self::create (c, std::move (deps), targetDimension_, id_);
1407  }
1408 
1409 private:
1410  void compute () final
1411  {
1412  using namespace numeric;
1413  auto& result = this->accessValueMutable ();
1414  result = accessValueConstCast<R>(*this->dependency (0));
1415  }
1416 
1418 
1419  size_t id_;
1420 };
1421 
1422 // Precompiled instantiations
1423 extern template class ConstantZero<uint>;
1424 extern template class ConstantZero<double>;
1425 extern template class ConstantZero<char>;
1426 extern template class ConstantZero<std::string>;
1427 
1428 extern template class ConstantZero<Parameter>;
1429 extern template class ConstantZero<TransitionFunction>;
1430 
1431 extern template class ConstantZero<Eigen::VectorXd>;
1432 extern template class ConstantZero<Eigen::RowVectorXd>;
1433 extern template class ConstantZero<Eigen::MatrixXd>;
1434 
1435 extern template class ConstantZero<ExtendedFloatVectorXd>;
1436 extern template class ConstantZero<ExtendedFloatRowVectorXd>;
1437 extern template class ConstantZero<ExtendedFloatMatrixXd>;
1438 
1439 
1440 extern template class ConstantOne<uint>;
1441 extern template class ConstantOne<double>;
1442 extern template class ConstantOne<char>;
1443 extern template class ConstantOne<std::string>;
1444 
1445 extern template class ConstantOne<Parameter>;
1446 extern template class ConstantOne<TransitionFunction>;
1447 
1448 extern template class ConstantOne<Eigen::VectorXd>;
1449 extern template class ConstantOne<Eigen::RowVectorXd>;
1450 extern template class ConstantOne<Eigen::MatrixXd>;
1451 
1452 extern template class ConstantOne<ExtendedFloatVectorXd>;
1453 extern template class ConstantOne<ExtendedFloatRowVectorXd>;
1454 extern template class ConstantOne<ExtendedFloatMatrixXd>;
1455 
1456 
1457 extern template class Identity<double>;
1458 extern template class Identity<ExtendedFloatMatrixXd>;
1459 extern template class Identity<Eigen::MatrixXd>;
1460 
1461 
1462 extern template class NumericConstant<uint>;
1463 extern template class NumericConstant<double>;
1464 extern template class NumericConstant<size_t>;
1465 extern template class NumericConstant<std::string>;
1466 
1467 extern template class NumericConstant<ExtendedFloatVectorXd>;
1468 extern template class NumericConstant<ExtendedFloatRowVectorXd>;
1469 extern template class NumericConstant<ExtendedFloatMatrixXd>;
1470 
1471 extern template class NumericConstant<Eigen::VectorXd>;
1472 extern template class NumericConstant<Eigen::RowVectorXd>;
1473 extern template class NumericConstant<Eigen::MatrixXd>;
1474 
1476 
1477 extern template class NumericMutable<uint>;
1478 extern template class NumericMutable<double>;
1479 
1480 extern template class NumericMutable<ExtendedFloatVectorXd>;
1481 extern template class NumericMutable<ExtendedFloatRowVectorXd>;
1482 extern template class NumericMutable<ExtendedFloatMatrixXd>;
1483 
1484 extern template class NumericMutable<Eigen::VectorXd>;
1485 extern template class NumericMutable<Eigen::RowVectorXd>;
1486 extern template class NumericMutable<Eigen::MatrixXd>;
1487 
1488 extern template class Convert<double, double>;
1489 
1490 extern template class Convert<ExtendedFloatVectorXd, double>;
1496 
1497 extern template class Convert<ExtendedFloatRowVectorXd, double>;
1503 
1504 extern template class Convert<ExtendedFloatMatrixXd, double>;
1509 
1510 extern template class Convert<Eigen::VectorXd, double>;
1511 extern template class Convert<Eigen::VectorXd, Eigen::VectorXd>;
1512 extern template class Convert<Eigen::VectorXd, Eigen::VectorXi>;
1514 
1515 extern template class Convert<Eigen::RowVectorXd, double>;
1519 
1520 extern template class Convert<Eigen::MatrixXd, double>;
1521 extern template class Convert<Eigen::MatrixXd, Eigen::MatrixXd>;
1523 } // namespace bpp
1524 #endif // BPP_PHYL_LIKELIHOOD_DATAFLOW_DATAFLOWNUMERIC_H
r = 1 for each component.
ConstantOne(const Dimension< T > &dim)
static std::shared_ptr< Self > create(Context &c, const Dimension< T > &dim)
Build a new ConstantOne node of the given dimension.
Dimension< T > targetDimension_
bool hasNumericalProperty(NumericalProperty prop) const final
Test if the node has the given numerical property.
std::size_t hashAdditionalArguments() const final
Return the hash of node-specific configuration.
NodeRef recreate(Context &, NodeRefVec &&deps) final
Recreate the node with different dependencies.
NodeRef derive(Context &c, const Node_DF &node) final
Returns a node computing d(this_node_expression)/d(node_expression).
void compute() final
Computation implementation.
std::string debugInfo() const override
Node debug info (default = ""): user defined detailed info for DF graph debug.
bool compareAdditionalArguments(const Node_DF &other) const final
Compare node-specific configuration to another.
const VectorLik & operator()(const VectorLik &)
ConstantTransitionFunction(const VectorLik &res)
ConstantTransitionFunction(double val, int row)
r = 0 for each component.
std::size_t hashAdditionalArguments() const final
Return the hash of node-specific configuration.
NodeRef derive(Context &c, const Node_DF &node) final
Returns a node computing d(this_node_expression)/d(node_expression).
std::string debugInfo() const override
Node debug info (default = ""): user defined detailed info for DF graph debug.
bool hasNumericalProperty(NumericalProperty prop) const final
Test if the node has the given numerical property.
NodeRef recreate(Context &, NodeRefVec &&deps) final
Recreate the node with different dependencies.
void compute() final
Computation implementation.
Dimension< T > targetDimension_
static std::shared_ptr< Self > create(Context &c, const Dimension< T > &dim)
Build a new ConstantZero node of the given dimension.
ConstantZero(const Dimension< T > &dim)
bool compareAdditionalArguments(const Node_DF &other) const final
Compare node-specific configuration to another.
Context for dataflow node construction.
Definition: DataFlow.h:527
r = convert(f).
typename NumericalDependencyTransform< F >::DepType DepF
bool compareAdditionalArguments(const Node_DF &other) const final
Compare node-specific configuration to another.
NodeRef derive(Context &c, const Node_DF &node) final
Returns a node computing d(this_node_expression)/d(node_expression).
NodeRef recreate(Context &c, NodeRefVec &&deps) final
Recreate the node with different dependencies.
static ValueRef< R > create(Context &c, NodeRefVec &&deps, const Dimension< R > &dim)
Build a new Convert node with the given output dimensions.
std::string debugInfo() const override
Node debug info (default = ""): user defined detailed info for DF graph debug.
Dimension< R > targetDimension_
Convert(NodeRefVec &&deps, const Dimension< R > &dim)
void compute() final
Computation implementation.
static Self Constant(Eigen::Index rows, Eigen::Index cols, double value)
virtual const ExtType & exponent_part() const
virtual const MatType & float_part() const
static Self Zero(Eigen::Index rows, Eigen::Index cols)
Eigen::Index cols() const
Eigen::Index rows() const
static Self Identity(Eigen::Index rows)
static Self Ones(Eigen::Index rows, Eigen::Index cols)
const FloatType & float_part() const noexcept
Definition: ExtendedFloat.h:88
const ExtType & exponent_part() const noexcept
Definition: ExtendedFloat.h:89
static constexpr int radix
Definition: ExtendedFloat.h:49
static ValueRef< R > create(Context &c, NodeRefVec &&deps, const Dimension< R > &dim, size_t id=0)
Build a new Convert node with the given output dimensions.
NodeRef recreate(Context &c, NodeRefVec &&deps) final
Recreate the node with different dependencies.
NodeRef derive(Context &c, const Node_DF &node) final
Returns a node computing d(this_node_expression)/d(node_expression).
Identity(NodeRefVec &&deps, const Dimension< R > &dim, size_t id)
Dimension< R > targetDimension_
bool compareAdditionalArguments(const Node_DF &other) const final
Compare node-specific configuration to another.
void compute() final
Computation implementation.
std::string debugInfo() const override
Node debug info (default = ""): user defined detailed info for DF graph debug.
Base dataflow Node class.
Definition: DataFlow.h:152
virtual std::string description() const
Node pretty name (default = type name).
Definition: DataFlow.cpp:151
const NodeRef & dependency(std::size_t i) const noexcept
Definition: DataFlow.h:185
void makeValid() noexcept
Definition: DataFlow.h:271
r = constant_value.
bool compareAdditionalArguments(const Node_DF &other) const override
Compare node-specific configuration to another.
NodeRef derive(Context &c, const Node_DF &node) final
Returns a node computing d(this_node_expression)/d(node_expression).
NodeRef recreate(Context &, NodeRefVec &&deps) override
Recreate the node with different dependencies.
bool hasNumericalProperty(NumericalProperty prop) const final
Test if the node has the given numerical property.
std::string debugInfo() const override
Node debug info (default = ""): user defined detailed info for DF graph debug.
std::size_t hashAdditionalArguments() const override
Return the hash of node-specific configuration.
std::string color() const override
void compute() final
Computation implementation.
NumericConstant(Args &&... args)
std::string description() const override
Node pretty name (default = type name).
static std::shared_ptr< Self > create(Context &c, Args &&... args)
Build a new NumericConstant node with T(args...) value.
r = variable_value.
NodeRef recreate(Context &, NodeRefVec &&deps) final
Recreate the node with different dependencies.
std::string debugInfo() const override
Node debug info (default = ""): user defined detailed info for DF graph debug.
void setValue(T &&t)
Setter with invalidation (movable value version).
NodeRef derive(Context &c, const Node_DF &node) final
Returns a node computing d(this_node_expression)/d(node_expression).
static std::shared_ptr< Self > create(Context &, Args &&... args)
Build a new NumericMutable node with T(args...) value.
void compute() final
Computation implementation.
std::string description() const override
Node pretty name (default = type name).
NumericMutable(Args &&... args)
void setValue(const T &t)
Setter with invalidation.
virtual double getValue() const
Abstract Node storing a value of type T.
Definition: DataFlow.h:352
const T & accessValueConst() const noexcept
Raw value access (const).
Definition: DataFlow.h:385
void modify(Callable &&modifier, bool makeValid)
General case for modification of the T object.
Definition: DataFlow.h:405
T & accessValueMutable() noexcept
Definition: DataFlow.h:416
bool isinf(const ExtendedFloat &d)
T identity(const Dimension< T > &)
std::size_t hash(T t, typename std::enable_if< std::is_floating_point< T >::value||std::is_integral< T >::value >::type *=0)
bool isinf(const double &d)
T one(const Dimension< T > &)
TransitionFunction one(const Dimension< TransitionFunction > &dim)
std::string debug(const TransitionFunction &f)
bool isIdentity(const T &t)
TransitionFunction zero(const Dimension< TransitionFunction > &dim)
bool isIdentity(const ExtendedFloatEigen< R, C, MatType > &efm)
void checkDimensionIsSquare(const MatrixDimension &dim)
std::string debug(const T &t, typename std::enable_if< std::is_arithmetic< T >::value >::type *=0)
R convert(const F &from, const Dimension< R > &)
T zero(const Dimension< T > &)
Derived inverse(ExtendedFloatEigenBase< Derived > base)
Defines the basic types of data flow nodes.
void removeDependenciesIf(NodeRefVec &deps, Predicate p)
std::size_t hash(const MatrixDimension &dim)
std::vector< double > Vdouble
NumericConstant< char > NodeX('X')
std::shared_ptr< Value< T > > ValueRef
Shared pointer alias for Value<T>.
Definition: DataFlow.h:84
void checkDependenciesNotNull(const std::type_info &contextNodeType, const NodeRefVec &deps)
Checks that all dependencies are not null, throws if not.
Definition: DataFlow.cpp:103
bool operator!=(const NoDimension &, const NoDimension &)
typename std::enable_if<(std::is_same< eVector, ExtendedFloatRowVectorXd >::value||std::is_same< eVector, ExtendedFloatVectorXd >::value), bool >::type EFoutput
bool operator==(const Matrix< Scalar > &m1, const Matrix< Scalar > &m2)
ExtendedFloatVectorXd VectorLik
Definition: Definitions.h:15
ExtendedFloatRowVectorXd RowLik
Definition: Definitions.h:14
std::string to_string(const NoDimension &)
ExtendedFloatMatrixXd MatrixLik
Definition: Definitions.h:13
ExtendedFloat pow(const ExtendedFloat &ef, double exp)
void checkRecreateWithoutDependencies(const std::type_info &contextNodeType, const NodeRefVec &deps)
typename std::enable_if<(std::is_same< eVector, ExtendedFloatRowVectorXd >::value||std::is_same< eVector, ExtendedFloatVectorXd >::value), bool >::type EFVector
ExtendedFloatRowVector< Eigen::Dynamic > ExtendedFloatRowVectorXd
void failureDeltaNotDerivable(const std::type_info &contextNodeType)
template void copyEigenToBpp(const ExtendedFloatMatrixXd &eigenMatrix, std::vector< std::vector< double >> &bppMatrix)
typename std::enable_if<((std::is_same< bVector, Vdouble >::value||std::is_same< bVector, std::vector< ExtendedFloat > >::value) &&(std::is_same< eVector, Eigen::RowVectorXd >::value||std::is_same< eVector, Eigen::VectorXd >::value)), bool >::type ForConvert
std::vector< NodeRef > NodeRefVec
Alias for a dependency vector (of NodeRef).
Definition: DataFlow.h:81
template void copyBppToEigen(const std::vector< ExtendedFloat > &bppVector, Eigen::RowVectorXd &eigenVector)
NumericalProperty
Numerical properties for DF Node.
Definition: DataFlow.h:88
double convert(const bpp::ExtendedFloat &ef)
void checkDependencyVectorSize(const std::type_info &contextNodeType, const NodeRefVec &deps, std::size_t expectedSize)
Definition: DataFlow.cpp:83
void combineHash(std::size_t &seed, const T &t)
Combine hashable value to a hash, from Boost library.
Definition: DataFlow.h:33
void failureNumericalDerivationNotConfigured()
void failureComputeWasCalled(const std::type_info &nodeType)
Definition: DataFlow.cpp:51
std::shared_ptr< Node_DF > NodeRef
Definition: DataFlow.h:78
std::function< VectorLik(const VectorLik &)> TransitionFunction
ExtendedFloatMatrix< Eigen::Dynamic, Eigen::Dynamic > ExtendedFloatMatrixXd
ExtendedFloatVector< Eigen::Dynamic > ExtendedFloatVectorXd
typename std::enable_if<((std::is_same< bVector, Vdouble >::value||std::is_same< bVector, std::vector< ExtendedFloat > >::value) &&(std::is_same< eVector, Eigen::RowVectorXd >::value||std::is_same< eVector, Eigen::VectorXd >::value||std::is_same< eVector, ExtendedFloatVectorXd >::value||std::is_same< eVector, ExtendedFloatRowVectorXd >::value)), bool >::type ForConvert2
Dimension(const ExtendedFloat &)
Dimension(const Parameter &)
Dimension(const std::string &)
Store a dimension for type T.
Basic matrix dimension type.
MatrixDimension(const ExtendedFloatEigenBase< Derived > &m)
MatrixDimension(Eigen::Index rows_, Eigen::Index cols_)
MatrixDimension(int rows_, int cols_)
MatrixDimension(size_t rows_, size_t cols_)
MatrixDimension()=default
MatrixDimension(const Eigen::MatrixBase< Derived > &m)
Empty type representing no dimensions.
typename NumericalDependencyTransform< T >::DepType DepType
static auto transform(const DepType &d) -> decltype(NumericalDependencyTransform< T >::transform(d).transpose())
Template struct used to describe a dependency transformation before compute().
T DepType
Real type of the dependency: T in the default case.
static const DepType & transform(const DepType &d)
Transform the DepType value: do nothing in the default case.
RowVectorDimension(Eigen::Index cols_)
RowVectorDimension(size_t cols_)
The T dependency should be transposed before computation.
VectorDimension(Eigen::Index rows_)
VectorDimension(size_t rows_)