Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
E
elsa
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
33
Issues
33
List
Boards
Labels
Service Desk
Milestones
Iterations
Merge Requests
9
Merge Requests
9
Requirements
Requirements
List
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Test Cases
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Code Review
Insights
Issue
Repository
Value Stream
External Wiki
External Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
IP
elsa
Commits
b29a17c5
Commit
b29a17c5
authored
Oct 30, 2019
by
David Frank
Committed by
Tobias Lasser
Oct 30, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add iterator support for DataContainer
parent
a41728d7
Pipeline
#171245
passed with stages
in 27 minutes and 13 seconds
Changes
5
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
474 additions
and
1 deletion
+474
-1
elsa/core/CMakeLists.txt
elsa/core/CMakeLists.txt
+1
-0
elsa/core/DataContainer.cpp
elsa/core/DataContainer.cpp
+76
-0
elsa/core/DataContainer.h
elsa/core/DataContainer.h
+62
-1
elsa/core/DataContainerIterator.h
elsa/core/DataContainerIterator.h
+179
-0
elsa/core/tests/test_DataContainer.cpp
elsa/core/tests/test_DataContainer.cpp
+156
-0
No files found.
elsa/core/CMakeLists.txt
View file @
b29a17c5
...
...
@@ -13,6 +13,7 @@ set(MODULE_HEADERS
DataDescriptor.h
BlockDescriptor.h
DataContainer.h
DataContainerIterator.h
DataHandler.h
DataHandlerCPU.h
LinearOperator.h
)
...
...
elsa/core/DataContainer.cpp
View file @
b29a17c5
...
...
@@ -289,6 +289,82 @@ namespace elsa {
return
;
}
template
<
typename
data_t
>
typename
DataContainer
<
data_t
>::
iterator
DataContainer
<
data_t
>::
begin
()
{
detach
();
return
iterator
(
&
(
*
this
)[
0
]);
}
template
<
typename
data_t
>
typename
DataContainer
<
data_t
>::
const_iterator
DataContainer
<
data_t
>::
begin
()
const
{
return
cbegin
();
}
template
<
typename
data_t
>
typename
DataContainer
<
data_t
>::
const_iterator
DataContainer
<
data_t
>::
cbegin
()
const
{
return
const_iterator
(
&
(
*
this
)[
0
]);
}
template
<
typename
data_t
>
typename
DataContainer
<
data_t
>::
iterator
DataContainer
<
data_t
>::
end
()
{
detach
();
return
iterator
(
&
(
*
this
)[
0
]
+
getSize
());
}
template
<
typename
data_t
>
typename
DataContainer
<
data_t
>::
const_iterator
DataContainer
<
data_t
>::
end
()
const
{
return
cend
();
}
template
<
typename
data_t
>
typename
DataContainer
<
data_t
>::
const_iterator
DataContainer
<
data_t
>::
cend
()
const
{
return
const_iterator
(
&
(
*
this
)[
0
]
+
getSize
());
}
template
<
typename
data_t
>
typename
DataContainer
<
data_t
>::
reverse_iterator
DataContainer
<
data_t
>::
rbegin
()
{
detach
();
return
reverse_iterator
(
end
());
}
template
<
typename
data_t
>
typename
DataContainer
<
data_t
>::
const_reverse_iterator
DataContainer
<
data_t
>::
rbegin
()
const
{
return
crbegin
();
}
template
<
typename
data_t
>
typename
DataContainer
<
data_t
>::
const_reverse_iterator
DataContainer
<
data_t
>::
crbegin
()
const
{
return
const_reverse_iterator
(
cend
());
}
template
<
typename
data_t
>
typename
DataContainer
<
data_t
>::
reverse_iterator
DataContainer
<
data_t
>::
rend
()
{
detach
();
return
reverse_iterator
(
begin
());
}
template
<
typename
data_t
>
typename
DataContainer
<
data_t
>::
const_reverse_iterator
DataContainer
<
data_t
>::
rend
()
const
{
return
crend
();
}
template
<
typename
data_t
>
typename
DataContainer
<
data_t
>::
const_reverse_iterator
DataContainer
<
data_t
>::
crend
()
const
{
return
const_reverse_iterator
(
cbegin
());
}
// ------------------------------------------
// explicit template instantiation
template
class
DataContainer
<
float
>;
...
...
elsa/core/DataContainer.h
View file @
b29a17c5
...
...
@@ -4,6 +4,7 @@
#include "elsa.h"
#include "DataDescriptor.h"
#include "DataHandler.h"
#include "DataContainerIterator.h"
#include <memory>
#include <type_traits>
...
...
@@ -20,7 +21,7 @@ namespace elsa
*
* \author Matthias Wieczorek - initial code
* \author Tobias Lasser - rewrite, modularization, modernization
* \author David Frank - added DataHandler concept
* \author David Frank - added DataHandler concept
, iterators
*
* \tparam data_t - data type that is stored in the DataContainer, defaulting to real_t.
*
...
...
@@ -208,6 +209,66 @@ namespace elsa
/// used for testing only and defined in test file
friend
int
useCount
<>
(
const
DataContainer
<
data_t
>&
dc
);
/// iterator for DataContainer (random access and continuous)
using
iterator
=
DataContainerIterator
<
DataContainer
<
data_t
>>
;
/// const iterator for DataContainer (random access and continuous)
using
const_iterator
=
ConstDataContainerIterator
<
DataContainer
<
data_t
>>
;
/// alias for reverse iterator
using
reverse_iterator
=
std
::
reverse_iterator
<
iterator
>
;
/// alias for const reverse iterator
using
const_reverse_iterator
=
std
::
reverse_iterator
<
const_iterator
>
;
/// returns iterator to the first element of the container
iterator
begin
();
/// returns const iterator to the first element of the container (cannot mutate data)
const_iterator
begin
()
const
;
/// returns const iterator to the first element of the container (cannot mutate data)
const_iterator
cbegin
()
const
;
/// returns iterator to one past the last element of the container
iterator
end
();
/// returns const iterator to one past the last element of the container (cannot mutate data)
const_iterator
end
()
const
;
/// returns const iterator to one past the last element of the container (cannot mutate data)
const_iterator
cend
()
const
;
/// returns reversed iterator to the last element of the container
reverse_iterator
rbegin
();
/// returns const reversed iterator to the last element of the container (cannot mutate data)
const_reverse_iterator
rbegin
()
const
;
/// returns const reversed iterator to the last element of the container (cannot mutate data)
const_reverse_iterator
crbegin
()
const
;
/// returns reversed iterator to one past the first element of container
reverse_iterator
rend
();
/// returns const reversed iterator to one past the first element of container (cannot mutate data)
const_reverse_iterator
rend
()
const
;
/// returns const reversed iterator to one past the first element of container (cannot mutate data)
const_reverse_iterator
crend
()
const
;
/// value_type of the DataContainer elements for iterators
using
value_type
=
data_t
;
/// pointer type of DataContainer elements for iterators
using
pointer
=
data_t
*
;
/// const pointer type of DataContainer elements for iterators
using
const_pointer
=
const
data_t
*
;
/// reference type of DataContainer elements for iterators
using
reference
=
data_t
&
;
/// const reference type of DataContainer elements for iterators
using
const_reference
=
const
data_t
&
;
/// difference type for iterators
using
difference_type
=
std
::
ptrdiff_t
;
private:
/// the current DataDescriptor
std
::
unique_ptr
<
DataDescriptor
>
_dataDescriptor
;
...
...
elsa/core/DataContainerIterator.h
0 → 100644
View file @
b29a17c5
#pragma once
#include <iterator>
namespace
elsa
::
detail
{
/**
* \brief iterator which uses a non-owning raw pointer to iterate over a container. The iterator is
* random access and assumes contiguous memory layout.
*
* \author David Frank - initial implementation
*
* \tparam T - the type of the container
*
* Note: comparing iterators from different containers is undefined behavior, so we do not check for it.
*/
template
<
typename
T
>
class
ptr_iterator
{
public:
/// alias for iterator type
using
self_type
=
ptr_iterator
;
/// the iterator category
using
iterator_category
=
std
::
random_access_iterator_tag
;
/// the value type of container elements
using
value_type
=
typename
T
::
value_type
;
/// pointer type of container elements
using
pointer
=
typename
T
::
pointer
;
/// reference type of container elements
using
reference
=
typename
T
::
reference
;
/// difference type of container
using
difference_type
=
typename
T
::
difference_type
;
/// constructor taking a non-owning pointer to the data
explicit
ptr_iterator
(
pointer
ptr
)
:
_ptr
(
ptr
)
{
}
/// de-referencing operator
reference
operator
*
()
{
return
*
_ptr
;
}
/// pointer access operator
pointer
operator
->
()
{
return
_ptr
;
}
/// subscript operator
reference
operator
[](
int
m
)
{
return
_ptr
[
m
];
}
/// prefix increment operator
self_type
operator
++
()
{
++
_ptr
;
return
*
this
;
}
/// postfix increment operator
self_type
operator
++
(
int
)
{
auto
i
=
*
this
;
++
_ptr
;
return
i
;
}
/// prefix decrement operator
self_type
operator
--
()
{
--
_ptr
;
return
*
this
;
}
/// postfix decrement operator
self_type
operator
--
(
int
)
{
auto
i
=
*
this
;
--
_ptr
;
return
i
;
}
/// moving iterator forward by n
self_type
&
operator
+=
(
int
n
)
{
_ptr
+=
n
;
return
*
this
;}
/// moving iterator backward by n
self_type
&
operator
-=
(
int
n
)
{
_ptr
-=
n
;
return
*
this
;}
/// return new iterator moved forward by n
self_type
operator
+
(
int
n
)
const
{
self_type
r
(
*
this
);
return
r
+=
n
;}
/// return new iterator moved backward by n
self_type
operator
-
(
int
n
)
const
{
self_type
r
(
*
this
);
return
r
-=
n
;}
/// return the difference between iterators
difference_type
operator
-
(
ptr_iterator
const
&
r
)
const
{
return
_ptr
-
r
.
_ptr
;
}
/// compare < with other iterator
bool
operator
<
(
const
ptr_iterator
&
r
)
const
{
return
_ptr
<
r
.
_ptr
;
}
/// compare <= with other iterator
bool
operator
<=
(
const
ptr_iterator
&
r
)
const
{
return
_ptr
<=
r
.
_ptr
;
}
/// compare > with other iterator
bool
operator
>
(
const
ptr_iterator
&
r
)
const
{
return
_ptr
>
r
.
_ptr
;
}
/// compare >= with other iterator
bool
operator
>=
(
const
ptr_iterator
&
r
)
const
{
return
_ptr
>=
r
.
_ptr
;
}
/// compare != with other iterator
bool
operator
!=
(
const
ptr_iterator
&
r
)
const
{
return
_ptr
!=
r
.
_ptr
;
}
/// compare == with other iterator
bool
operator
==
(
const
ptr_iterator
&
r
)
const
{
return
_ptr
==
r
.
_ptr
;
}
private:
/// non-owning (!) pointer to data (do not clean up or anything)
pointer
_ptr
{};
};
/**
* \brief constant iterator which uses a non-owning raw pointer to iterate over a container. The iterator is
* random access and assumes contiguous memory layout. It is const in the sense that it cannot mutate the state
* of the object it iterates over.
*
* \author David Frank - initial implementation
*
* \tparam T - the type of the container
*
* Note: comparing iterators from different containers is undefined behavior, so we do not check for it.
*/
template
<
typename
T
>
class
const_ptr_iterator
{
public:
/// alias for iterator type
using
self_type
=
const_ptr_iterator
;
/// the iterator category
using
iterator_category
=
std
::
random_access_iterator_tag
;
/// the value type of container elements
using
value_type
=
typename
T
::
value_type
;
/// pointer type of container elements
using
pointer
=
typename
T
::
const_pointer
;
/// reference type of container elements
using
reference
=
typename
T
::
const_reference
;
/// difference type of container
using
difference_type
=
typename
T
::
difference_type
;
/// constructor taking a non-owning pointer to the data
explicit
const_ptr_iterator
(
pointer
ptr
)
:
_ptr
(
ptr
)
{
}
/// de-referencing operator
reference
operator
*
()
{
return
*
_ptr
;
}
/// pointer access operator
pointer
operator
->
()
{
return
_ptr
;
}
/// subscript operator
reference
operator
[](
int
m
)
{
return
_ptr
[
m
];
}
/// prefix increment operator
self_type
operator
++
()
{
++
_ptr
;
return
*
this
;
}
/// postfix increment operator
self_type
operator
++
(
int
)
{
auto
i
=
*
this
;
++
_ptr
;
return
i
;
}
/// prefix decrement operator
self_type
operator
--
()
{
--
_ptr
;
return
*
this
;
}
/// postfix decrement operator
self_type
operator
--
(
int
)
{
auto
i
=
*
this
;
--
_ptr
;
return
i
;
}
/// moving iterator forward by n
self_type
&
operator
+=
(
int
n
)
{
_ptr
+=
n
;
return
*
this
;
}
/// moving iterator backward by n
self_type
&
operator
-=
(
int
n
)
{
_ptr
-=
n
;
return
*
this
;
}
/// return new iterator moved forward by n
self_type
operator
+
(
int
n
)
const
{
self_type
r
(
*
this
);
return
r
+=
n
;
}
/// return new iterator moved backward by n
self_type
operator
-
(
int
n
)
const
{
self_type
r
(
*
this
);
return
r
-=
n
;
}
/// return the difference between iterators
difference_type
operator
-
(
const_ptr_iterator
const
&
r
)
const
{
return
_ptr
-
r
.
_ptr
;
}
/// compare < with other iterator
bool
operator
<
(
const
self_type
&
r
)
const
{
return
_ptr
<
r
.
_ptr
;
}
/// compare <= with other iterator
bool
operator
<=
(
const
self_type
&
r
)
const
{
return
_ptr
<=
r
.
_ptr
;
}
/// compare > with other iterator
bool
operator
>
(
const
self_type
&
r
)
const
{
return
_ptr
>
r
.
_ptr
;
}
/// compare >= with other iterator
bool
operator
>=
(
const
self_type
&
r
)
const
{
return
_ptr
>=
r
.
_ptr
;
}
/// compare != with other iterator
bool
operator
!=
(
const
self_type
&
r
)
const
{
return
_ptr
!=
r
.
_ptr
;
}
/// compare == with other iterator
bool
operator
==
(
const
self_type
&
r
)
const
{
return
_ptr
==
r
.
_ptr
;
}
private:
/// non-owning (!) pointer to data (do not clean up or anything)
pointer
_ptr
{};
};
}
// end namespace elsa::detail
namespace
elsa
{
/// alias for the iterator for DataContainer
template
<
typename
T
>
using
DataContainerIterator
=
detail
::
ptr_iterator
<
T
>
;
/// alias for the constant iterator for DataContainer
template
<
typename
T
>
using
ConstDataContainerIterator
=
detail
::
const_ptr_iterator
<
T
>
;
}
// end namespace elsa
elsa/core/tests/test_DataContainer.cpp
View file @
b29a17c5
...
...
@@ -473,4 +473,160 @@ SCENARIO("Testing the copy-on-write mechanism") {
}
}
}
}
SCENARIO
(
"Testing iterators for DataContainer"
)
{
GIVEN
(
"A 1D container"
)
{
constexpr
index_t
size
=
20
;
IndexVector_t
numCoeff
(
1
);
numCoeff
<<
size
;
DataDescriptor
desc
(
numCoeff
);
DataContainer
dc1
(
desc
);
DataContainer
dc2
(
desc
);
Eigen
::
VectorXf
randVec1
=
Eigen
::
VectorXf
::
Random
(
size
);
Eigen
::
VectorXf
randVec2
=
Eigen
::
VectorXf
::
Random
(
size
);
for
(
index_t
i
=
0
;
i
<
size
;
++
i
)
{
dc1
[
i
]
=
randVec1
(
i
);
dc2
[
i
]
=
randVec2
(
i
);
}
THEN
(
"We can iterate forward"
)
{
int
i
=
0
;
for
(
auto
v
=
dc1
.
cbegin
();
v
!=
dc1
.
cend
();
v
++
)
{
REQUIRE
(
*
v
==
randVec1
[
i
++
]);
}
REQUIRE
(
i
==
size
);
}
THEN
(
"We can iterate backward"
)
{
int
i
=
size
;
for
(
auto
v
=
dc1
.
crbegin
();
v
!=
dc1
.
crend
();
v
++
)
{
REQUIRE
(
*
v
==
randVec1
[
--
i
]);
}
REQUIRE
(
i
==
0
);
}
THEN
(
"We can iterate and mutate"
)
{
int
i
=
0
;
for
(
auto
&
v
:
dc1
)
{
v
=
v
*
2
;
REQUIRE
(
v
==
2
*
randVec1
[
i
++
]);
}
REQUIRE
(
i
==
size
);
i
=
0
;
for
(
auto
v
:
dc1
)
{
REQUIRE
(
v
==
2
*
randVec1
[
i
++
]);
}
REQUIRE
(
i
==
size
);
}
THEN
(
"We can use STL algorithms"
)
{
REQUIRE
(
*
std
::
min_element
(
dc1
.
cbegin
(),
dc1
.
cend
())
==
randVec1
.
minCoeff
());
REQUIRE
(
*
std
::
max_element
(
dc1
.
cbegin
(),
dc1
.
cend
())
==
randVec1
.
maxCoeff
());
}
}
GIVEN
(
"A 2D container"
)
{
constexpr
index_t
size
=
20
;
IndexVector_t
numCoeff
(
2
);
numCoeff
<<
size
,
size
;
DataDescriptor
desc
(
numCoeff
);
DataContainer
dc1
(
desc
);
Eigen
::
VectorXf
randVec1
=
Eigen
::
VectorXf
::
Random
(
size
*
size
);
for
(
index_t
i
=
0
;
i
<
dc1
.
getSize
();
++
i
)
{
dc1
[
i
]
=
randVec1
[
i
];
}
THEN
(
"We can iterate forward"
)
{
int
i
=
0
;
for
(
auto
v
:
dc1
)
{
REQUIRE
(
v
==
randVec1
[
i
++
]);
}
REQUIRE
(
i
==
size
*
size
);
}
THEN
(
"We can iterate backward"
)
{
int
i
=
size
*
size
;
for
(
auto
v
=
dc1
.
crbegin
();
v
!=
dc1
.
crend
();
v
++
)
{
REQUIRE
(
*
v
==
randVec1
[
--
i
]);
}
REQUIRE
(
i
==
0
);
}
THEN
(
"We can iterate and mutate"
)
{
int
i
=
0
;
for
(
auto
&
v
:
dc1
)
{
v
=
v
*
2
;
REQUIRE
(
v
==
2
*
randVec1
[
i
++
]);
}
REQUIRE
(
i
==
size
*
size
);
i
=
0
;
for
(
auto
v
:
dc1
)
{
REQUIRE
(
v
==
2
*
randVec1
[
i
++
]);
}
REQUIRE
(
i
==
size
*
size
);
}
THEN
(
"We can use STL algorithms"
)
{
REQUIRE
(
*
std
::
min_element
(
dc1
.
cbegin
(),
dc1
.
cend
())
==
randVec1
.
minCoeff
());
REQUIRE
(
*
std
::
max_element
(
dc1
.
cbegin
(),
dc1
.
cend
())
==
randVec1
.
maxCoeff
());
}
}
GIVEN
(
"A 3D container"
)
{
constexpr
index_t
size
=
20
;
IndexVector_t
numCoeff
(
3
);
numCoeff
<<
size
,
size
,
size
;
DataDescriptor
desc
(
numCoeff
);
DataContainer
dc1
(
desc
);
Eigen
::
VectorXf
randVec1
=
Eigen
::
VectorXf
::
Random
(
size
*
size
*
size
);
for
(
index_t
i
=
0
;
i
<
dc1
.
getSize
();
++
i
)
{
dc1
[
i
]
=
randVec1
[
i
];
}
THEN
(
"We can iterate forward"
)
{
int
i
=
0
;
for
(
auto
v
:
dc1
)
{
REQUIRE
(
v
==
randVec1
[
i
++
]);
}
REQUIRE
(
i
==
size
*
size
*
size
);
}
THEN
(
"We can iterate backward"
)
{
int
i
=
size
*
size
*
size
;
for
(
auto
v
=
dc1
.
crbegin
();
v
!=
dc1
.
crend
();
v
++
)
{
REQUIRE
(
*
v
==
randVec1
[
--
i
]);
}
REQUIRE
(
i
==
0
);
}
THEN
(
"We can iterate and mutate"
)
{
int
i
=
0
;
for
(
auto
&
v
:
dc1
)
{
v
=
v
*
2
;
REQUIRE
(
v
==
2
*
randVec1
[
i
++
]);
}
REQUIRE
(
i
==
size
*
size
*
size
);
i
=
0
;
for
(
auto
v
:
dc1
)
{
REQUIRE
(
v
==
2
*
randVec1
[
i
++
]);
}
REQUIRE
(
i
==
size
*
size
*
size
);
}
THEN
(
"We can use STL algorithms"
)
{
REQUIRE
(
*
std
::
min_element
(
dc1
.
cbegin
(),
dc1
.
cend
())
==
randVec1
.
minCoeff
());
REQUIRE
(
*
std
::
max_element
(
dc1
.
cbegin
(),
dc1
.
cend
())
==
randVec1
.
maxCoeff
());
}
}
}
\ No newline at end of file
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