Mentions légales du service
Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
ScalFMM
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
solverstack
ScalFMM
Commits
4dec09ef
Commit
4dec09ef
authored
9 years ago
by
Quentin Khan
Browse files
Options
Downloads
Patches
Plain Diff
Add NodeIterator base class
parent
f81be4b4
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
Src/Adaptive/new/FNodeIterator.hpp
+258
-0
258 additions, 0 deletions
Src/Adaptive/new/FNodeIterator.hpp
Tests/noDist/Adaptive/test_FNodeIterator.cpp
+191
-0
191 additions, 0 deletions
Tests/noDist/Adaptive/test_FNodeIterator.cpp
with
449 additions
and
0 deletions
Src/Adaptive/new/FNodeIterator.hpp
0 → 100644
+
258
−
0
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
This diff is collapsed.
Click to expand it.
Tests/noDist/Adaptive/test_FNodeIterator.cpp
0 → 100644
+
191
−
0
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
();
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment