Commit f44e6d09 by Maarten L. Hekkelman

backup of documentation

parent d496ebf6
...@@ -262,8 +262,8 @@ class condition ...@@ -262,8 +262,8 @@ class condition
return m_impl ? m_impl->single() : std::optional<row_handle>(); 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); /**< Return a condition which is the logical OR or condition @a and @b */
friend condition operator&&(condition &&a, condition &&b); /**< Operator AND */ friend condition operator&&(condition &&a, condition &&b); /**< Return a condition which is the logical AND or condition @a and @b */
/// @cond /// @cond
friend struct detail::or_condition_impl; friend struct detail::or_condition_impl;
......
...@@ -30,22 +30,46 @@ ...@@ -30,22 +30,46 @@
#include <array> #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 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> template <typename Category, typename... Ts>
class iterator_impl class iterator_impl
{ {
public: public:
/** @cond */
template <typename, typename...> template <typename, typename...>
friend class iterator_impl; friend class iterator_impl;
friend class category; friend class category;
/** @endcond */
/** variable that contains the number of elements in the tuple */
static constexpr size_t N = sizeof...(Ts); static constexpr size_t N = sizeof...(Ts);
/** @cond */
using category_type = std::remove_cv_t<Category>; using category_type = std::remove_cv_t<Category>;
using row_type = std::conditional_t<std::is_const_v<Category>, const row, row>; using row_type = std::conditional_t<std::is_const_v<Category>, const row, row>;
...@@ -152,14 +176,16 @@ class iterator_impl ...@@ -152,14 +176,16 @@ class iterator_impl
return m_current != rhs.m_current; return m_current != rhs.m_current;
} }
/** @endcond */
private: private:
template <size_t... Is> template <size_t... Is>
tuple_type get(std::index_sequence<Is...>) const tuple_type get(std::index_sequence<Is...>) const
{ {
if (m_current != nullptr) if (m_current != nullptr)
{ {
row_handle rh{*m_category, *m_current}; row_handle rh{ *m_category, *m_current };
return tuple_type{rh[m_column_ix[Is]].template as<Ts>()...}; return tuple_type{ rh[m_column_ix[Is]].template as<Ts>()... };
} }
return {}; return {};
...@@ -171,10 +197,18 @@ class iterator_impl ...@@ -171,10 +197,18 @@ class iterator_impl
std::array<uint16_t, N> m_column_ix; 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> class iterator_impl<Category>
{ {
public: public:
/** @cond */
template <typename, typename...> template <typename, typename...>
friend class iterator_impl; friend class iterator_impl;
...@@ -195,7 +229,7 @@ class iterator_impl<Category> ...@@ -195,7 +229,7 @@ class iterator_impl<Category>
template <typename C2> template <typename C2>
iterator_impl(const iterator_impl<C2> &rhs) iterator_impl(const iterator_impl<C2> &rhs)
: m_category(rhs.m_category) : 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> ...@@ -223,7 +257,7 @@ class iterator_impl<Category>
reference operator*() reference operator*()
{ {
return {*m_category, *m_current}; return { *m_category, *m_current };
} }
pointer operator->() pointer operator->()
...@@ -271,16 +305,26 @@ class iterator_impl<Category> ...@@ -271,16 +305,26 @@ class iterator_impl<Category>
return m_current != rhs.m_current; return m_current != rhs.m_current;
} }
/** @endcond */
private: private:
category_type *m_category = nullptr; category_type *m_category = nullptr;
row_type *m_current = 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> class iterator_impl<Category, T>
{ {
public: public:
/** @cond */
template <typename, typename...> template <typename, typename...>
friend class iterator_impl; friend class iterator_impl;
...@@ -390,12 +434,14 @@ class iterator_impl<Category, T> ...@@ -390,12 +434,14 @@ class iterator_impl<Category, T>
return m_current != rhs.m_current; return m_current != rhs.m_current;
} }
/** @endcond */
private: private:
value_type get() const value_type get() const
{ {
if (m_current != nullptr) 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>(); return rh[m_column_ix].template as<T>();
} }
...@@ -411,10 +457,23 @@ class iterator_impl<Category, T> ...@@ -411,10 +457,23 @@ class iterator_impl<Category, T>
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// iterator proxy // 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> template <typename Category, typename... Ts>
class iterator_proxy class iterator_proxy
{ {
public: public:
/** @cond */
static constexpr const size_t N = sizeof...(Ts); static constexpr const size_t N = sizeof...(Ts);
using category_type = Category; using category_type = Category;
...@@ -431,21 +490,21 @@ class iterator_proxy ...@@ -431,21 +490,21 @@ class iterator_proxy
iterator_proxy(const iterator_proxy &) = delete; iterator_proxy(const iterator_proxy &) = delete;
iterator_proxy &operator=(const iterator_proxy &) = delete; iterator_proxy &operator=(const iterator_proxy &) = delete;
/** @endcond */
iterator begin() const { return iterator(m_begin, 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); } 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; } 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
explicit operator bool() const { return not empty(); } size_t size() const { return std::distance(begin(), end()); } ///< Return size of the range
size_t size() const { return std::distance(begin(), end()); }
// row front() { return *begin(); } // row front() { return *begin(); }
// row back() { return *(std::prev(end())); } // 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) void swap(iterator_proxy &rhs)
{ {
std::swap(m_category, rhs.m_category); std::swap(m_category, rhs.m_category);
...@@ -463,10 +522,20 @@ class iterator_proxy ...@@ -463,10 +522,20 @@ class iterator_proxy
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// conditional 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> template <typename CategoryType, typename... Ts>
class conditional_iterator_proxy class conditional_iterator_proxy
{ {
public: public:
/** @cond */
static constexpr const size_t N = sizeof...(Ts); static constexpr const size_t N = sizeof...(Ts);
using category_type = std::remove_cv_t<CategoryType>; using category_type = std::remove_cv_t<CategoryType>;
...@@ -549,20 +618,21 @@ class conditional_iterator_proxy ...@@ -549,20 +618,21 @@ class conditional_iterator_proxy
conditional_iterator_proxy(const conditional_iterator_proxy &) = delete; conditional_iterator_proxy(const conditional_iterator_proxy &) = delete;
conditional_iterator_proxy &operator=(const conditional_iterator_proxy &) = delete; conditional_iterator_proxy &operator=(const conditional_iterator_proxy &) = delete;
iterator begin() const; /** @endcond */
iterator end() const;
bool empty() const;
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(); } // 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); void swap(conditional_iterator_proxy &rhs);
private: private:
...@@ -574,6 +644,7 @@ class conditional_iterator_proxy ...@@ -574,6 +644,7 @@ class conditional_iterator_proxy
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/** @cond */
template <typename Category, typename... Ts> template <typename Category, typename... Ts>
iterator_proxy<Category, Ts...>::iterator_proxy(Category &cat, row_iterator pos, char const *const columns[N]) iterator_proxy<Category, Ts...>::iterator_proxy(Category &cat, row_iterator pos, char const *const columns[N])
: m_category(&cat) : m_category(&cat)
...@@ -675,4 +746,6 @@ void conditional_iterator_proxy<Category, Ts...>::swap(conditional_iterator_prox ...@@ -675,4 +746,6 @@ void conditional_iterator_proxy<Category, Ts...>::swap(conditional_iterator_prox
std::swap(mCix, rhs.mCix); std::swap(mCix, rhs.mCix);
} }
/** @endcond */
} // namespace cif } // namespace cif
\ No newline at end of file
...@@ -35,30 +35,48 @@ ...@@ -35,30 +35,48 @@
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
/**
* @file matrix.hpp
*
* Some basic matrix operations and classes to hold matrices.
*
* We're using expression templates for optimal performance.
*
*/
namespace cif namespace cif
{ {
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// We're using expression templates here // 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> template <typename M>
class matrix_expression class matrix_expression
{ {
public: public:
constexpr size_t dim_m() const { return static_cast<const M &>(*this).dim_m(); } 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(); } 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) constexpr auto &operator()(size_t i, size_t j)
{ {
return static_cast<M &>(*this).operator()(i, 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 constexpr auto operator()(size_t i, size_t j) const
{ {
return static_cast<const M &>(*this).operator()(i, j); 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) void swap_row(size_t r1, size_t r2)
{ {
for (size_t c = 0; c < dim_m(); ++c) for (size_t c = 0; c < dim_m(); ++c)
...@@ -69,6 +87,7 @@ class matrix_expression ...@@ -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) void swap_col(size_t c1, size_t c2)
{ {
for (size_t r = 0; r < dim_n(); ++r) for (size_t r = 0; r < dim_n(); ++r)
...@@ -79,6 +98,7 @@ class matrix_expression ...@@ -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) friend std::ostream &operator<<(std::ostream &os, const matrix_expression &m)
{ {
os << '['; os << '[';
...@@ -107,15 +127,29 @@ class matrix_expression ...@@ -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> template <typename F = float>
class matrix : public matrix_expression<matrix<F>> class matrix : public matrix_expression<matrix<F>>
{ {
public: public:
/** The value type */
using value_type = F; 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> template <typename M2>
matrix(const matrix_expression<M2> &m) matrix(const matrix_expression<M2> &m)
: m_m(m.dim_m()) : m_m(m.dim_m())
...@@ -129,6 +163,14 @@ class matrix : public matrix_expression<matrix<F>> ...@@ -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) matrix(size_t m, size_t n, value_type v = 0)
: m_m(m) : m_m(m)
, m_n(n) , m_n(n)
...@@ -137,15 +179,18 @@ class matrix : public matrix_expression<matrix<F>> ...@@ -137,15 +179,18 @@ class matrix : public matrix_expression<matrix<F>>
std::fill(m_data.begin(), m_data.end(), v); std::fill(m_data.begin(), m_data.end(), v);
} }
/** @cond */
matrix() = default; matrix() = default;
matrix(matrix &&m) = default; matrix(matrix &&m) = default;
matrix(const matrix &m) = default; matrix(const matrix &m) = default;
matrix &operator=(matrix &&m) = default; matrix &operator=(matrix &&m) = default;
matrix &operator=(const matrix &m) = default; matrix &operator=(const matrix &m) = default;
/** @endcond */
constexpr size_t dim_m() const { return m_m; } constexpr size_t dim_m() const { return m_m; } ///< Return dimension m
constexpr size_t dim_n() const { return m_n; } 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 constexpr value_type operator()(size_t i, size_t j) const
{ {
assert(i < m_m); assert(i < m_m);
...@@ -153,6 +198,7 @@ class matrix : public matrix_expression<matrix<F>> ...@@ -153,6 +198,7 @@ class matrix : public matrix_expression<matrix<F>>
return m_data[i * m_n + j]; 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) constexpr value_type &operator()(size_t i, size_t j)
{ {
assert(i < m_m); assert(i < m_m);
...@@ -168,14 +214,27 @@ class matrix : public matrix_expression<matrix<F>> ...@@ -168,14 +214,27 @@ class matrix : public matrix_expression<matrix<F>>
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// special case, 3x3 matrix // 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> template <typename F, size_t M, size_t N>
class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>> class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
{ {
public: public:
/** The value type */
using value_type = F; using value_type = F;
/** The storage size */
static constexpr size_t kSize = M * N; static constexpr size_t kSize = M * N;
/** Copy constructor */
template <typename M2> template <typename M2>
matrix_fixed(const M2 &m) matrix_fixed(const M2 &m)
{ {
...@@ -187,21 +246,26 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>> ...@@ -187,21 +246,26 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
} }
} }
/** default constructor */
matrix_fixed(value_type v = 0) matrix_fixed(value_type v = 0)
{ {
m_data.fill(v); m_data.fill(v);
} }
/** Alternate constructor taking an array of values to store */
matrix_fixed(const F (&v)[kSize]) matrix_fixed(const F (&v)[kSize])
{ {
fill(v, std::make_index_sequence<kSize>{}); fill(v, std::make_index_sequence<kSize>{});
} }
/** @cond */
matrix_fixed(matrix_fixed &&m) = default; matrix_fixed(matrix_fixed &&m) = default;
matrix_fixed(const matrix_fixed &m) = default; matrix_fixed(const matrix_fixed &m) = default;
matrix_fixed &operator=(matrix_fixed &&m) = default; matrix_fixed &operator=(matrix_fixed &&m) = default;
matrix_fixed &operator=(const 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> template<size_t... Ixs>
matrix_fixed& fill(const F (&a)[kSize], std::index_sequence<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>> ...@@ -209,9 +273,10 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
return *this; return *this;
} }
constexpr size_t dim_m() const { return M; } constexpr size_t dim_m() const { return M; } ///< Return dimension m
constexpr size_t dim_n() const { return N; } 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 constexpr value_type operator()(size_t i, size_t j) const
{ {
assert(i < M); assert(i < M);
...@@ -219,6 +284,7 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>> ...@@ -219,6 +284,7 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
return m_data[i * N + j]; 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) constexpr value_type &operator()(size_t i, size_t j)
{ {
assert(i < M); assert(i < M);
...@@ -230,20 +296,32 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>> ...@@ -230,20 +296,32 @@ class matrix_fixed : public matrix_expression<matrix_fixed<F, M, N>>
std::array<value_type, M * N> m_data; std::array<value_type, M * N> m_data;
}; };
/** typedef of a fixed matrix of size 3x3 */
template <typename F> template <typename F>
using matrix3x3 = matrix_fixed<F, 3, 3>; using matrix3x3 = matrix_fixed<F, 3, 3>;
/** typedef of a fixed matrix of size 4x4 */
template <typename F> template <typename F>
using matrix4x4 = matrix_fixed<F, 4, 4>; 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> template <typename F = float>
class symmetric_matrix : public matrix_expression<symmetric_matrix<F>> class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
{ {
public: public:
/** The value type */
using value_type = F; 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) symmetric_matrix(size_t n, value_type v = 0)
: m_n(n) : m_n(n)
, m_data((m_n * (m_n + 1)) / 2) , m_data((m_n * (m_n + 1)) / 2)
...@@ -251,15 +329,18 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>> ...@@ -251,15 +329,18 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
std::fill(m_data.begin(), m_data.end(), v); std::fill(m_data.begin(), m_data.end(), v);
} }
/** @cond */
symmetric_matrix() = default; symmetric_matrix() = default;
symmetric_matrix(symmetric_matrix &&m) = default; symmetric_matrix(symmetric_matrix &&m) = default;
symmetric_matrix(const symmetric_matrix &m) = default; symmetric_matrix(const symmetric_matrix &m) = default;
symmetric_matrix &operator=(symmetric_matrix &&m) = default; symmetric_matrix &operator=(symmetric_matrix &&m) = default;
symmetric_matrix &operator=(const 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_m() const { return m_n; } ///< Return dimension m
constexpr size_t dim_n() const { return m_n; } 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 constexpr value_type operator()(size_t i, size_t j) const
{ {
return i < j return i < j
...@@ -267,6 +348,7 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>> ...@@ -267,6 +348,7 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>>
: m_data[(i * (i + 1)) / 2 + j]; : 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) constexpr value_type &operator()(size_t i, size_t j)
{ {
if (i > j) if (i > j)
...@@ -282,25 +364,39 @@ class symmetric_matrix : public matrix_expression<symmetric_matrix<F>> ...@@ -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> template <typename F, size_t M>
class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F, M>> class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F, M>>
{ {
public: public:
/** The value type */
using value_type = F; using value_type = F;
/** constructor with all elements set to value @a v */
symmetric_matrix_fixed(value_type v = 0) symmetric_matrix_fixed(value_type v = 0)
{ {
std::fill(m_data.begin(), m_data.end(), v); std::fill(m_data.begin(), m_data.end(), v);
} }
/** @cond */
symmetric_matrix_fixed(symmetric_matrix_fixed &&m) = default; symmetric_matrix_fixed(symmetric_matrix_fixed &&m) = default;
symmetric_matrix_fixed(const 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=(symmetric_matrix_fixed &&m) = default;
symmetric_matrix_fixed &operator=(const 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_m() const { return M; } ///< Return dimension m
constexpr size_t dim_n() const { return 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 constexpr value_type operator()(size_t i, size_t j) const
{ {
return i < j return i < j
...@@ -308,6 +404,7 @@ class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F ...@@ -308,6 +404,7 @@ class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F
: m_data[(i * (i + 1)) / 2 + j]; : 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) constexpr value_type &operator()(size_t i, size_t j)
{ {
if (i > j) if (i > j)
...@@ -320,28 +417,42 @@ class symmetric_matrix_fixed : public matrix_expression<symmetric_matrix_fixed<F ...@@ -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; std::array<value_type, (M * (M + 1)) / 2> m_data;
}; };
/** typedef of a fixed symmetric matrix of size 3x3 */
template <typename F> template <typename F>
using symmetric_matrix3x3 = symmetric_matrix_fixed<F, 3>; using symmetric_matrix3x3 = symmetric_matrix_fixed<F, 3>;
/** typedef of a fixed symmetric matrix of size 4x4 */
template <typename F> template <typename F>
using symmetric_matrix4x4 = symmetric_matrix_fixed<F, 4>; 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> template <typename F = float>
class identity_matrix : public matrix_expression<identity_matrix<F>> class identity_matrix : public matrix_expression<identity_matrix<F>>
{ {
public: public:
/** the value type */
using value_type = F; using value_type = F;
/** constructor taking a dimension @a n */
identity_matrix(size_t n) identity_matrix(size_t n)
: m_n(n) : m_n(n)
{ {
} }
constexpr size_t dim_m() 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; } 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 constexpr value_type operator()(size_t i, size_t j) const
{ {
return static_cast<value_type>(i == j ? 1 : 0); return static_cast<value_type>(i == j ? 1 : 0);
...@@ -354,10 +465,17 @@ class identity_matrix : public matrix_expression<identity_matrix<F>> ...@@ -354,10 +465,17 @@ class identity_matrix : public matrix_expression<identity_matrix<F>>
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// matrix functions, implemented as expression templates // 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> template <typename M1, typename M2>
class matrix_subtraction : public matrix_expression<matrix_subtraction<M1, M2>> class matrix_subtraction : public matrix_expression<matrix_subtraction<M1, M2>>
{ {
public: public:
/** constructor */
matrix_subtraction(const M1 &m1, const M2 &m2) matrix_subtraction(const M1 &m1, const M2 &m2)
: m_m1(m1) : m_m1(m1)
, m_m2(m2) , m_m2(m2)
...@@ -366,9 +484,10 @@ class matrix_subtraction : public matrix_expression<matrix_subtraction<M1, M2>> ...@@ -366,9 +484,10 @@ class matrix_subtraction : public matrix_expression<matrix_subtraction<M1, M2>>
assert(m_m1.dim_n() == m_m2.dim_n()); assert(m_m1.dim_n() == m_m2.dim_n());
} }
constexpr size_t dim_m() const { return m_m1.dim_m(); } 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(); } 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 constexpr auto operator()(size_t i, size_t j) const
{ {
return m_m1(i, j) - m_m2(i, j); return m_m1(i, j) - m_m2(i, j);
...@@ -379,16 +498,24 @@ class matrix_subtraction : public matrix_expression<matrix_subtraction<M1, M2>> ...@@ -379,16 +498,24 @@ class matrix_subtraction : public matrix_expression<matrix_subtraction<M1, M2>>
const M2 &m_m2; const M2 &m_m2;
}; };
/** operator to subtract two matrices and return a matrix expression */
template <typename M1, typename M2> template <typename M1, typename M2>
auto operator-(const matrix_expression<M1> &m1, const matrix_expression<M2> &m2) auto operator-(const matrix_expression<M1> &m1, const matrix_expression<M2> &m2)
{ {
return matrix_subtraction(m1, 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> template <typename M1, typename M2>
class matrix_matrix_multiplication : public matrix_expression<matrix_matrix_multiplication<M1, M2>> class matrix_matrix_multiplication : public matrix_expression<matrix_matrix_multiplication<M1, M2>>
{ {
public: public:
/** constructor */
matrix_matrix_multiplication(const M1 &m1, const M2 &m2) matrix_matrix_multiplication(const M1 &m1, const M2 &m2)
: m_m1(m1) : m_m1(m1)
, m_m2(m2) , m_m2(m2)
...@@ -396,9 +523,10 @@ class matrix_matrix_multiplication : public matrix_expression<matrix_matrix_mult ...@@ -396,9 +523,10 @@ class matrix_matrix_multiplication : public matrix_expression<matrix_matrix_mult
assert(m1.dim_m() == m2.dim_n()); assert(m1.dim_m() == m2.dim_n());
} }
constexpr size_t dim_m() const { return m_m1.dim_m(); } 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(); } 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 constexpr auto operator()(size_t i, size_t j) const
{ {
using value_type = decltype(m_m1(0, 0)); using value_type = decltype(m_m1(0, 0));
...@@ -416,21 +544,30 @@ class matrix_matrix_multiplication : public matrix_expression<matrix_matrix_mult ...@@ -416,21 +544,30 @@ class matrix_matrix_multiplication : public matrix_expression<matrix_matrix_mult
const M2 &m_m2; 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> template <typename M, typename T>
class matrix_scalar_multiplication : public matrix_expression<matrix_scalar_multiplication<M, T>> class matrix_scalar_multiplication : public matrix_expression<matrix_scalar_multiplication<M, T>>
{ {
public: public:
/** value type */
using value_type = T; using value_type = T;
/** constructor */
matrix_scalar_multiplication(const M &m, value_type v) matrix_scalar_multiplication(const M &m, value_type v)
: m_m(m) : m_m(m)
, m_v(v) , m_v(v)
{ {
} }
constexpr size_t dim_m() const { return m_m.dim_m(); } 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(); } 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 constexpr auto operator()(size_t i, size_t j) const
{ {
return m_m(i, j) * m_v; return m_m(i, j) * m_v;
...@@ -441,12 +578,14 @@ class matrix_scalar_multiplication : public matrix_expression<matrix_scalar_mult ...@@ -441,12 +578,14 @@ class matrix_scalar_multiplication : public matrix_expression<matrix_scalar_mult
value_type m_v; 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> 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) auto operator*(const matrix_expression<M1> &m, T v)
{ {
return matrix_scalar_multiplication(m, 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> 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) 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) ...@@ -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> template <typename M>
auto determinant(const M &m); auto determinant(const M &m);
/** Implementation of the determinant function for fixed size matrices of size 3x3 */
template <typename F = float> template <typename F = float>
auto determinant(const matrix3x3<F> &m) auto determinant(const matrix3x3<F> &m)
{ {
...@@ -466,9 +610,14 @@ 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))); 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> template <typename M>
M inverse(const M &m); M inverse(const M &m);
/** Implementation of the inverse function for fixed size matrices of size 3x3 */
template <typename F = float> template <typename F = float>
matrix3x3<F> inverse(const matrix3x3<F> &m) matrix3x3<F> inverse(const matrix3x3<F> &m)
{ {
...@@ -491,18 +640,25 @@ 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> template <typename M>
class matrix_cofactors : public matrix_expression<matrix_cofactors<M>> class matrix_cofactors : public matrix_expression<matrix_cofactors<M>>
{ {
public: public:
/** constructor */
matrix_cofactors(const M &m) matrix_cofactors(const M &m)
: m_m(m) : m_m(m)
{ {
} }
constexpr size_t dim_m() const { return m_m.dim_m(); } 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(); } 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 constexpr auto operator()(size_t i, size_t j) const
{ {
const size_t ixs[4][3] = { 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