Commit f44e6d09 by Maarten L. Hekkelman

backup of documentation

parent d496ebf6
......@@ -262,8 +262,8 @@ class condition
return m_impl ? m_impl->single() : std::optional<row_handle>();
}
friend condition operator||(condition &&a, condition &&b); /**< Operator OR */
friend condition operator&&(condition &&a, condition &&b); /**< Operator AND */
friend condition operator||(condition &&a, condition &&b); /**< Return a condition which is the logical OR or condition @a and @b */
friend condition operator&&(condition &&a, condition &&b); /**< Return a condition which is the logical AND or condition @a and @b */
/// @cond
friend struct detail::or_condition_impl;
......
......@@ -30,22 +30,46 @@
#include <array>
/**
* @file iterator.hpp
*
* This file contains several implementations of generic iterators.
*
* Using partial specialization we can have implementation for
* iterators that return row_handles, a single value or tuples of
* multiple values.
*
*/
namespace cif
{
// --------------------------------------------------------------------
/**
* @brief Implementation of an iterator that can return
* multiple values in a tuple. Of course, that tuple can
* then used in structured binding to receive the values
* in a for loop e.g.
*
* @tparam Category The category for this iterator
* @tparam Ts The types this iterator can be dereferenced to
*/
template <typename Category, typename... Ts>
class iterator_impl
{
public:
/** @cond */
template <typename, typename...>
friend class iterator_impl;
friend class category;
/** @endcond */
/** variable that contains the number of elements in the tuple */
static constexpr size_t N = sizeof...(Ts);
/** @cond */
using category_type = std::remove_cv_t<Category>;
using row_type = std::conditional_t<std::is_const_v<Category>, const row, row>;
......@@ -152,14 +176,16 @@ class iterator_impl
return m_current != rhs.m_current;
}
/** @endcond */
private:
template <size_t... Is>
tuple_type get(std::index_sequence<Is...>) const
{
if (m_current != nullptr)
{
row_handle rh{*m_category, *m_current};
return tuple_type{rh[m_column_ix[Is]].template as<Ts>()...};
row_handle rh{ *m_category, *m_current };
return tuple_type{ rh[m_column_ix[Is]].template as<Ts>()... };
}
return {};
......@@ -171,10 +197,18 @@ class iterator_impl
std::array<uint16_t, N> m_column_ix;
};
template<typename Category>
/**
* @brief Implementation of an iterator that returns
* only row_handles
*
* @tparam Category The category for this iterator
*/
template <typename Category>
class iterator_impl<Category>
{
public:
/** @cond */
template <typename, typename...>
friend class iterator_impl;
......@@ -195,7 +229,7 @@ class iterator_impl<Category>
template <typename C2>
iterator_impl(const iterator_impl<C2> &rhs)
: m_category(rhs.m_category)
, m_current(const_cast<row_type*>(rhs.m_current))
, m_current(const_cast<row_type *>(rhs.m_current))
{
}
......@@ -223,7 +257,7 @@ class iterator_impl<Category>
reference operator*()
{
return {*m_category, *m_current};
return { *m_category, *m_current };
}
pointer operator->()
......@@ -271,16 +305,26 @@ class iterator_impl<Category>
return m_current != rhs.m_current;
}
/** @endcond */
private:
category_type *m_category = nullptr;
row_type *m_current = nullptr;
};
/**
* @brief Implementation of an iterator that can return
* a single value.
*
* @tparam Category The category for this iterator
* @tparam T The type this iterator can be dereferenced to
*/
template<typename Category, typename T>
template <typename Category, typename T>
class iterator_impl<Category, T>
{
public:
/** @cond */
template <typename, typename...>
friend class iterator_impl;
......@@ -390,12 +434,14 @@ class iterator_impl<Category, T>
return m_current != rhs.m_current;
}
/** @endcond */
private:
value_type get() const
{
if (m_current != nullptr)
{
row_handle rh{*m_category, *m_current};
row_handle rh{ *m_category, *m_current };
return rh[m_column_ix].template as<T>();
}
......@@ -411,10 +457,23 @@ class iterator_impl<Category, T>
// --------------------------------------------------------------------
// iterator proxy
/**
* @brief An iterator_proxy is used as a result type for methods that
* return a range of values you want to iterate over.
*
* E.g. the class cif::category contains the method cif::category::rows()
* that returns an iterator_proxy that allows you to iterate over
* all the rows in the category.
*
* @tparam Category The category for the iterators
* @tparam Ts The types the iterators return. See class: iterator
*/
template <typename Category, typename... Ts>
class iterator_proxy
{
public:
/** @cond */
static constexpr const size_t N = sizeof...(Ts);
using category_type = Category;
......@@ -431,21 +490,21 @@ class iterator_proxy
iterator_proxy(const iterator_proxy &) = delete;
iterator_proxy &operator=(const iterator_proxy &) = delete;
/** @endcond */
iterator begin() const { return iterator(m_begin, m_column_ix); }
iterator end() const { return iterator(m_end, m_column_ix); }
iterator begin() const { return iterator(m_begin, m_column_ix); } ///< Return the iterator pointing to the first row
iterator end() const { return iterator(m_end, m_column_ix); } ///< Return the iterator pointing past the last row
bool empty() const { return m_begin == m_end; }
explicit operator bool() const { return not empty(); }
size_t size() const { return std::distance(begin(), end()); }
bool empty() const { return m_begin == m_end; } ///< Return true if the range is empty
explicit operator bool() const { return not empty(); } ///< Easy way to detect if the range is empty
size_t size() const { return std::distance(begin(), end()); } ///< Return size of the range
// row front() { return *begin(); }
// row back() { return *(std::prev(end())); }
category_type &category() const { return *m_category; }
category_type &category() const { return *m_category; } ///< Return the category the iterator belong to
/** swap */
void swap(iterator_proxy &rhs)
{
std::swap(m_category, rhs.m_category);
......@@ -463,10 +522,20 @@ class iterator_proxy
// --------------------------------------------------------------------
// conditional iterator proxy
/**
* @brief A conditional iterator proxy is similar to an iterator_proxy
* in that it can be used to return a range of rows you can iterate over.
* In the case of an conditional_iterator_proxy a cif::condition is used
* to filter out only those rows that match the condition.
*
* @tparam CategoryType The category the iterators belong to
* @tparam Ts The types to which the iterators can be dereferenced
*/
template <typename CategoryType, typename... Ts>
class conditional_iterator_proxy
{
public:
/** @cond */
static constexpr const size_t N = sizeof...(Ts);
using category_type = std::remove_cv_t<CategoryType>;
......@@ -549,20 +618,21 @@ class conditional_iterator_proxy
conditional_iterator_proxy(const conditional_iterator_proxy &) = delete;
conditional_iterator_proxy &operator=(const conditional_iterator_proxy &) = delete;
iterator begin() const;
iterator end() const;
bool empty() const;
/** @endcond */
explicit operator bool() const { return not empty(); }
iterator begin() const; ///< Return the iterator pointing to the first row
iterator end() const; ///< Return the iterator pointing past the last row
size_t size() const { return std::distance(begin(), end()); }
bool empty() const; ///< Return true if the range is empty
explicit operator bool() const { return not empty(); } ///< Easy way to detect if the range is empty
size_t size() const { return std::distance(begin(), end()); } ///< Return size of the range
row_handle front() { return *begin(); }
row_handle front() { return *begin(); } ///< Return reference to the first row
// row_handle back() { return *begin(); }
CategoryType &category() const { return *m_cat; }
CategoryType &category() const { return *m_cat; } ///< Category the iterators belong to
/** swap */
void swap(conditional_iterator_proxy &rhs);
private:
......@@ -574,6 +644,7 @@ class conditional_iterator_proxy
// --------------------------------------------------------------------
/** @cond */
template <typename Category, typename... Ts>
iterator_proxy<Category, Ts...>::iterator_proxy(Category &cat, row_iterator pos, char const *const columns[N])
: m_category(&cat)
......@@ -675,4 +746,6 @@ void conditional_iterator_proxy<Category, Ts...>::swap(conditional_iterator_prox
std::swap(mCix, rhs.mCix);
}
/** @endcond */
} // namespace cif
\ No newline at end of file
......@@ -35,30 +35,48 @@
#include <type_traits>
#include <vector>
/**
* @file matrix.hpp
*
* Some basic matrix operations and classes to hold matrices.
*
* We're using expression templates for optimal performance.
*
*/
namespace cif
{
// --------------------------------------------------------------------
// We're using expression templates here
/**
* @brief Base for the matrix expression templates
* This all uses the Curiously recurring template pattern
*
* @tparam M The type of the derived class
*/
template <typename M>
class matrix_expression
{
public:
constexpr size_t dim_m() const { return static_cast<const M &>(*this).dim_m(); }
constexpr size_t dim_n() const { return static_cast<const M &>(*this).dim_n(); }
constexpr size_t dim_m() const { return static_cast<const M &>(*this).dim_m(); } ///< Return the size (dimension) in direction m
constexpr size_t dim_n() const { return static_cast<const M &>(*this).dim_n(); } ///< Return the size (dimension) in direction n
constexpr bool empty() const { return dim_m() == 0 or dim_n() == 0; }
constexpr bool empty() const { return dim_m() == 0 or dim_n() == 0; } ///< Convenient way to test for empty matrices
/** Return a reference to element [ @a i, @a j ] */
constexpr auto &operator()(size_t i, size_t j)
{
return static_cast<M &>(*this).operator()(i, j);
}
/** Return the value of element [ @a i, @a j ] */
constexpr auto operator()(size_t i, size_t j) const
{
return static_cast<const M &>(*this).operator()(i, j);
}
/** Swap the contents of rows @a r1 and @a r2 */
void swap_row(size_t r1, size_t r2)
{
for (size_t c = 0; c < dim_m(); ++c)
......@@ -69,6 +87,7 @@ class matrix_expression
}
}
/** Swap the contents of columns @a c1 and @a c2 */
void swap_col(size_t c1, size_t c2)
{
for (size_t r = 0; r < dim_n(); ++r)
......@@ -79,6 +98,7 @@ class matrix_expression
}
}
/** write the matrix @a m to std::ostream @a os */
friend std::ostream &operator<<(std::ostream &os, const matrix_expression &m)
{
os << '[';
......@@ -107,15 +127,29 @@ class matrix_expression
};
// --------------------------------------------------------------------
// matrix is m x n, addressing i,j is 0 <= i < m and 0 <= j < n
// element m i,j is mapped to [i * n + j] and thus storage is row major
/**
* @brief Storage class implementation of matrix_expression.
*
* @tparam F The type of the stored values
*
* matrix is m x n, addressing i,j is 0 <= i < m and 0 <= j < n
* element m i,j is mapped to [i * n + j] and thus storage is row major
*/
template <typename F = float>
class matrix : public matrix_expression<matrix<F>>
{
public:
/** The value type */
using value_type = F;
/**
* @brief Copy construct a new matrix object using @a m
*
* @tparam M2 Type of @a m
* @param m The matrix expression to copy values from
*/
template <typename M2>
matrix(const matrix_expression<M2> &m)
: m_m(m.dim_m())
......@@ -129,6 +163,14 @@ class matrix : public matrix_expression<matrix<F>>
}
}
/**
* @brief Construct a new matrix object with dimension @a m and @a n
* setting the values to @a v
*
* @param m Requested dimension M
* @param n Requested dimension N
* @param v Value to store in each element
*/
matrix(size_t m, size_t n, value_type v = 0)
: m_m(m)
, m_n(n)
......@@ -137,15 +179,18 @@ class matrix : public matrix_expression<matrix<F>>
std::fill(m_data.begin(), m_data.end(), v);
}
/** @cond */
matrix() = default;
matrix(matrix &&m) = default;
matrix(const matrix &m) = default;
matrix &operator=(matrix &&m) = default;
matrix &operator=(const matrix &m) = default;
/** @endcond */
constexpr size_t dim_m() const { return m_m; }
constexpr size_t dim_n() const { return m_n; }
constexpr size_t dim_m() const { return m_m; } ///< Return dimension m
constexpr size_t dim_n() const { return m_n; } ///< Return dimension n
/** Return the value of element [ @a i, @a j ] */
constexpr value_type operator()(size_t i, size_t j) const
{
assert(i < m_m);
......@@ -153,6 +198,7 @@ class matrix : public matrix_expression<matrix<F>>
return m_data[i * m_n + j];
}
/** Return a reference to element [ @a i, @a j ] */
constexpr value_type &operator()(size_t i, size_t j)
{
assert(i < m_m);
......@@ -168,14 +214,27 @@ class matrix : public matrix_expression<matrix<F>>
// --------------------------------------------------------------------
// special case, 3x3 matrix
/**
* @brief Storage class implementation of matrix_expression
* with compile time fixed size.
*
* @tparam F The type of the stored values
*
* matrix is m x n, addressing i,j is 0 <= i < m and 0 <= j < n
* element m i,j is mapped to [i * n + j] and thus storage is row major
*/
template <typename F, size_t M, size_t N>
class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
{
public:
/** The value type */
using value_type = F;
/** The storage size */
static constexpr size_t kSize = M * N;
/** Copy constructor */
template <typename M2>
matrix_fixed(const M2 &m)
{
......@@ -187,21 +246,26 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
}
}
/** default constructor */
matrix_fixed(value_type v = 0)
{
m_data.fill(v);
}
/** Alternate constructor taking an array of values to store */
matrix_fixed(const F (&v)[kSize])
{
fill(v, std::make_index_sequence<kSize>{});
}
/** @cond */
matrix_fixed(matrix_fixed &&m) = default;
matrix_fixed(const matrix_fixed &m) = default;
matrix_fixed &operator=(matrix_fixed &&m) = default;
matrix_fixed &operator=(const matrix_fixed &m) = default;
/** @endcond */
/** Store the values in @a a in the matrix */
template<size_t... Ixs>
matrix_fixed& fill(const F (&a)[kSize], std::index_sequence<Ixs...>)
{
......@@ -209,9 +273,10 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
return *this;
}
constexpr size_t dim_m() const { return M; }
constexpr size_t dim_n() const { return N; }
constexpr size_t dim_m() const { return M; } ///< Return dimension m
constexpr size_t dim_n() const { return N; } ///< Return dimension n
/** Return the value of element [ @a i, @a j ] */
constexpr value_type operator()(size_t i, size_t j) const
{
assert(i < M);
......@@ -219,6 +284,7 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
return m_data[i * N + j];
}
/** Return a reference to element [ @a i, @a j ] */
constexpr value_type &operator()(size_t i, size_t j)
{
assert(i < M);
......@@ -230,20 +296,32 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
std::array<value_type, M * N> m_data;
};
/** typedef of a fixed matrix of size 3x3 */
template <typename F>
using matrix3x3 = matrix_fixed<F, 3, 3>;
/** typedef of a fixed matrix of size 4x4 */
template <typename F>
using matrix4x4 = matrix_fixed<F, 4, 4>;
// --------------------------------------------------------------------
/**
* @brief Storage class implementation of symmetric matrix_expression
*
* @tparam F The type of the stored values
*
* matrix is m x n, addressing i,j is 0 <= i < m and 0 <= j < n
* element m i,j is mapped to [i * n + j] and thus storage is row major
*/
template <typename F = float>
class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
{
public:
/** The value type */
using value_type = F;
/** constructor for a matrix of size @a n x @a n elements with value @a v */
symmetric_matrix(size_t n, value_type v = 0)
: m_n(n)
, m_data((m_n * (m_n + 1)) / 2)
......@@ -251,15 +329,18 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
std::fill(m_data.begin(), m_data.end(), v);
}
/** @cond */
symmetric_matrix() = default;
symmetric_matrix(symmetric_matrix &&m) = default;
symmetric_matrix(const symmetric_matrix &m) = default;
symmetric_matrix &operator=(symmetric_matrix &&m) = default;
symmetric_matrix &operator=(const symmetric_matrix &m) = default;
/** @endcond */
constexpr size_t dim_m() const { return m_n; }
constexpr size_t dim_n() const { return m_n; }
constexpr size_t dim_m() const { return m_n; } ///< Return dimension m
constexpr size_t dim_n() const { return m_n; } ///< Return dimension n
/** Return the value of element [ @a i, @a j ] */
constexpr value_type operator()(size_t i, size_t j) const
{
return i < j
......@@ -267,6 +348,7 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
: m_data[(i * (i + 1)) / 2 + j];
}
/** Return a reference to element [ @a i, @a j ] */
constexpr value_type &operator()(size_t i, size_t j)
{
if (i > j)
......@@ -282,25 +364,39 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
// --------------------------------------------------------------------
/**
* @brief Storage class implementation of symmetric matrix_expression
* with compile time fixed size.
*
* @tparam F The type of the stored values
*
* matrix is m x n, addressing i,j is 0 <= i < m and 0 <= j < n
* element m i,j is mapped to [i * n + j] and thus storage is row major
*/
template <typename F, size_t M>
class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F, M>>
{
public:
/** The value type */
using value_type = F;
/** constructor with all elements set to value @a v */
symmetric_matrix_fixed(value_type v = 0)
{
std::fill(m_data.begin(), m_data.end(), v);
}
/** @cond */
symmetric_matrix_fixed(symmetric_matrix_fixed &&m) = default;
symmetric_matrix_fixed(const symmetric_matrix_fixed &m) = default;
symmetric_matrix_fixed &operator=(symmetric_matrix_fixed &&m) = default;
symmetric_matrix_fixed &operator=(const symmetric_matrix_fixed &m) = default;
/** @endcond */
constexpr size_t dim_m() const { return M; }
constexpr size_t dim_n() const { return M; }
constexpr size_t dim_m() const { return M; } ///< Return dimension m
constexpr size_t dim_n() const { return M; } ///< Return dimension n
/** Return the value of element [ @a i, @a j ] */
constexpr value_type operator()(size_t i, size_t j) const
{
return i < j
......@@ -308,6 +404,7 @@ class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F
: m_data[(i * (i + 1)) / 2 + j];
}
/** Return a reference to element [ @a i, @a j ] */
constexpr value_type &operator()(size_t i, size_t j)
{
if (i > j)
......@@ -320,28 +417,42 @@ class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F
std::array<value_type, (M * (M + 1)) / 2> m_data;
};
/** typedef of a fixed symmetric matrix of size 3x3 */
template <typename F>
using symmetric_matrix3x3 = symmetric_matrix_fixed<F, 3>;
/** typedef of a fixed symmetric matrix of size 4x4 */
template <typename F>
using symmetric_matrix4x4 = symmetric_matrix_fixed<F, 4>;
// --------------------------------------------------------------------
/**
* @brief implementation of symmetric matrix_expression with a value
* of 1 for the diagonal values and 0 for all the others.
*
* @tparam F The type of the stored values
*
* matrix is m x n, addressing i,j is 0 <= i < m and 0 <= j < n
* element m i,j is mapped to [i * n + j] and thus storage is row major
*/
template <typename F = float>
class identity_matrix : public matrix_expression<identity_matrix<F>>
{
public:
/** the value type */
using value_type = F;
/** constructor taking a dimension @a n */
identity_matrix(size_t n)
: m_n(n)
{
}
constexpr size_t dim_m() const { return m_n; }
constexpr size_t dim_n() const { return m_n; }
constexpr size_t dim_m() const { return m_n; } ///< Return dimension m
constexpr size_t dim_n() const { return m_n; } ///< Return dimension n
/** Return the value of element [ @a i, @a j ] */
constexpr value_type operator()(size_t i, size_t j) const
{
return static_cast<value_type>(i == j ? 1 : 0);
......@@ -354,10 +465,17 @@ class identity_matrix : public matrix_expression<identity_matrix<F>>
// --------------------------------------------------------------------
// matrix functions, implemented as expression templates
/**
* @brief Implementation of a substraction operation as a matrix expression
*
* @tparam M1 Type of matrix 1
* @tparam M2 Type of matrix 2
*/
template <typename M1, typename M2>
class matrix_subtraction : public matrix_expression<matrix_subtraction<M1, M2>>
{
public:
/** constructor */
matrix_subtraction(const M1 &m1, const M2 &m2)
: m_m1(m1)
, m_m2(m2)
......@@ -366,9 +484,10 @@ class matrix_subtraction : public matrix_expression<matrix_subtraction<M1, M2>>
assert(m_m1.dim_n() == m_m2.dim_n());
}
constexpr size_t dim_m() const { return m_m1.dim_m(); }
constexpr size_t dim_n() const { return m_m1.dim_n(); }
constexpr size_t dim_m() const { return m_m1.dim_m(); } ///< Return dimension m
constexpr size_t dim_n() const { return m_m1.dim_n(); } ///< Return dimension n
/** Access to the value of element [ @a i, @a j ] */
constexpr auto operator()(size_t i, size_t j) const
{
return m_m1(i, j) - m_m2(i, j);
......@@ -379,16 +498,24 @@ class matrix_subtraction : public matrix_expression<matrix_subtraction<M1, M2>>
const M2 &m_m2;
};
/** operator to subtract two matrices and return a matrix expression */
template <typename M1, typename M2>
auto operator-(const matrix_expression<M1> &m1, const matrix_expression<M2> &m2)
{
return matrix_subtraction(m1, m2);
}
/**
* @brief Implementation of a multiplication operation as a matrix expression
*
* @tparam M1 Type of matrix 1
* @tparam M2 Type of matrix 2
*/
template <typename M1, typename M2>
class matrix_matrix_multiplication : public matrix_expression<matrix_matrix_multiplication<M1, M2>>
{
public:
/** constructor */
matrix_matrix_multiplication(const M1 &m1, const M2 &m2)
: m_m1(m1)
, m_m2(m2)
......@@ -396,9 +523,10 @@ class matrix_matrix_multiplication : public matrix_expression<matrix_matrix_mult
assert(m1.dim_m() == m2.dim_n());
}
constexpr size_t dim_m() const { return m_m1.dim_m(); }
constexpr size_t dim_n() const { return m_m1.dim_n(); }
constexpr size_t dim_m() const { return m_m1.dim_m(); } ///< Return dimension m
constexpr size_t dim_n() const { return m_m1.dim_n(); } ///< Return dimension n
/** Access to the value of element [ @a i, @a j ] */
constexpr auto operator()(size_t i, size_t j) const
{
using value_type = decltype(m_m1(0, 0));
......@@ -416,21 +544,30 @@ class matrix_matrix_multiplication : public matrix_expression<matrix_matrix_mult
const M2 &m_m2;
};
/**
* @brief Implementation of a multiplication operation of a matrix and a scalar value as a matrix expression
*
* @tparam M1 Type of matrix
* @tparam M2 Type of scalar value
*/
template <typename M, typename T>
class matrix_scalar_multiplication : public matrix_expression<matrix_scalar_multiplication<M, T>>
{
public:
/** value type */
using value_type = T;
/** constructor */
matrix_scalar_multiplication(const M &m, value_type v)
: m_m(m)
, m_v(v)
{
}
constexpr size_t dim_m() const { return m_m.dim_m(); }
constexpr size_t dim_n() const { return m_m.dim_n(); }
constexpr size_t dim_m() const { return m_m.dim_m(); } ///< Return dimension m
constexpr size_t dim_n() const { return m_m.dim_n(); } ///< Return dimension n
/** Access to the value of element [ @a i, @a j ] */
constexpr auto operator()(size_t i, size_t j) const
{
return m_m(i, j) * m_v;
......@@ -441,12 +578,14 @@ class matrix_scalar_multiplication : public matrix_expression<matrix_scalar_mult
value_type m_v;
};
/** First implementation of operator*, enabled if the second parameter is a scalar */
template <typename M1, typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
auto operator*(const matrix_expression<M1> &m, T v)
{
return matrix_scalar_multiplication(m, v);
}
/** First implementation of operator*, enabled if the second parameter is not a scalar and thus must be a matrix, right? */
template <typename M1, typename M2, std::enable_if_t<not std::is_floating_point_v<M2>, int> = 0>
auto operator*(const matrix_expression<M1> &m1, const matrix_expression<M2> &m2)
{
......@@ -455,9 +594,14 @@ auto operator*(const matrix_expression<M1> &m1, const matrix_expression<M2> &m2)
// --------------------------------------------------------------------
/** Generic routine to calculate the determinant of a matrix
*
* @note This is currently only implemented for fixed matrices of size 3x3
*/
template <typename M>
auto determinant(const M &m);
/** Implementation of the determinant function for fixed size matrices of size 3x3 */
template <typename F = float>
auto determinant(const matrix3x3<F> &m)
{
......@@ -466,9 +610,14 @@ auto determinant(const matrix3x3<F> &m)
m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0)));
}
/** Generic routine to calculate the inverse of a matrix
*
* @note This is currently only implemented for fixed matrices of size 3x3
*/
template <typename M>
M inverse(const M &m);
/** Implementation of the inverse function for fixed size matrices of size 3x3 */
template <typename F = float>
matrix3x3<F> inverse(const matrix3x3<F> &m)
{
......@@ -491,18 +640,25 @@ matrix3x3<F> inverse(const matrix3x3<F> &m)
// --------------------------------------------------------------------
/**
* @brief Implementation of a cofactor calculation as a matrix expression
*
* @tparam M Type of matrix
*/
template <typename M>
class matrix_cofactors : public matrix_expression<matrix_cofactors<M>>
{
public:
/** constructor */
matrix_cofactors(const M &m)
: m_m(m)
{
}
constexpr size_t dim_m() const { return m_m.dim_m(); }
constexpr size_t dim_n() const { return m_m.dim_n(); }
constexpr size_t dim_m() const { return m_m.dim_m(); } ///< Return dimension m
constexpr size_t dim_n() const { return m_m.dim_n(); } ///< Return dimension n
/** Access to the value of element [ @a i, @a j ] */
constexpr auto operator()(size_t i, size_t j) const
{
const size_t ixs[4][3] = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment