Program Listing for File factory.hpp
↰ Return to documentation for file (src/navtk/factory.hpp)
#pragma once
#include <type_traits>
#include <xtensor/core/xexpression.hpp>
#include <xtensor/core/xmath.hpp>
#include <xtensor/views/xbroadcast.hpp>
#include <navtk/inspect.hpp>
#include <navtk/tensors.hpp>
namespace navtk {
template <class T, IfTensorOfDim<T, 1>* = nullptr>
inline Vector to_vec(const T& m) {
if constexpr (xt::is_xexpression<T>::value == true) {
return m;
} else {
return Vector(m);
}
}
template <class T, IfTensorOfDim<T, 2>* = nullptr>
inline Matrix to_matrix(const T& m, std::size_t = 1) {
if constexpr (xt::is_xexpression<T>::value == true) {
return m;
} else {
return Matrix(m);
}
}
template <class T, IfTensorOfDim<T, 3>* = nullptr>
inline Tensor<3> to_tensor_3d(const T& m, std::size_t = 1) {
if constexpr (xt::is_xexpression<T>::value == true) {
return m;
} else {
return Tensor<3>(m);
}
}
#ifndef NEED_DOXYGEN_EXHALE_WORKAROUND
template <class T, IfTensorOfDim<T, 0>* = nullptr>
inline Vector to_vec(const T& m) {
if constexpr (std::ranges::range<T>) {
if (has_zero_size(m)) return Vector{};
return Vector{m()};
} else if constexpr (std::is_arithmetic<T>::value == true) {
return Vector({m});
} else {
return Vector{m()};
}
}
template <class T, IfTensorOfDim<T, 2>* = nullptr>
Vector to_vec(const T& m) {
auto mat = to_matrix(m);
if (has_zero_size(mat)) {
return Vector{};
} else if (mat.shape()[0] == 1 && mat.shape()[1] == 1) {
return Tensor<1>{mat(0, 0)};
} else if (mat.shape()[0] == 1 || mat.shape()[1] == 1) {
return xt::squeeze(mat);
}
// Combine data from all rows into one row
return xt::flatten(mat);
}
template <class T, IfTensorOfDim<T, 3>* = nullptr>
Vector to_vec(const T& m) {
auto tensor = to_tensor_3d(m);
if (has_zero_size(tensor)) {
return Vector{};
} else if (tensor.shape()[0] == 1 && tensor.shape()[1] == 1 && tensor.shape()[2] == 1) {
return Tensor<1>{tensor(0, 0, 0)};
}
// if there is at least one dimmension that is not being used
if (tensor.shape()[0] == 1 || tensor.shape()[1] == 1 || tensor.shape()[2] == 1) {
auto squeezed = xt::squeeze(tensor);
if (squeezed.dimension() == 1) {
return squeezed;
} else if (squeezed.dimension() == 2) {
return xt::flatten(squeezed);
}
}
return xt::flatten(tensor);
}
template <typename T, IfEigenInterface<T>* = nullptr>
Vector to_vec(const T& m) {
// TODO: PNTOS-56 Instead, could attempt to block memory copy if we can determine memory layout
// of m
auto rows = m.rows();
auto cols = m.cols();
Vector out = xt::zeros<Scalar>({rows * cols});
for (decltype(rows) i = 0; i < rows; i++) {
for (decltype(cols) j = 0; j < cols; j++) {
out(i * cols + j) = m(i, j);
}
}
return out;
}
template <class T, IfTensorOfDim<T, 0>* = nullptr>
inline Matrix to_matrix(const T& m, std::size_t = 1) {
if constexpr (std::ranges::range<T>) {
if (has_zero_size(m)) return Matrix{};
return Matrix{{m()}};
} else if constexpr (std::is_arithmetic<T>::value == true) {
return Matrix{{m}};
} else {
return Matrix{{m()}};
}
}
template <class T, IfTensorOfDim<T, 1>* = nullptr>
Matrix to_matrix(const T& m, std::size_t axis = 1) {
auto vec = to_vec(m);
return xt::expand_dims(vec, axis);
}
template <class T, IfTensorOfDim<T, 3>* = nullptr>
Matrix to_matrix(const T& m, std::size_t axis = 1) {
auto tensor = to_tensor_3d(m);
if (has_zero_size(tensor)) {
return Matrix{};
}
if (tensor.shape()[0] == 1 && tensor.shape()[1] == 1 && tensor.shape()[2] == 1) {
return Tensor<2>{{tensor(0, 0, 0)}};
}
if (tensor.shape()[0] == 1 || tensor.shape()[1] == 1 || tensor.shape()[2] == 1) {
auto squeezed = xt::squeeze(tensor);
if (squeezed.dimension() == 1) {
return xt::expand_dims(squeezed, axis);
} else if (squeezed.dimension() == 2) {
return squeezed;
}
}
auto flattened = xt::flatten(tensor);
return xt::expand_dims(flattened, axis);
}
template <typename T, IfEigenInterface<T>* = nullptr>
Matrix to_matrix(const T& m, std::size_t = 1) {
// TODO: PNTOS-56 Instead, could attempt to block memory copy if we can determine memory layout
// of m
auto rows = m.rows();
auto cols = m.cols();
Matrix out = xt::zeros<Scalar>({rows, cols});
for (decltype(rows) i = 0; i < rows; i++) {
for (decltype(cols) j = 0; j < cols; j++) {
out(i, j) = m(i, j);
}
}
return out;
}
template <typename T, std::size_t rows, std::size_t cols>
Matrix to_matrix(T (&data)[rows][cols]) {
Matrix out = xt::zeros<Scalar>({rows, cols});
for (Size ii = 0; ii < rows; ++ii)
for (Size jj = 0; jj < cols; ++jj) out(ii, jj) = data[ii][jj];
return out;
}
template <class T, IfTensorOfDim<T, 0>* = nullptr>
inline Tensor<3> to_tensor_3d(const T& m, std::size_t = 1) {
if constexpr (xt::is_xexpression<T>::value == true) {
if (has_zero_size(m)) return Tensor<3>{};
return Tensor<3>{{{m()}}};
} else if constexpr (std::is_arithmetic<T>::value == true) {
return Tensor<3>{{{m}}};
} else {
return Tensor<3>{{{m()}}};
}
}
template <class T, IfTensorOfDim<T, 1>* = nullptr>
Tensor<3> to_tensor_3d(const T& m, std::size_t axis = 2) {
auto vec = to_vec(m);
const size_t N = vec.shape()[0];
std::array<size_t, 3> shape = {1, 1, 1};
shape[axis] = N;
return xt::reshape_view(vec, shape);
}
template <class T, IfTensorOfDim<T, 2>* = nullptr>
Tensor<3> to_tensor_3d(const T& m, std::size_t axis = 0) {
auto mat = to_matrix(m);
return xt::expand_dims(mat, axis);
}
template <typename T, std::size_t index, std::size_t rows, std::size_t cols>
Tensor<3> to_tensor_3d(T (&data)[index][rows][cols]) {
auto out = xt::zeros<Scalar>({index, rows, cols});
for (Size ii = 0; ii < index; ++ii)
for (Size jj = 0; jj < rows; ++jj)
for (Size kk = 0; kk < cols; ++kk) out(ii, jj, kk) = data[ii][jj][kk];
return out;
}
#endif
Matrix eye(Size rows, Size cols, int diagonal_index = 0);
Matrix eye(Size size);
#ifndef NEED_DOXYGEN_EXHALE_WORKAROUND
template <typename... T>
Tensor<sizeof...(T)> empty(T... dim) {
using tensor_shape_type = typename Tensor<sizeof...(T)>::shape_type::value_type;
return Tensor<sizeof...(T)>::from_shape({static_cast<tensor_shape_type>(dim)...});
}
template <typename... T>
Tensor<sizeof...(T)> zeros(T... dim) {
return xt::zeros<Scalar>({Size(dim)...});
}
template <typename... T>
Tensor<sizeof...(T)> fill(Scalar value, T... dim) {
return zeros(dim...) + value;
}
template <typename... T>
Tensor<sizeof...(T)> ones(T... dim) {
return xt::ones<Scalar>({Size(dim)...});
}
#endif
Matrix block_diag(std::initializer_list<Matrix> matrices);
template <typename... T>
Matrix block_diag(T&&... matrices) {
return block_diag({to_matrix(matrices, 0)...});
}
} // namespace navtk