NEST  2.6.0,not_revisioned_source_dir@0
ntree_impl.h
Go to the documentation of this file.
1 /*
2  * ntree_impl.h
3  *
4  * This file is part of NEST.
5  *
6  * Copyright (C) 2004 The NEST Initiative
7  *
8  * NEST is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * NEST is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #ifndef NTREE_IMPL_H
24 #define NTREE_IMPL_H
25 
26 #include "ntree.h"
27 #include "mask.h"
28 
29 namespace nest {
30 
31  template<int D, class T, int max_capacity, int max_depth>
33  ntree_(&q), top_(&q), node_(0)
34  {
35  // First leaf
36  while(!ntree_->is_leaf())
37  ntree_ = ntree_->children_[0];
38 
39  // Find the first non-empty leaf
40  while( ntree_->nodes_.empty() ) {
41 
42  next_leaf_();
43  if (ntree_ == 0) break;
44 
45  }
46  }
47 
48  template<int D, class T, int max_capacity, int max_depth>
50  {
51  node_++;
52 
53  while (node_ >= ntree_->nodes_.size()) {
54 
55  next_leaf_();
56 
57  node_ = 0;
58 
59  if (ntree_ == 0) break;
60 
61  }
62 
63  return *this;
64  }
65 
66  template<int D, class T, int max_capacity, int max_depth>
68  {
69 
70  // If we are on the last subntree, move up
71  while(ntree_ && (ntree_ != top_) && (ntree_->my_subquad_ == N-1)) {
72  ntree_ = ntree_->parent_;
73  }
74 
75  // Since we stop at the top, this should never happen!
76  assert(ntree_ != 0);
77 
78  // If we have reached the top, mark as invalid and return
79  if (ntree_ == top_) {
80  ntree_ = 0;
81  return;
82  }
83 
84  // Move to next sibling
85  ntree_ = ntree_->parent_->children_[ntree_->my_subquad_+1];
86 
87  // Move down if this is not a leaf.
88  while(!ntree_->is_leaf())
89  ntree_ = ntree_->children_[0];
90 
91  }
92 
93  // Proper mod which returns non-negative numbers
94  static inline double_t mod(double_t x, double_t p)
95  {
96  x = std::fmod(x,p);
97  if (x<0)
98  x += p;
99  return x;
100  }
101 
102  template<int D, class T, int max_capacity, int max_depth>
104  ntree_(&q), top_(&q), allin_top_(0), node_(0), mask_(&mask), anchor_(anchor), anchors_(), current_anchor_(0)
105  {
106  if (ntree_->periodic_.any()) {
107  Box<D> mask_bb = mask_->get_bbox();
108 
109  // Move lower left corner of mask into main image of layer
110  for(int i=0;i<D;++i) {
111  if (ntree_->periodic_[i]) {
112  anchor_[i] = nest::mod(anchor_[i] + mask_bb.lower_left[i] - ntree_->lower_left_[i], ntree_->extent_[i]) - mask_bb.lower_left[i] + ntree_->lower_left_[i];
113  }
114  }
115  anchors_.push_back(anchor_);
116 
117  // Add extra anchors for each dimension where this is needed
118  // (Assumes that the mask is not wider than the layer)
119  for(int i=0;i<D;++i) {
120  if (ntree_->periodic_[i]) {
121  int n = anchors_.size();
122  if ((anchor_[i] + mask_bb.upper_right[i] - ntree_->lower_left_[i]) > ntree_->extent_[i]) {
123  for(int j=0;j<n;++j) {
124  Position<D> p = anchors_[j];
125  p[i] -= ntree_->extent_[i];
126  anchors_.push_back(p);
127  }
128  }
129  }
130  }
131 /*
132  for(int i=0;i<anchors_.size();++i) {
133  std::cout << anchors_[i] << std::endl;
134  }
135  std::cout << "---" << std::endl;
136 */
137  }
138 
139  init_();
140  }
141 
142  template<int D, class T, int max_capacity, int max_depth>
144  {
145  node_ = 0;
146  allin_top_ = 0;
147  ntree_ = top_;
148 
149  if (mask_->outside(Box<D>(ntree_->lower_left_-anchor_,ntree_->lower_left_-anchor_+ntree_->extent_))) {
150 
151  next_anchor_();
152 
153  } else {
154 
155  if (mask_->inside(Box<D>(ntree_->lower_left_-anchor_, ntree_->lower_left_-anchor_+ntree_->extent_))) {
156  first_leaf_inside_();
157  } else {
158  first_leaf_();
159  }
160 
161  if ( ntree_->nodes_.empty() || (!mask_->inside(ntree_->nodes_[node_].first-anchor_))) {
162  ++(*this);
163  }
164  }
165  }
166 
167  template<int D, class T, int max_capacity, int max_depth>
169  {
170  ++current_anchor_;
171  if (current_anchor_ >= anchors_.size()) {
172  // Done. Mark as invalid.
173  ntree_ = 0;
174  node_ = 0;
175  } else {
176  anchor_ = anchors_[current_anchor_];
177  init_();
178  }
179  }
180 
181  template<int D, class T, int max_capacity, int max_depth>
183  {
184 
185  // There are two states: the initial state, and "all in". In the
186  // all in state, we are in a subtree which is completely inside
187  // the mask. The allin_top_ is the top of this subtree. When
188  // exiting the subtree, the state changes to the initial
189  // state. In the initial state, we must check each quadrant to
190  // see if it is completely inside or outside the mask. If inside,
191  // we go all in. If outside, we move on to the next leaf. If
192  // neither, keep going until we find a leaf. Upon exiting from
193  // this function, we are either done (ntree_==0), or on a leaf
194  // node which at least intersects with the mask. If allin_top_!=0,
195  // the leaf is completely inside the mask.
196 
197  if (allin_top_) {
198  // state: all in
199 
200  // If we are on the last subtree, move up
201  while(ntree_ && (ntree_ != allin_top_) && (ntree_->my_subquad_ == N-1)) {
202  ntree_ = ntree_->parent_;
203  }
204 
205  // Since we stop at the top, this should never happen!
206  assert(ntree_ != 0);
207 
208  // If we reached the allin_top_, we are no longer all in.
209  if (ntree_ != allin_top_) {
210 
211  // Move to next sibling
212  ntree_ = ntree_->parent_->children_[ntree_->my_subquad_+1];
213 
214  // Move down if this is not a leaf.
215  while(!ntree_->is_leaf())
216  ntree_ = ntree_->children_[0];
217 
218  return;
219 
220  }
221 
222  allin_top_ = 0;
223  // Will continue as not all in.
224 
225  }
226 
227  // state: Not all in
228 
229  do {
230 
231  // If we are on the last subtree, move up
232  while(ntree_ && (ntree_ != top_) && (ntree_->my_subquad_ == N-1)) {
233  ntree_ = ntree_->parent_;
234  }
235 
236  // Since we stop at the top, this should never happen!
237  assert(ntree_ != 0);
238 
239  // If we have reached the top, mark as invalid and return
240  if (ntree_ == top_) {
241  return next_anchor_();
242  }
243 
244  // Move to next sibling
245  ntree_ = ntree_->parent_->children_[ntree_->my_subquad_+1];
246 
247  if (mask_->inside(Box<D>(ntree_->lower_left_-anchor_, ntree_->lower_left_-anchor_+ntree_->extent_))) {
248  return first_leaf_inside_();
249  }
250 
251  } while (mask_->outside(Box<D>(ntree_->lower_left_-anchor_, ntree_->lower_left_-anchor_+ntree_->extent_)));
252 
253  return first_leaf_();
254  }
255 
256  template<int D, class T, int max_capacity, int max_depth>
258  {
259  while(!ntree_->is_leaf()) {
260 
261  ntree_ = ntree_->children_[0];
262 
263  if (mask_->inside(Box<D>(ntree_->lower_left_-anchor_, ntree_->lower_left_-anchor_+ntree_->extent_))) {
264  return first_leaf_inside_();
265  }
266 
267  if (mask_->outside(Box<D>(ntree_->lower_left_-anchor_,ntree_->lower_left_-anchor_+ntree_->extent_))) {
268  return next_leaf_();
269  }
270 
271  }
272  }
273 
274 
275  template<int D, class T, int max_capacity, int max_depth>
277  {
278 
279  allin_top_ = ntree_;
280 
281  while(!ntree_->is_leaf()) {
282  ntree_ = ntree_->children_[0];
283  }
284  }
285 
286  template<int D, class T, int max_capacity, int max_depth>
288  {
289  node_++;
290 
291  if (allin_top_ == 0) {
292  while((node_ < ntree_->nodes_.size()) && (!mask_->inside(ntree_->nodes_[node_].first-anchor_))) {
293  node_++;
294  }
295  }
296 
297  while (node_ >= ntree_->nodes_.size()) {
298 
299  next_leaf_();
300 
301  node_ = 0;
302 
303  if (ntree_ == 0) break;
304 
305  if (allin_top_ == 0) {
306  while((node_ < ntree_->nodes_.size()) && (!mask_->inside(ntree_->nodes_[node_].first-anchor_))) {
307  node_++;
308  }
309  }
310  }
311 
312  return *this;
313  }
314 
315  template<int D, class T, int max_capacity, int max_depth>
317  {
318  int r = 0;
319  for(int i=0;i<D;++i)
320  r += (1<<i) * (pos[i]<lower_left_[i]+extent_[i]/2?0:1);
321 
322  return r;
323  }
324 
325  template<int D, class T, int max_capacity, int max_depth>
326  void Ntree<D,T,max_capacity,max_depth>::append_nodes_(std::vector<std::pair<Position<D>,T> >&v)
327  {
328  if (leaf_) {
329  std::copy(nodes_.begin(), nodes_.end(), std::back_inserter(v));
330  } else {
331  for (int i=0;i<N;++i)
332  children_[i]->append_nodes_(v);
333  }
334  }
335 
336  template<int D, class T, int max_capacity, int max_depth>
337  void Ntree<D,T,max_capacity,max_depth>::append_nodes_(std::vector<std::pair<Position<D>,T> >&v, const Mask<D> &mask, const Position<D> &anchor)
338  {
339  if (mask.outside(Box<D>(lower_left_-anchor, lower_left_-anchor+extent_)))
340  return;
341 
342  if (mask.inside(Box<D>(lower_left_-anchor, lower_left_-anchor+extent_)))
343  return append_nodes_(v);
344 
345  if (leaf_) {
346 
347  for(typename std::vector<std::pair<Position<D>,T> >::iterator i=nodes_.begin();
348  i!=nodes_.end(); ++i) {
349  if (mask.inside(i->first - anchor))
350  v.push_back(*i);
351  }
352 
353  } else {
354 
355  for (int i=0;i<N;++i)
356  children_[i]->append_nodes_(v,mask,anchor);
357 
358  }
359  }
360 
361  template<int D, class T, int max_capacity, int max_depth>
363  {
364  if (periodic_.any()) {
365  // Map position into standard range when using periodic b.c.
366  // Only necessary when inserting positions during source driven connect when target
367  // has periodic b.c. May be inefficient.
368 
369  for(int i=0;i<D;++i) {
370  if (periodic_[i]) {
371  pos[i] = lower_left_[i] + std::fmod(pos[i]-lower_left_[i], extent_[i]);
372  if (pos[i]<lower_left_[i])
373  pos[i] += extent_[i];
374  }
375  }
376  }
377 
378  if (leaf_ && (nodes_.size()>=max_capacity) && (my_depth_<max_depth))
379  split_();
380 
381  if (leaf_) {
382 
383  assert((pos >= lower_left_) && (pos < lower_left_ + extent_));
384 
385  nodes_.push_back(std::pair<Position<D>,T>(pos,node));
386 
387  return iterator(*this,nodes_.size()-1);
388 
389  } else {
390 
391  return children_[subquad_(pos)]->insert(pos,node);
392 
393  }
394  }
395 
396  template<int D, class T, int max_capacity, int max_depth>
398  {
399  assert(leaf_);
400 
401  for(int j=0;j<N;++j) {
403  for(int i=0;i<D;++i) {
404  if (j & (1<<i))
405  ll[i] += extent_[i]*0.5;
406  }
407 
408  children_[j] = new Ntree<D,T,max_capacity,max_depth>(ll, extent_*0.5,0,this,j);
409  }
410 
411  for(typename std::vector<std::pair<Position<D>,T> >::iterator i=nodes_.begin(); i!=nodes_.end(); ++i) {
412  children_[subquad_(i->first)]->insert(i->first,i->second);
413  }
414 
415  nodes_.clear();
416 
417  leaf_ = false;
418  }
419 
420 }
421 
422 #endif
masked_iterator & operator++()
Move the iterator to the next node inside the mask within the tree.
Definition: ntree_impl.h:287
const Mask< D > * mask_
Definition: ntree.h:203
bool is_leaf() const
Definition: ntree.h:357
Iterator iterating the nodes in a Quadtree inside a Mask.
Definition: ntree.h:128
bool leaf_
Definition: ntree.h:305
void next_leaf_()
Move to the next leaf quadrant, or set ntree_ to 0 if there are no more leaves.
Definition: ntree_impl.h:67
iterator & operator++()
Move the iterator to the next node within the tree.
Definition: ntree_impl.h:49
void next_anchor_()
Go to the next anchor image.
Definition: ntree_impl.h:168
void split_()
Change a leaf ntree to a regular ntree with four children regions.
Definition: ntree_impl.h:397
void next_leaf_()
Find the next leaf which is not outside the mask.
Definition: ntree_impl.h:182
int subquad_(const Position< D > &)
Definition: ntree_impl.h:316
assert(pNet!=0)
void first_leaf_inside_()
Set the allin_top_ to the current quadrant, and find the first leaf below the current quadrant...
Definition: ntree_impl.h:276
Abstract base class for masks with given dimension.
Definition: mask.h:90
A Ntree object represents a subtree or leaf in a Ntree structure.
Definition: ntree.h:49
const Name anchor("anchor")
Definition: topology_names.h:50
static const int N
Definition: ntree.h:53
static double_t mod(double_t x, double_t p)
Definition: ntree_impl.h:94
Position< D > lower_left_
Definition: ntree.h:302
iterator insert(Position< D > pos, const T &node)
Traverse quadtree structure from current ntree.
Definition: ntree_impl.h:362
Iterator iterating the nodes in a Quadtree.
Definition: ntree.h:64
void first_leaf_()
Find the first leaf which is not outside the mask.
Definition: ntree_impl.h:257
A box is defined by the lower left corner (minimum coordinates) and the upper right corner (maximum c...
Definition: position.h:289
Position< D > extent_
Definition: ntree.h:303
int my_depth_
This Ntree's depth in the tree.
Definition: ntree.h:311
void init_()
Initialize.
Definition: ntree_impl.h:143
Ntree * ntree_
Definition: ntree.h:120
const Name x("x")
current scaling factor of the synaptic weight [0...1] (Tsodyks2_connection)
Definition: nest_names.h:356
Position< D > upper_right
Definition: position.h:297
std::vector< Position< D > > anchors_
Definition: ntree.h:205
std::bitset< D > periodic_
periodic b.c.
Definition: ntree.h:313
double double_t
Double precision floating point numbers.
Definition: nest.h:93
iterator()
Initialize an invalid iterator.
Definition: ntree.h:69
Position< D > anchor_
Definition: ntree.h:204
const Name n("n")
Number of synaptic release sites (int >=0) (Tsodyks2_connection)
Definition: nest_names.h:202
friend class iterator
Definition: ntree.h:315
std::vector< value_type > nodes_
Definition: ntree.h:307
Ntree * ntree_
Definition: ntree.h:199
Position< D > lower_left
Definition: position.h:296
const Name mask("mask")
Definition: topology_names.h:57
Ntree * children_[N]
Definition: ntree.h:312
const Name p("p")
current release probability (Tsodyks2_connection)
Definition: nest_names.h:218
void append_nodes_(std::vector< value_type > &)
Append this ntree's nodes to the vector.
masked_iterator()
Initialize an invalid iterator.
Definition: ntree.h:133