11 #include <Eigen/Dense>
28 template<
bool B,
class T =
void >
55 template<
typename T,
typename ...Args>
58 return std::unique_ptr<T>(
new T(std::forward<Args>(args)...));
71 template<
typename Derived>
74 double max =
static_cast<double>(data.maxCoeff());
76 return max + std::log(
static_cast<double>((data.array() - max).exp().sum()));
98 template<typename Derived, typename DerivedScalar = typename Derived::Scalar, bfl::utils::enable_if_t<std::is_floating_point<DerivedScalar>::value,
bool> =
true>
101 Eigen::Matrix<DerivedScalar, 3, Eigen::Dynamic> rotation_vectors(3, quaternion.cols());
103 for (std::size_t i = 0; i < quaternion.cols(); ++i)
105 const DerivedScalar norm_n = quaternion.col(i).tail(3).norm();
108 const DerivedScalar w = quaternion.col(i)(0);
110 rotation_vectors.col(i) = - 2.0 * std::acos(-w) * quaternion.col(i).tail(3) / norm_n;
112 rotation_vectors.col(i) = 2.0 * std::acos(w) * quaternion.col(i).tail(3) / norm_n;
115 rotation_vectors.col(i) = Eigen::Matrix<DerivedScalar, 3, 1>::Zero();
118 return rotation_vectors;
138 template<typename Derived, typename DerivedScalar = typename Derived::Scalar, bfl::utils::enable_if_t<std::is_floating_point<DerivedScalar>::value,
bool> =
true>
141 Eigen::Matrix<DerivedScalar, 4, Eigen::Dynamic> quaternions(4, rotation_vector.cols());
142 for (std::size_t i = 0; i < rotation_vector.cols(); ++i)
144 const DerivedScalar norm_r = rotation_vector.col(i).norm();
147 quaternions.col(i)(0) = std::cos(norm_r / 2.0);
148 quaternions.col(i).tail(3) = std::sin(norm_r / 2.0) * rotation_vector.col(i) / norm_r;
152 quaternions.col(i)(0) = 1.0;
153 quaternions.col(i).tail(3) = Eigen::Matrix<DerivedScalar, 3, 1>::Zero();
182 template<
typename Derived,
typename DerivedArg2,
typename DerivedScalar =
typename Derived::Scalar,
typename DerivedArg2Scalar =
typename DerivedArg2::Scalar,
184 Eigen::Matrix<DerivedScalar, 4, Eigen::Dynamic>
sum_quaternion_rotation_vector(
const Eigen::MatrixBase<Derived>& quaternion,
const Eigen::MatrixBase<DerivedArg2>& rotation_vector)
189 Eigen::Quaternion<DerivedScalar> q_right(quaternion.col(0)(0), quaternion.col(0)(1), quaternion.col(0)(2), quaternion.col(0)(3));
191 Eigen::Matrix<DerivedScalar, 4, Eigen::Dynamic> quaternions(4, rotation_vector.cols());
192 for (std::size_t i = 0; i < rotation_vector.cols(); ++i)
194 Eigen::Quaternion<DerivedScalar> q_left(vector_as_quaternion.col(i)(0), vector_as_quaternion.col(i)(1), vector_as_quaternion.col(i)(2), vector_as_quaternion.col(i)(3));
195 Eigen::Quaternion<DerivedScalar> sum = q_left * q_right;
197 quaternions.col(i)(0) = sum.w();
198 quaternions.col(i).tail(3) = sum.vec();
225 template<
typename Derived,
typename DerivedArg2,
typename DerivedScalar =
typename Derived::Scalar,
typename DerivedArg2Scalar =
typename DerivedArg2::Scalar,
227 Eigen::Matrix<DerivedScalar, 3, Eigen::Dynamic>
diff_quaternion(
const Eigen::MatrixBase<Derived>& quaternion_left,
const Eigen::MatrixBase<DerivedArg2>& quaternion_right)
229 Eigen::Matrix<DerivedScalar, 4, Eigen::Dynamic> products(4, quaternion_left.cols());
231 Eigen::Quaternion<DerivedScalar> q_right(quaternion_right.col(0)(0), quaternion_right.col(0)(1), quaternion_right.col(0)(2), quaternion_right.col(0)(3));
232 Eigen::Quaternion<DerivedScalar> q_right_conj = q_right.conjugate();
235 for (std::size_t i = 0; i < quaternion_left.cols(); ++i)
237 Eigen::Quaternion<DerivedScalar> q_left(quaternion_left.col(i)(0), quaternion_left.col(i)(1), quaternion_left.col(i)(2), quaternion_left.col(i)(3));
238 Eigen::Quaternion<DerivedScalar> product = q_left * q_right_conj;
240 products.col(i)(0) = product.w();
241 products.col(i).tail(3) = product.vec();
269 template<
typename Derived,
typename DerivedArg2,
typename DerivedScalar =
typename Derived::Scalar,
typename DerivedArg2Scalar =
typename DerivedArg2::Scalar,
271 Eigen::Matrix<DerivedScalar, 4, 1>
mean_quaternion(
const Eigen::MatrixBase<Derived>& weight,
const Eigen::MatrixBase<DerivedArg2>& quaternion)
274 Eigen::Matrix<DerivedScalar, 4, 4> outer_product_mean = Eigen::Matrix<DerivedScalar, 4, 4>::Zero();
275 for (std::size_t i = 0; i < weight.rows(); ++i)
276 outer_product_mean.noalias() += weight.col(0)(i) * quaternion.col(i) * quaternion.col(i).transpose();
279 Eigen::EigenSolver<Eigen::Matrix<DerivedScalar, 4, 4>> eigen_solver(outer_product_mean);
280 Eigen::Matrix<std::complex<DerivedScalar>, 4, 1> eigenvalues(eigen_solver.eigenvalues());
282 eigenvalues.real().maxCoeff(&maximum_index);
283 return eigen_solver.eigenvectors().real().block(0, maximum_index, 4, 1);
296 template<
typename Derived>
297 Eigen::VectorXd
multivariate_gaussian_log_density(
const Eigen::MatrixBase<Derived>& input,
const Eigen::Ref<const Eigen::VectorXd>& mean,
const Eigen::Ref<const Eigen::MatrixXd>& covariance)
299 const auto diff = input.colwise() - mean;
301 Eigen::VectorXd values(diff.cols());
302 for (std::size_t i = 0; i < diff.cols(); i++)
303 values(i) = - 0.5 * (
static_cast<double>(diff.rows()) * std::log(2.0 * M_PI) + std::log(covariance.determinant()) + (diff.col(i).transpose() * covariance.inverse() * diff.col(i)));
330 template<
typename Derived>
331 Eigen::VectorXd
multivariate_gaussian_log_density_UVR(
const Eigen::MatrixBase<Derived>& input,
const Eigen::Ref<const Eigen::VectorXd>& mean,
const Eigen::Ref<const Eigen::MatrixXd>& U,
const Eigen::Ref<const Eigen::MatrixXd>& V,
const Eigen::Ref<const Eigen::MatrixXd>& R)
333 std::size_t input_size = input.rows();
334 std::size_t block_size = R.rows();
335 std::size_t num_blocks = input_size / block_size;
337 const auto diff = input.colwise() - mean;
340 Eigen::MatrixXd inv_R(block_size, input_size);
341 if (R.cols() == block_size)
344 Eigen::MatrixXd inv_R_single = R.inverse();
345 for (std::size_t i = 0; i < num_blocks; i++)
347 inv_R.block(0, block_size * i, block_size, block_size) = inv_R_single;
353 for (std::size_t i = 0; i < num_blocks; i++)
355 inv_R.block(0, block_size * i, block_size, block_size) = R.block(0, block_size * i, block_size, block_size).inverse();
360 Eigen::MatrixXd V_inv_R(V.rows(), V.cols());
361 for (std::size_t i = 0; i < V.cols() / block_size; i++)
363 V_inv_R.middleCols(i * block_size, block_size) = V.middleCols(i * block_size, block_size) * inv_R.block(0, block_size * i, block_size, block_size);
367 Eigen::MatrixXd diff_T_inv_R(input.cols(), input.rows());
368 for (std::size_t i = 0; i < num_blocks; i++)
370 diff_T_inv_R.middleCols(i * block_size, block_size) = diff.middleRows(i * block_size, block_size).transpose() * inv_R.block(0, block_size * i, block_size, block_size);
374 Eigen::MatrixXd I_V_inv_R_U = Eigen::MatrixXd::Identity(V.rows(), V.rows()) + V_inv_R * U;
381 Eigen::VectorXd weighted_diffs(input.cols());
382 for (std::size_t i = 0; i < weighted_diffs.size(); i++)
383 weighted_diffs(i) = diff_T_inv_R.row(i) * (Eigen::MatrixXd::Identity(U.rows(), U.rows()) - U * I_V_inv_R_U.inverse() * V_inv_R) * diff.col(i);
392 if (R.cols() == block_size)
393 det_R = std::pow(R.determinant(), num_blocks);
395 for (std::size_t i = 0; i < num_blocks; i++)
396 det_R *= R.block(0, block_size * i, block_size, block_size).determinant();
398 det_S = det_R * I_V_inv_R_U.determinant();
401 Eigen::VectorXd values(input.cols());
402 for (std::size_t i = 0; i < input.cols(); i++)
403 values(i) = - 0.5 * (
static_cast<double>(diff.rows()) * std::log(2.0 * M_PI) + std::log(det_S) + weighted_diffs(i));
418 template<
typename Derived>
419 Eigen::VectorXd
multivariate_gaussian_density(
const Eigen::MatrixBase<Derived>& input,
const Eigen::Ref<const Eigen::VectorXd>& mean,
const Eigen::Ref<const Eigen::MatrixXd>& covariance)
446 template<
typename Derived>
447 Eigen::VectorXd
multivariate_gaussian_density_UVR(
const Eigen::MatrixBase<Derived>& input,
const Eigen::Ref<const Eigen::VectorXd>& mean,
const Eigen::Ref<const Eigen::MatrixXd>& U,
const Eigen::Ref<const Eigen::MatrixXd>& V,
const Eigen::Ref<const Eigen::MatrixXd>& R)
462 template<
typename timetype = std::chrono::milliseconds>
482 stop_time_ = std::chrono::steady_clock::now();
496 std::chrono::steady_clock::duration time_span;
501 time_span = std::chrono::steady_clock::now() -
start_time_;
503 return static_cast<double>(time_span.count()) * std::chrono::steady_clock::period::num / std::chrono::steady_clock::period::den * timetype::period::den;
514 return static_cast<double>(std::chrono::steady_clock::now().time_since_epoch().count()) * std::chrono::steady_clock::period::num / std::chrono::steady_clock::period::den * timetype::period::den;
532 std::chrono::steady_clock::time_point
start_time_ = std::chrono::steady_clock::now();
558 inline std::string
throw_message(
const std::string& from_where,
const std::string& error_message,
const std::string& data_log =
"")
560 if (from_where.empty() || error_message.empty())
561 return "UTILS::THROW_MESSAGE::EMPTY_THROW_REPORT";
565 message =
"ERROR::" + from_where +
"\n";
566 message +=
"MESSAGE:\n";
567 message +=
"\t" + error_message +
"\n";
569 if (!data_log.empty())
572 message +=
"\t" + data_log +
"\n";