Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
libcifpp
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
libcifpp
Commits
f44e6d09
Unverified
Commit
f44e6d09
authored
Sep 05, 2023
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
backup of documentation
parent
d496ebf6
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
278 additions
and
48 deletions
+278
-48
include/cif++/condition.hpp
+2
-2
include/cif++/iterator.hpp
+97
-23
include/cif++/matrix.hpp
+179
-23
No files found.
include/cif++/condition.hpp
View file @
f44e6d09
...
@@ -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
;
...
...
include/cif++/iterator.hpp
View file @
f44e6d09
...
@@ -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
include/cif++/matrix.hpp
View file @
f44e6d09
...
@@ -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
]
=
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment