Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
ScalFMM
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
5
Issues
5
List
Boards
Labels
Service Desk
Milestones
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
solverstack
ScalFMM
Commits
4dec09ef
Commit
4dec09ef
authored
Jan 25, 2016
by
Quentin Khan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add NodeIterator base class
parent
f81be4b4
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
449 additions
and
0 deletions
+449
-0
Src/Adaptive/new/FNodeIterator.hpp
Src/Adaptive/new/FNodeIterator.hpp
+258
-0
Tests/noDist/Adaptive/test_FNodeIterator.cpp
Tests/noDist/Adaptive/test_FNodeIterator.cpp
+191
-0
No files found.
Src/Adaptive/new/FNodeIterator.hpp
0 → 100644
View file @
4dec09ef
#ifndef _SCALFMM_NODE_ITERATOR_HPP_
#define _SCALFMM_NODE_ITERATOR_HPP_
#include <vector>
#include "Utils/FConstFuncs.hpp"
namespace
scalfmm
{
namespace
tests
{
struct
test_NodeIterator
;
}
}
template
<
class
Derived
,
class
Node
>
class
FNodeIterator
{
public:
friend
struct
scalfmm
::
tests
::
test_NodeIterator
;
using
node_t
=
Node
;
// Iterator types
using
value_type
=
node_t
;
using
difference_type
=
std
::
ptrdiff_t
;
using
pointer
=
node_t
*
;
using
reference
=
node_t
&
;
using
iterator_category
=
std
::
bidirectional_iterator_tag
;
constexpr
static
std
::
size_t
child_count
=
node_t
::
child_count
;
enum
class
IteratorPosition
{
begin
,
end
,
reverse_end
};
protected:
enum
class
Direction
{
forwards
,
backwards
};
using
state_container
=
std
::
vector
<
char
>
;
using
index_t
=
typename
state_container
::
value_type
;
/// Root node for the graph walk
/** \warning This may not be the first node of the walk. */
node_t
*
_root
=
nullptr
;
/// Current node for the graph walk
node_t
*
_cur
=
nullptr
;
/** Current state in the walk
* Contains the indexes of the next children to visit per level
* in the currently visited tree branch.
*/
state_container
_cur_state
;
/// Special past_the_end iterator status
bool
_is_end
=
false
;
/// Special past_the_reverse_end iterator status
bool
_is_rend
=
false
;
public:
/// Main constructor
/**
* \param root The graph root node before walking accross it.
*
* \warning This constructor must be completed by the derived class.
* It does not set #_cur nor #_cur_state to the right value. */
FNodeIterator
(
node_t
*
root
,
IteratorPosition
p
=
IteratorPosition
::
begin
)
:
_root
(
root
),
_is_end
(
p
==
IteratorPosition
::
end
),
_is_rend
(
p
==
IteratorPosition
::
reverse_end
)
{
if
(
!
_is_end
&&
!
_is_rend
)
{
static_cast
<
Derived
*>
(
this
)
->
template
move_to_boundary
<
Direction
::
forwards
>();
}
}
/// Default constructor
/** Such a constructed iterator is not in a valid state. */
FNodeIterator
()
=
default
;
/// Copy constructor
FNodeIterator
(
const
FNodeIterator
&
other
)
=
default
;
/// Copy assignment
FNodeIterator
&
operator
=
(
const
FNodeIterator
&
other
)
=
default
;
/// Move constructor
FNodeIterator
(
FNodeIterator
&&
other
)
=
default
;
/// Move assignment
FNodeIterator
&
operator
=
(
FNodeIterator
&&
other
)
=
default
;
/// Destructor
~
FNodeIterator
()
=
default
;
/// Swap operation
void
swap
(
FNodeIterator
&&
other
)
noexcept
{
#define _MY_SWAP_(a) {auto tmp = a; a = other.a; other.a = tmp;}
_MY_SWAP_
(
_root
);
_MY_SWAP_
(
_cur
);
_MY_SWAP_
(
_is_end
);
_MY_SWAP_
(
_is_rend
);
_cur_state
.
swap
(
other
.
_cur_state
);
#undef _MY_SWAP_
}
/// Dereference operator
node_t
&
operator
*
()
{
return
*
_cur
;
}
/// Dereference const operator
const
node_t
&
operator
*
()
const
{
return
*
_cur
;
}
/// Pointer dereference operator
node_t
*
operator
->
()
{
return
_cur
;
}
/// Pointer const dereference operator
const
node_t
*
operator
->
()
const
{
return
_cur
;
}
/// Prefix increment
//virtual FNodeIterator& operator++() = 0;
/// Postfix increment
Derived
operator
++
(
int
)
{
Derived
it
(
static_cast
<
Derived
&>
(
*
this
));
++
static_cast
<
Derived
&>
(
*
this
);
return
it
;
}
/// Prefix decrement
//virtual FNodeIterator& operator--() = 0;
/// Postfix decrement
Derived
operator
--
(
int
)
{
Derived
it
(
static_cast
<
Derived
&>
(
*
this
));
--
static_cast
<
Derived
&>
(
*
this
);
return
it
;
}
/// Equality operator
friend
bool
operator
==
(
const
FNodeIterator
&
lhs
,
const
FNodeIterator
&
rhs
)
{
#define _TEST_EQ(name) (lhs.name == rhs.name)
return
_TEST_EQ
(
_root
)
&&
_TEST_EQ
(
_cur
)
&&
_TEST_EQ
(
_is_end
)
&&
_TEST_EQ
(
_is_rend
);
#undef _TEST_EQ
}
/// Inequality operator
friend
bool
operator
!=
(
const
FNodeIterator
&
lhs
,
const
FNodeIterator
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
friend
Derived
operator
+=
(
Derived
lhs
,
difference_type
n
)
{
if
(
n
<
0
)
{
for
(;
n
!=
0
;
++
n
,
--
lhs
);
}
if
(
n
>
0
)
{
for
(;
n
!=
0
;
--
n
,
++
lhs
);
}
return
lhs
;
}
friend
Derived
operator
-=
(
const
Derived
&
lhs
,
difference_type
n
)
{
return
operator
+=
(
lhs
,
-
n
);
}
friend
Derived
operator
+
(
const
Derived
&
lhs
,
difference_type
n
)
{
return
lhs
+=
n
;
}
friend
Derived
operator
-
(
const
Derived
&
lhs
,
difference_type
n
)
{
return
operator
+=
(
lhs
,
-
n
);
}
protected:
// Methods used in all subclasses
template
<
Direction
dir
>
void
goto_root
()
{
this
->
_is_rend
=
false
;
this
->
_is_end
=
false
;
this
->
_cur
=
this
->
_root
;
this
->
_cur_state
.
clear
();
this
->
_cur_state
.
push_back
(
first_idx
<
dir
>
());
}
/** Returns the end flag corresponding to the direction */
template
<
Direction
dir
>
bool
is_end
()
{
return
dir
==
Direction
::
forwards
?
this
->
_is_end
:
this
->
_is_rend
;
}
/** Returns the end flag corresponding to the oposite direction */
template
<
Direction
dir
>
bool
is_other_end
()
{
return
dir
==
Direction
::
forwards
?
this
->
_is_rend
:
this
->
_is_end
;
}
/** Sets the end flag according to the direction */
template
<
Direction
dir
>
void
set_end
()
{
if
(
dir
==
Direction
::
forwards
)
{
this
->
_is_end
=
true
;
}
else
{
this
->
_is_rend
=
true
;
}
}
/** Returns the first index to insert in #_cur_state */
template
<
Direction
dir
>
index_t
first_idx
()
const
{
return
dir
==
Direction
::
forwards
?
-
1
:
(
index_t
)
Node
::
child_count
;
}
/** Indicates whether the last child of a node has been visited */
template
<
Direction
dir
>
bool
at_last_child
()
const
{
if
(
dir
==
Direction
::
forwards
)
{
// Compile time optimisation will remove unused branch
return
Node
::
child_count
-
1
==
this
->
_cur_state
.
back
();
}
else
{
return
0
==
this
->
_cur_state
.
back
();
}
}
/** Moves the cursor to its parent
*
* \warning Undefined behaviour when the cursor points to a leaf.
*/
void
move_up
()
{
this
->
_cur_state
.
pop_back
();
this
->
_cur
=
this
->
_cur
->
getParent
();
}
/** Moves the cursor to the next child to visit
*
* \warning Undefined behaviour when the cursor points to a leaf.
*/
template
<
Direction
dir
>
void
move_down
()
{
if
(
dir
==
Direction
::
forwards
)
{
// Compile time optimisation will remove unused branch
++
(
this
->
_cur_state
.
back
());
}
else
{
--
(
this
->
_cur_state
.
back
());
}
this
->
_cur
=
this
->
_cur
->
getChild
((
std
::
size_t
)
this
->
_cur_state
.
back
());
this
->
_cur_state
.
push_back
(
first_idx
<
dir
>
());
}
};
template
<
class
Derived
,
class
Node
>
void
swap
(
FNodeIterator
<
Derived
,
Node
>&
it1
,
FNodeIterator
<
Derived
,
Node
>&
it2
)
{
it1
.
swap
(
it2
);
}
#endif
Tests/noDist/Adaptive/test_FNodeIterator.cpp
0 → 100644
View file @
4dec09ef
#include <cassert>
#include "test_Abstract.hpp"
#include "MockParticle.hpp"
#include "Adaptive/new/FTree.hpp"
#include "Adaptive/new/FNode.hpp"
#include "Adaptive/new/FNodeIterator.hpp"
#include "Utils/make_unique.hpp"
namespace
scalfmm
{
namespace
tests
{
struct
test_NodeIterator
:
public
test_Abstract
<
test_NodeIterator
>
{
using
Real
=
double
;
constexpr
static
std
::
size_t
Dim
=
3
;
using
tree_t
=
FTree
<
std
::
vector
<
MockParticle
<
Real
,
Dim
>
>
,
NodeEmptyData
>
;
using
node_t
=
typename
tree_t
::
node_t
;
using
box_t
=
typename
tree_t
::
box_t
;
struct
test_iterator
:
public
FNodeIterator
<
test_iterator
,
node_t
>
{
using
base_t
=
FNodeIterator
<
test_iterator
,
node_t
>
;
int
pp
=
0
;
int
mm
=
0
;
using
base_t
::
base_t
;
using
base_t
::
operator
++
;
using
base_t
::
operator
--
;
template
<
base_t
::
Direction
>
void
move_to_boundary
()
{}
test_iterator
&
operator
++
(){
++
pp
;
return
*
this
;}
test_iterator
&
operator
--
(){
++
mm
;
return
*
this
;}
};
tree_t
*
tree
=
nullptr
;
node_t
*
root
=
nullptr
;
box_t
box
{{
0
,
0
,
0
},
100
};
public:
void
set_up
()
{
assert
(
nullptr
==
tree
);
tree
=
new
tree_t
(
box
);
root
=
tree
->
root
();
// Allocated by tree constructor
}
void
tear_down
()
{
delete
tree
;
tree
=
nullptr
;
root
=
nullptr
;
// Deleted by tree destructor
}
void
run_all
()
{
RUN
(
test_constructor_default
);
RUN
(
test_constructor_custom
);
RUN
(
test_constructor_copy
);
RUN
(
test_constructor_move
);
RUN
(
test_operator_copy
);
RUN
(
test_operator_move
);
RUN
(
test_operator_dereference
);
RUN
(
test_increment_postfix
);
RUN
(
test_decrement_postfix
);
}
void
test_constructor_default
()
{
test_iterator
a
;
assert
(
a
.
_root
==
nullptr
);
assert
(
a
.
_cur
==
nullptr
);
assert
(
a
.
_is_end
==
false
);
assert
(
a
.
_is_rend
==
false
);
}
void
test_constructor_custom
()
{
test_iterator
a
(
root
);
assert
(
a
.
_root
==
root
);
assert
(
a
.
_is_end
==
false
);
assert
(
a
.
_is_rend
==
false
);
}
void
test_constructor_copy
()
{
test_iterator
a
(
root
);
a
.
_is_end
=
true
;
a
.
_is_rend
=
true
;
test_iterator
b
(
a
);
assert
(
a
.
_root
==
b
.
_root
);
assert
(
a
.
_cur
==
b
.
_cur
);
assert
(
a
.
_is_end
==
b
.
_is_end
);
assert
(
a
.
_is_rend
==
b
.
_is_rend
);
assert
(
a
.
_cur_state
==
b
.
_cur_state
);
}
void
test_constructor_move
()
{
auto
a
=
std
::
make_unique
<
test_iterator
>
(
root
);
a
->
_is_end
=
true
;
a
->
_is_rend
=
true
;
auto
_root
=
a
->
_root
;
auto
_cur
=
a
->
_cur
;
auto
_cur_state
=
a
->
_cur_state
;
auto
_is_end
=
a
->
_is_end
;
auto
_is_rend
=
a
->
_is_rend
;
test_iterator
b
(
std
::
move
(
*
a
));
assert
(
_root
==
b
.
_root
);
assert
(
_cur
==
b
.
_cur
);
assert
(
_is_end
==
b
.
_is_end
);
assert
(
_is_rend
==
b
.
_is_rend
);
assert
(
_cur_state
==
b
.
_cur_state
);
}
void
test_operator_copy
()
{
test_iterator
a
(
root
);
a
.
_is_end
=
true
;
a
.
_is_rend
=
true
;
test_iterator
b
;
b
=
a
;
assert
(
a
.
_root
==
b
.
_root
);
assert
(
a
.
_cur
==
b
.
_cur
);
assert
(
a
.
_is_end
==
b
.
_is_end
);
assert
(
a
.
_is_rend
==
b
.
_is_rend
);
assert
(
a
.
_cur_state
==
b
.
_cur_state
);
}
void
test_operator_move
()
{
auto
a
=
std
::
make_unique
<
test_iterator
>
(
root
);
a
->
_is_end
=
true
;
a
->
_is_rend
=
true
;
auto
_root
=
a
->
_root
;
auto
_cur
=
a
->
_cur
;
auto
_cur_state
=
a
->
_cur_state
;
auto
_is_end
=
a
->
_is_end
;
auto
_is_rend
=
a
->
_is_rend
;
test_iterator
b
;
b
=
std
::
move
(
*
a
);
assert
(
_root
==
b
.
_root
);
assert
(
_cur
==
b
.
_cur
);
assert
(
_is_end
==
b
.
_is_end
);
assert
(
_is_rend
==
b
.
_is_rend
);
assert
(
_cur_state
==
b
.
_cur_state
);
}
void
test_operator_dereference
()
{
test_iterator
a
(
root
);
a
.
_cur
=
root
;
assert
(
&
(
*
a
)
==
root
);
const
test_iterator
b
(
a
);
assert
(
&
(
*
b
)
==
root
);
auto
c
=
std
::
make_unique
<
test_iterator
>
(
a
);
assert
(
&
((
*
c
)
->
getTree
())
==
tree
);
auto
d
=
std
::
make_unique
<
const
test_iterator
>
(
a
);
assert
(
&
((
*
d
)
->
getTree
())
==
tree
);
}
void
test_increment_postfix
()
{
test_iterator
a
(
root
);
int
plus
=
(
a
++
).
pp
;
assert
(
plus
==
0
);
assert
(
a
.
pp
==
1
);
}
void
test_decrement_postfix
()
{
test_iterator
a
(
root
);
int
minus
=
(
a
--
).
mm
;
assert
(
minus
==
0
);
assert
(
a
.
mm
==
1
);
}
};
}
}
int
main
()
{
scalfmm
::
tests
::
test_NodeIterator
().
run_all
();
}
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