Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
solverstack
ScalFMM
Commits
a01d0d40
Commit
a01d0d40
authored
Jan 25, 2016
by
Quentin Khan
Browse files
Add FNode in order iterator implementation
parent
8f4ca7e1
Changes
2
Hide whitespace changes
Inline
Side-by-side
Src/Adaptive/new/FInOrderNodeIterator.hpp
0 → 100644
View file @
a01d0d40
#ifndef _SCALFMM_IN_ORDER_NODE_ITERATOR_HPP_
#define _SCALFMM_IN_ORDER_NODE_ITERATOR_HPP_
#include "FNodeIterator.hpp"
namespace
scalfmm
{
namespace
tests
{
struct
test_InOrderNodeIterator
;
}
}
template
<
class
Node
>
class
FInOrderNodeIterator
:
public
FNodeIterator
<
FInOrderNodeIterator
<
Node
>
,
Node
>
{
using
base_t
=
FNodeIterator
<
FInOrderNodeIterator
<
Node
>
,
Node
>
;
using
Direction
=
typename
base_t
::
Direction
;
friend
scalfmm
::
tests
::
test_InOrderNodeIterator
;
friend
base_t
;
public:
using
base_t
::
base_t
;
using
base_t
::
operator
++
;
using
base_t
::
operator
--
;
FInOrderNodeIterator
&
operator
++
()
{
return
move_iterator
<
Direction
::
forwards
>
();
}
FInOrderNodeIterator
&
operator
--
()
{
return
move_iterator
<
Direction
::
backwards
>
();
}
private:
/** Indicates the index of the middle child */
template
<
Direction
dir
>
typename
base_t
::
index_t
mid_idx
()
const
{
if
(
dir
==
Direction
::
forwards
)
{
// Compile time optimisation will remove unused branch
return
(
base_t
::
child_count
/
2
)
-
1
;
}
else
{
return
(
base_t
::
child_count
/
2
);
}
}
/** Moves the cursor to the first node
*
* Resets the iterator to a valid state.
*/
template
<
Direction
dir
>
FInOrderNodeIterator
&
move_to_boundary
()
{
base_t
::
template
goto_root
<
dir
>();
while
(
!
this
->
_cur
->
is_leaf
())
{
base_t
::
template
move_down
<
dir
>();
}
return
*
this
;
}
template
<
Direction
dir
>
FInOrderNodeIterator
&
leaf_next
()
{
// Leave current leaf
if
(
!
this
->
_cur_state
.
empty
())
{
base_t
::
move_up
();
}
// If we visited half the parent's children, stay on the parent
if
(
!
this
->
_cur_state
.
empty
()
&&
mid_idx
<
dir
>
()
==
this
->
_cur_state
.
back
())
{
return
*
this
;
}
// If we visited all the children of the node, we move up
while
(
!
this
->
_cur_state
.
empty
()
&&
base_t
::
template
at_last_child
<
dir
>())
{
base_t
::
move_up
();
}
// Moving too far up means we got to the end of the tree
if
(
this
->
_cur_state
.
empty
())
{
base_t
::
template
set_end
<
dir
>();
return
*
this
;
}
// Once we moved up enough, we move down to the next leaf
while
(
!
this
->
_cur
->
is_leaf
())
{
base_t
::
template
move_down
<
dir
>();
}
return
*
this
;
}
template
<
Direction
dir
>
FInOrderNodeIterator
&
node_next
()
{
// If we are on an internal node, we move down to the children
if
(
dir
==
Direction
::
forwards
)
{
// Compile time optimisation will remove unused branch
this
->
_cur_state
.
back
()
=
static_cast
<
char
>
(
mid_idx
<
dir
>
()
+
1
);
}
else
{
this
->
_cur_state
.
back
()
=
static_cast
<
char
>
(
mid_idx
<
dir
>
()
-
1
);
}
this
->
_cur
=
this
->
_cur
->
getChild
((
std
::
size_t
)
this
->
_cur_state
.
back
());
this
->
_cur_state
.
push_back
(
base_t
::
template
first_idx
<
dir
>());
while
(
!
this
->
_cur
->
is_leaf
())
{
base_t
::
template
move_down
<
dir
>();
}
return
*
this
;
}
template
<
Direction
dir
>
FInOrderNodeIterator
&
move_iterator
()
{
// If before the beginning, move to the first node
if
(
base_t
::
template
is_other_end
<
dir
>())
{
return
move_to_boundary
<
dir
>
();
}
// Don't move if already past the end
if
(
base_t
::
template
is_end
<
dir
>())
{
return
*
this
;
}
if
(
this
->
_cur
->
is_leaf
())
{
return
leaf_next
<
dir
>
();
}
else
{
return
node_next
<
dir
>
();
}
}
};
#endif
Tests/noDist/Adaptive/test_FInOrderNodeIterator.cpp
0 → 100644
View file @
a01d0d40
#include <cassert>
#include <iterator>
#include "test_Abstract.hpp"
#include "MockParticle.hpp"
#include "Adaptive/new/FTree.hpp"
#include "Adaptive/new/FNode.hpp"
#include "Adaptive/new/FInOrderNodeIterator.hpp"
#include "Utils/make_unique.hpp"
namespace
scalfmm
{
namespace
tests
{
struct
test_InOrderNodeIterator
:
public
test_Abstract
<
test_InOrderNodeIterator
>
{
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
;
using
iterator_t
=
FInOrderNodeIterator
<
node_t
>
;
tree_t
*
tree
=
nullptr
;
node_t
*
root
=
nullptr
;
box_t
box
{{
0
,
0
,
0
},
100
};
public:
/** Sets up a tree in which only the root node and its second child
* have children.
*
* 0 ___________________o____ ...
* | | | |
* 1 o ___o____ o o ...
* ||||||||
* 2 oooooooo
*/
void
set_up
()
{
assert
(
nullptr
==
tree
);
tree
=
new
tree_t
(
box
);
root
=
tree
->
root
();
root
->
split
();
root
->
getChild
(
1
)
->
split
();
}
void
tear_down
()
{
delete
tree
;
tree
=
nullptr
;
root
=
nullptr
;
}
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_prefix_increment
);
RUN
(
test_prefix_decrement
);
RUN
(
test_incr_inverse_decr
);
RUN
(
test_single_node_tree
);
}
/** Tested for NodeIterator, testing that it is correctly accessible */
void
test_constructor_default
()
{
iterator_t
a
;
assert
(
a
.
_root
==
nullptr
);
assert
(
a
.
_cur
==
nullptr
);
assert
(
a
.
_is_end
==
false
);
assert
(
a
.
_is_rend
==
false
);
}
void
test_constructor_custom
()
{
iterator_t
a
(
root
);
assert
(
a
.
_root
==
root
);
assert
(
a
.
_cur
==
root
->
getChild
(
0
));
assert
(
a
.
_is_end
==
false
);
assert
(
a
.
_is_rend
==
false
);
assert
(
a
.
_cur_state
==
decltype
(
a
.
_cur_state
)
({
0
,
-
1
}));
}
/** Tested for NodeIterator, testing that it is correctly accessible */
void
test_constructor_copy
()
{
iterator_t
a
(
root
);
iterator_t
b
(
a
);
}
/** Tested for NodeIterator, testing that it is correctly accessible */
void
test_constructor_move
()
{
auto
a
=
std
::
make_unique
<
iterator_t
>
(
root
);
iterator_t
b
(
std
::
move
(
*
a
));
}
/** Tested for NodeIterator, testing that it is correctly accessible */
void
test_operator_copy
()
{
iterator_t
a
(
root
);
iterator_t
b
;
b
=
a
;
}
/** Tested for NodeIterator, testing that it is correctly accessible */
void
test_operator_move
()
{
auto
a
=
std
::
make_unique
<
iterator_t
>
(
root
);
iterator_t
b
;
b
=
std
::
move
(
*
a
);
}
/** Tests a single node tree */
void
test_single_node_tree
()
{
tree_t
stree
(
box
);
node_t
*
sroot
=
stree
.
root
();
iterator_t
it
(
sroot
);
assert
(
it
.
operator
->
()
==
sroot
);
assert
(
it
.
_is_end
==
false
);
assert
(
it
.
_is_rend
==
false
);
++
it
;
assert
(
it
.
_is_end
==
true
);
assert
(
it
.
_is_rend
==
false
);
--
it
;
assert
(
it
.
operator
->
()
==
sroot
);
--
it
;
assert
(
it
.
_is_end
==
false
);
assert
(
it
.
_is_rend
==
true
);
++
it
;
assert
(
it
.
operator
->
()
==
sroot
);
assert
(
it
.
_is_end
==
false
);
assert
(
it
.
_is_rend
==
false
);
}
/** Walks the tree, checking each step */
void
test_prefix_increment
()
{
iterator_t
it
(
root
);
assert
(
root
->
getChild
(
0
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
0
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
1
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
2
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
3
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
1
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
4
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
5
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
6
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
7
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
2
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
3
)
==
&
(
*
it
));
++
it
;
assert
(
root
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
4
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
5
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
6
)
==
&
(
*
it
));
++
it
;
assert
(
root
->
getChild
(
7
)
==
&
(
*
it
));
iterator_t
it2
(
++
it
);
++
it
;
assert
(
it2
==
it
);
assert
(
it2
.
_is_end
==
true
);
assert
(
it2
.
_is_rend
==
false
);
}
/** Moves iterator past the end and plays back the walk */
void
test_prefix_decrement
()
{
iterator_t
it
(
root
);
for
(
int
i
=
0
;
i
<
17
;
++
i
)
{
++
it
;
}
assert
(
it
.
_is_end
==
true
);
--
it
;
assert
(
it
.
_is_end
==
false
);
assert
(
root
->
getChild
(
7
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
6
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
5
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
4
)
==
&
(
*
it
));
--
it
;
assert
(
root
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
3
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
2
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
7
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
6
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
5
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
4
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
1
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
3
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
2
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
1
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
1
)
->
getChild
(
0
)
==
&
(
*
it
));
--
it
;
assert
(
root
->
getChild
(
0
)
==
&
(
*
it
));
--
it
;
assert
(
it
.
_is_rend
==
true
);
}
void
test_incr_inverse_decr
()
{
iterator_t
it
(
root
);
while
(
!
(
it
).
_is_end
)
{
auto
cur
=
it
.
_cur
;
++
it
;
auto
cur2
=
it
.
_cur
;
--
it
;
assert
(
cur
==
it
.
_cur
);
++
it
;
assert
(
cur2
==
it
.
_cur
);
}
while
(
!
(
it
).
_is_rend
)
{
auto
cur
=
it
.
_cur
;
--
it
;
auto
cur2
=
it
.
_cur
;
++
it
;
assert
(
cur
==
it
.
_cur
);
--
it
;
assert
(
cur2
==
it
.
_cur
);
}
}
};
}
}
int
main
()
{
scalfmm
::
tests
::
test_InOrderNodeIterator
().
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