Program Listing for File factory.hpp

Return to documentation for file (src/navtk/factory.hpp)

#pragma once

#include <xtensor/core/xmath.hpp>

#include <navtk/inspect.hpp>
#include <navtk/tensors.hpp>

namespace navtk {

template <class T, IfTensorOfDim<T, 0>* = nullptr>
Vector to_vec(const T& m) {
    if (has_zero_size(m)) return Vector{};
    return Vector{m()};
}

#ifndef NEED_DOXYGEN_EXHALE_WORKAROUND
template <class T, IfTensorOfDim<T, 1>* = nullptr>
Vector to_vec(const T& m) {
    return m;
}

template <class T, IfTensorOfDim<T, 2>* = nullptr>
Vector to_vec(const T& m) {
    if (has_zero_size(m)) {
        return Vector{};
    } else if (m.shape()[0] == 1 && m.shape()[1] == 1) {
        return Tensor<1>{m(0, 0)};
    } else if (m.shape()[0] == 1 || m.shape()[1] == 1) {
        return xt::squeeze(m);
    }

    // Combine data from all rows into one row
    return xt::flatten(m);
}

template <class T, IfTensorOfDim<T, 3>* = nullptr>
Vector to_vec(const T& m) {
    if (has_zero_size(m)) {
        return Vector{};
    } else if (m.shape()[0] == 1 && m.shape()[1] == 1 && m.shape()[2] == 1) {
        return Tensor<1>{m(0, 0, 0)};
    }

    // if there is at least one dimmension that is not being used
    if (m.shape()[0] == 1 || m.shape()[1] == 1 || m.shape()[2] == 1) {
        auto squeezed = xt::squeeze(m);
        if (squeezed.dimension() == 1) {
            return squeezed;
        } else if (squeezed.dimension() == 2) {
            return xt::flatten(squeezed);
        }
    }

    return xt::flatten(m);
}

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;
}
#endif

template <class T, IfTensorOfDim<T, 0>* = nullptr>
Matrix to_matrix(const T& m, std::size_t = 1) {
    if (has_zero_size(m)) return Matrix{};
    return Matrix{{m()}};
}

#ifndef NEED_DOXYGEN_EXHALE_WORKAROUND
template <class T, IfTensorOfDim<T, 1>* = nullptr>
Matrix to_matrix(const T& m, std::size_t axis = 1) {
    return xt::expand_dims(m, axis);
}

template <class T, IfTensorOfDim<T, 2>* = nullptr>
Matrix to_matrix(const T& m, std::size_t = 1) {
    return m;
}

template <class T, IfTensorOfDim<T, 3>* = nullptr>
Matrix to_matrix(const T& m, std::size_t axis = 1) {
    if (has_zero_size(m)) {
        return Matrix{};
    }

    if (m.shape()[0] == 1 && m.shape()[1] == 1 && m.shape()[2] == 1) {
        return Tensor<2>{{m(0, 0, 0)}};
    }

    if (m.shape()[0] == 1 || m.shape()[1] == 1 || m.shape()[2] == 1) {
        auto squeezed = xt::squeeze(m);
        if (squeezed.dimension() == 1) {
            return xt::expand_dims(squeezed, axis);
        } else if (squeezed.dimension() == 2) {
            return squeezed;
        }
    }

    auto flattened = xt::flatten(m);

    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;
}
#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)> 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