MADNESS  version 0.9
key.h
Go to the documentation of this file.
1 /*
2  This file is part of MADNESS.
3 
4  Copyright (C) 2007,2010 Oak Ridge National Laboratory
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20  For more information please contact:
21 
22  Robert J. Harrison
23  Oak Ridge National Laboratory
24  One Bethel Valley Road
25  P.O. Box 2008, MS-6367
26 
27  email: harrisonrj@ornl.gov
28  tel: 865-241-3937
29  fax: 865-572-0680
30 
31 
32  $Id$
33  */
34 
35 #ifndef MADNESS_MRA_KEY_H__INCLUDED
36 #define MADNESS_MRA_KEY_H__INCLUDED
37 
40 
41 #include <vector>
42 #include <madness/mra/power.h>
43 #include <madness/world/array.h>
44 #include <madness/world/binfsar.h>
46 #include <stdint.h>
47 
48 namespace madness {
49 
50  // // this has problems when nproc is a large-ish power of 2 such as 256
51  // // and leads to bad data distribution.
52  // static inline unsigned int sdbm(int n, const unsigned char* c, unsigned int sum=0) {
53  // for (int i=0; i<n; ++i) sum = c[i] + (sum << 6) + (sum << 16) - sum;
54  // return sum;
55  // }
56 
57  typedef int64_t Translation;
58  typedef int Level;
59 
60  template<std::size_t NDIM>
62 
64 
68  template<std::size_t NDIM>
69  class Key {
70  friend class KeyChildIterator<NDIM> ;
71  private:
72  Level n;
74  hashT hashval;
75 
76 
77  // Helper function for operator <
78  int
79  encode(int dig) const {
80  int retval = 0;
81  for (std::size_t j = 0; j < NDIM; ++j) {
82  // retval += ((l[j]/2^{n-1-dig}) mod 2) * 2^j
83  retval += ((l[j] >> (n - 1 - dig)) % 2) << j;
84  }
85  return retval;
86  }
87 
88  // Helper function for (Level, Translation) constructor
89  Vector<Translation, NDIM>
90  decode(Level level, Translation k) const {
91  Vector<Translation, NDIM> L(0);
92  int twotoD = power<static_cast<int>(NDIM)> ();
93  int powr = 1, divisor = 2;
94  for (Level i = 0; i < level; ++i) {
95  Translation r = k % twotoD;
96  for (int j = 0; j < NDIM; ++j) {
97  L[NDIM - j - 1] += (r % divisor) * powr;
98  r /= divisor;
99  }
100  k /= twotoD;
101  powr *= 2;
102  }
103  return L;
104  }
105  public:
107  Key() {
108  }
109 
111  Key(Level n, const Vector<Translation, NDIM>& l) :
112  n(n), l(l) {
113  rehash();
114  }
115 
117  Key(int n) :
118  n(n), l(0) {
119  rehash();
120  }
121 
123  Key(Level n, Translation p) :
124  n(n) {
125  l = decode(n, p);
126  rehash();
127  }
128 
130  Key(const int n, const int l0) : n(n) {
131  MADNESS_ASSERT(NDIM==1);
133  rehash();
134  }
135 
137  Key(const int n, const int l0, const int l1, const int l2) : n(n) {
138  MADNESS_ASSERT(NDIM==3);
140  l[0]=l0; l[1]=l1; l[2]=l2;
141  rehash();
142  }
143 
145  static Key<NDIM>
147  return Key<NDIM> (-1);
148  }
149 
151  bool
152  is_invalid() const {
153  return n == -1;
154  }
155 
157  bool
158  is_valid() const {
159  return n != -1;
160  }
161 
163  bool
164  operator==(const Key& other) const {
165  if (hashval != other.hashval)
166  return false;
167  if (n != other.n)
168  return false;
169  bool result = l == other.l;
170  if (result && hashval != other.hashval) {
171  print("!! keys same but hash is different", hashval,
172  other.hashval, *this, other);
173  MADNESS_EXCEPTION("Tell HQI not RJ3!",0);
174  }
175  return result;
176  }
177 
178  bool
179  operator!=(const Key& other) const {
180  return !(*this == other);
181  }
182 
184  bool
185  operator<(const Key& other) const {
186  if (*this == other)
187  return false; // I am not less than self
188  Level nmin;
189  bool retval = false;
190 
191  if (this->n > other.n) {
192  nmin = other.n;
193  retval = true;
194  }
195  else {
196  nmin = this->n;
197  }
198 
199  for (Level i = 0; i < nmin; ++i) {
200  int tthis = this->encode(i), tother = other.encode(i);
201  if (tthis != tother) {
202  return (tthis < tother);
203  }
204  }
205  return retval;
206  }
207 
208  inline hashT
209  hash() const {
210  return hashval;
211  }
212 
213  // template<typename Archive>
214  // inline void
215  // serialize(Archive& ar) {
216  // ar & archive::wrap((unsigned char*) this, sizeof(*this));
217  // }
218 
219  Level
220  level() const {
221  return n;
222  }
223 
225  translation() const {
226  return l;
227  }
228 
229  uint64_t
230  distsq() const {
231  uint64_t dist = 0;
232  for (std::size_t d = 0; d < NDIM; ++d) {
233  dist += l[d] * l[d];
234  }
235  return dist;
236  }
237 
239 
247  Key
248  parent(int generation = 1) const {
250  if (generation > n)
251  generation = n;
252  for (std::size_t i = 0; i < NDIM; ++i)
253  pl[i] = l[i] >> generation;
254  return Key(n - generation, pl);
255  }
256 
257 
258  bool
259  is_child_of(const Key& key) const {
260  if (this->n < key.n) {
261  return false; // I can't be child of something lower on the tree
262  }
263  else if (this->n == key.n) {
264  return (*this == key); // I am child of myself
265  }
266  else {
267  Level dn = this->n - key.n;
268  Key mama = this->parent(dn);
269  return (mama == key);
270  }
271  }
272 
273 
274  bool
275  is_parent_of(const Key& key) const {
276  return (key.is_child_of(*this));
277  }
278 
280 
282  bool
283  is_neighbor_of(const Key& key, const std::vector<bool>& bperiodic) const {
284  Translation dist = 0;
285  Translation TWON1 = (Translation(1)<<n) - 1;
286  for (std::size_t i=0; i<NDIM; ++i)
287  {
288  Translation ll = std::abs(l[i] - key.l[i]);
289  if (bperiodic[i] && ll==TWON1) ll=1;
290  dist = std::max(dist, ll);
291  }
292  return (dist <= 1);
293  }
294 
296 
299  Key neighbor(const Key<NDIM>& disp) const {
301  return Key(this->level(),l);
302  }
303 
304 
306  bool thisKeyContains(const Vector<double,NDIM>& x, const unsigned int& dim0,
307  const unsigned int& dim1) const {
308 
309  // it's sufficient if one single dimension is out
310  bool contains=true;
311  const double twotoN = std::pow(2.0,double(n));
312  MADNESS_ASSERT(dim0<NDIM and dim1<NDIM);
313 
314  for (unsigned int i=0; i<NDIM; i++ ) {
315 
316  // check bounds
317  MADNESS_ASSERT((x[i]>=0.0) and (x[i]<=1.0));
318 
319  // leave these two dimensions out
320  if ((i==dim0) or (i==dim1)) continue;
321 
322  const int ll=int (x[i]*twotoN);
323  if (not (l[i]==ll)) contains=false;
324  }
325  return contains;
326  }
327 
329  template<std::size_t LDIM, std::size_t KDIM>
330  void break_apart(Key<LDIM>& key1, Key<KDIM>& key2) const {
331 
332  // if LDIM==NDIM the 2nd key will be constructed empty
333  MADNESS_ASSERT((LDIM+KDIM==NDIM) or (LDIM==NDIM));
336  for (int i=0; i<static_cast<int>(LDIM); ++i) {
337  l1[i]=l[i];
338  }
339  for (size_t i=LDIM; i<NDIM; ++i) {
340  l2[i-LDIM]=l[i];
341  }
342  key1=Key<LDIM>(n,l1);
343  key2=Key<KDIM>(n,l2);
344  }
345 
347  template<std::size_t LDIM>
348  Key<NDIM+LDIM> merge_with(const Key<LDIM>& rhs) const {
350  for (int i=0; i<static_cast<int>(NDIM); ++i) t[i] =this->l[i];
351  for (int i=0; i<static_cast<int>(LDIM); ++i) t[NDIM+i]=rhs.translation()[i];
352  return Key<NDIM+LDIM>(rhs.level(),t);
353  }
354 
356 
361  bool is_farther_out_than(const Key<NDIM>& other) const {
362  for (size_t i=0; i<NDIM; ++i) {
363  if ((other.translation()[i]>0) and (other.translation()[i]>l[i])) return false;
364  if ((other.translation()[i]<0) and (other.translation()[i]<l[i])) return false;
365  }
366  return true;
367  }
368 
369 
371  void
372  rehash() {
373  //hashval = sdbm(sizeof(n)+sizeof(l), (unsigned char*)(&n));
374  // default hash is still best
375  hashval = hash_value(l);
376  hash_combine(hashval, n);
377  }
378  };
379 
380  template<std::size_t NDIM>
381  std::ostream&
382  operator<<(std::ostream& s, const Key<NDIM>& key) {
383  s << "(" << key.level() << "," << key.translation() << ")";
384  return s;
385  }
386 
388 
392  template<size_t NDIM>
394  MADNESS_ASSERT(source.level()==target.level());
395  const Vector<Translation,NDIM> l = target.translation()-source.translation();
396  return Key<NDIM>(source.level(),l);
397  }
398 
399 
400 
402 
407  template<std::size_t NDIM>
408  class KeyChildIterator {
409  Key<NDIM> parent;
410  Key<NDIM> child;
411  Vector<Translation, NDIM> p;
412  bool finished;
413 
414  public:
416  p(0), finished(true) {
417  }
418 
419  KeyChildIterator(const Key<NDIM>& parent) :
420  parent(parent), child(parent.n + 1, parent.l * 2), p(0),
421  finished(false) {
422  }
423 
427  if (finished)
428  return *this;
429  std::size_t i;
430  for (i = 0; i < NDIM; ++i) {
431  if (p[i] == 0) {
432  ++(p[i]);
433  ++(child.l[i]);
434  for (std::size_t j = 0; j < i; ++j) {
435  --(p[j]);
436  --(child.l[j]);
437  }
438  break;
439  }
440  }
441  finished = (i == NDIM);
442  child.rehash();
443  return *this;
444  }
445 
447  operator bool() const {
448  return !finished;
449  }
450 
451  template<typename Archive>
452  inline void
453  serialize(Archive& ar) {
454  ar & archive::wrap((unsigned char*) this, sizeof(*this));
455  }
456 
458  inline const Key<NDIM>&
459  key() const {
460  return child;
461  }
462  };
463 
465  template<std::size_t NDIM, typename opT>
466  inline void
467  foreach_child(const Key<NDIM>& parent, opT& op) {
469  it(parent); it; ++it)
470  op(it.key());
471  }
472 
474  template<std::size_t NDIM, typename objT>
475  inline void
476  foreach_child(const Key<NDIM>& parent, objT* obj, void
477  (objT::*memfun)(const Key<NDIM>&)) {
479  it(parent); it; ++it)
480  (obj ->* memfun)(it.key());
481  }
482 
483  namespace archive {
484 
485  // For efficiency serialize opaque so is just one memcpy, but
486  // when reading from external storage rehash() so that we
487  // can read data even if hash algorithm/function has changed.
488 
489  template <class Archive, std::size_t NDIM>
490  struct ArchiveLoadImpl< Archive, Key<NDIM> > {
491  static void load(const Archive& ar, Key<NDIM>& t) {
492  ar & archive::wrap((unsigned char*) &t, sizeof(t));
493  }
494  };
495 
496  template <std::size_t NDIM>
498  static void load(const BinaryFstreamInputArchive& ar, Key<NDIM>& t) {
499  ar & archive::wrap((unsigned char*) &t, sizeof(t));
500  t.rehash(); // <<<<<<<<<< This is the point
501  }
502  };
503 
504  template <class Archive, std::size_t NDIM>
505  struct ArchiveStoreImpl< Archive, Key<NDIM> > {
506  static void store(const Archive& ar, const Key<NDIM>& t) {
507  ar & archive::wrap((unsigned char*) &t, sizeof(t));
508  }
509  };
510  }
511 
512 }
513 
514 #endif // MADNESS_MRA_KEY_H__INCLUDED
515 
Wraps an archive around a binary file stream for input.
Definition: binfsar.h:78
void rehash()
Recomputes hashval ... presently only done when reading from external storage.
Definition: key.h:372
Key(const int n, const int l0)
easy constructor
Definition: key.h:130
static void store(const Archive &ar, const Key< NDIM > &t)
Definition: key.h:506
const Vector< Translation, NDIM > & translation() const
Definition: key.h:225
Key()
Default constructor makes an uninitialized key.
Definition: key.h:107
const int NDIM
Definition: tdse1.cc:44
Key< NDIM+LDIM > merge_with(const Key< LDIM > &rhs) const
merge with other key (ie concatenate), use level of rhs, not of this
Definition: key.h:348
KeyChildIterator(const Key< NDIM > &parent)
Definition: key.h:419
Key(int n)
Constructor with given n and l=0.
Definition: key.h:117
archive_array< T > wrap(const T *, unsigned int)
Factory function to wrap dynamically allocated pointer as typed archive_array.
Definition: archive.h:820
Defines hash functions for use in distributed containers.
const double L
Definition: 3dharmonic.cc:123
bool operator<(const Key &other) const
Comparison based upon depth first lexical order.
Definition: key.h:185
FLOAT target(const FLOAT &x)
Definition: y.cc:295
void foreach_child(const Key< NDIM > &parent, opT &op)
Applies op(key) to each child key of parent.
Definition: key.h:467
KeyChildIterator & operator++()
Pre-increment of an iterator (i.e., ++it)
Definition: key.h:426
const Key< NDIM > & key() const
Returns the key of the child.
Definition: key.h:459
Key(Level n, const Vector< Translation, NDIM > &l)
Constructor with given n, l.
Definition: key.h:111
KeyChildIterator()
Definition: key.h:415
Default store of a thingy via serialize(ar,t)
Definition: archive.h:708
uint64_t distsq() const
Definition: key.h:230
void break_apart(Key< LDIM > &key1, Key< KDIM > &key2) const
break key into two low-dimensional keys
Definition: key.h:330
bool is_invalid() const
Checks if a key is invalid.
Definition: key.h:152
void serialize(Archive &ar)
Definition: key.h:453
bool operator!=(const Key &other) const
Definition: key.h:179
bool is_valid() const
Checks if a key is valid.
Definition: key.h:158
Implements archive wrapping a binary filestream.
bool is_child_of(const Key &key) const
Definition: key.h:259
Key(const int n, const int l0, const int l1, const int l2)
easy constructor
Definition: key.h:137
bool thisKeyContains(const Vector< double, NDIM > &x, const unsigned int &dim0, const unsigned int &dim1) const
check if this MultiIndex contains point x, disregarding these two dimensions
Definition: key.h:306
#define max(a, b)
Definition: lda.h:53
Key parent(int generation=1) const
Returns the key of the parent.
Definition: key.h:248
bool is_parent_of(const Key &key) const
Definition: key.h:275
static Key< NDIM > invalid()
Returns an invalid key.
Definition: key.h:146
Level level() const
Definition: key.h:220
Default load of a thingy via serialize(ar,t)
Definition: archive.h:718
madness::hashT hash_value(const std::array< T, N > &a)
Hash std::array with madness::Hash.
Definition: array.h:62
void hash_combine(hashT &seed, const T &v)
Combine hash values.
Definition: worldhash.h:259
Key< NDIM > displacement(const Key< NDIM > &source, const Key< NDIM > &target)
given a source and a target, return the displacement in translation
Definition: key.h:393
std::size_t hashT
The hash value type.
Definition: worldhash.h:148
int Level
Definition: key.h:58
static void load(const BinaryFstreamInputArchive &ar, Key< NDIM > &t)
Definition: key.h:498
bool is_farther_out_than(const Key< NDIM > &other) const
return if the other key is pointing in the same direction and is farther out
Definition: key.h:361
bool is_neighbor_of(const Key &key, const std::vector< bool > &bperiodic) const
Assuming keys are at the same level, returns true if displaced by no more than 1 in any direction...
Definition: key.h:283
hashT hash() const
Definition: key.h:209
Tensor< double > op(const Tensor< double > &x)
Definition: kain.cc:508
bool operator==(const Key &other) const
Equality test.
Definition: key.h:164
void print(const A &a)
Print a single item to std::cout terminating with new line.
Definition: print.h:122
#define MADNESS_EXCEPTION(msg, value)
Definition: worldexc.h:88
Key(Level n, Translation p)
Constructor from lexical index in depth first order.
Definition: key.h:123
int64_t Translation
Definition: key.h:57
Holds machinery to set up Functions/FuncImpls using various Factories and Interfaces.
Definition: chem/atomutil.cc:45
Key neighbor(const Key< NDIM > &disp) const
given a displacement, generate a neighbor key; ignore boundary conditions and disp's level ...
Definition: key.h:299
Key is the index for a node of the 2^NDIM-tree.
Definition: key.h:69
static void load(const Archive &ar, Key< NDIM > &t)
Definition: key.h:491
Iterates in lexical order thru all children of a key.
Definition: key.h:61