LIBINT  2.6.0
quanta.h
1 /*
2  * Copyright (C) 2004-2019 Edward F. Valeev
3  *
4  * This file is part of Libint.
5  *
6  * Libint 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 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Libint 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 Libint. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef _libint2_src_bin_libint_quanta_h_
22 #define _libint2_src_bin_libint_quanta_h_
23 
24 #include <cassert>
25 #include <vector>
26 #include <smart_ptr.h>
27 #include <global_macros.h>
28 #include <iter.h>
29 
30 using namespace std;
31 
32 
33 namespace libint2 {
34 
40  public Hashable<LIBINT2_UINT_LEAST64,ComputeKey> {
41  public:
42  typedef DummyIterator iter_type;
44  static const LIBINT2_UINT_LEAST64 max_quantum_number = 100;
45 
46  virtual ~QuantumSet() {}
47  virtual std::string label() const =0;
48 
50  virtual unsigned int num_quanta() const =0;
52  virtual void inc(unsigned int i) =0;
54  virtual void dec(unsigned int i) =0;
55  };
56 
59  template<typename T, unsigned int N> class QuantumNumbers : public QuantumSet {
60 
61  vector<T> qn_;
62 
63  public:
64  typedef QuantumSet parent_type;
67 
68  QuantumNumbers(const vector<T>& qn);
69  QuantumNumbers(const SafePtr<QuantumNumbers>&);
70  QuantumNumbers(const SafePtr<QuantumSet>&);
71  QuantumNumbers(const SafePtr<ConstructablePolymorphically>&);
73  ~QuantumNumbers();
74 
75  bool operator==(const QuantumNumbers&) const;
76  std::string label() const;
77 
79  void inc(unsigned int i) { ++qn_.at(i); }
81  void dec(unsigned int i) {
82 #if CHECK_SAFETY
83  if (qn_.at(i) == T(0))
84  throw std::runtime_error("QuantumNumbers::dec -- quantum number already zero");
85 #endif
86  --qn_.at(i);
87  }
88 
90  const T elem(unsigned int i) const {
91  return qn_.at(i);
92  }
93 
95  unsigned int num_quanta() const {
96  return qn_.size();
97  }
98 
100  LIBINT2_UINT_LEAST64 key() const {
101  LIBINT2_UINT_LEAST64 key = 0;
102  LIBINT2_UINT_LEAST64 pfac = 1;
103  const int maxi = ((int)num_quanta()) - 1;
104  for(int i=maxi; i>=0; i--) {
105  key += pfac*qn_[i];
106  pfac *= QuantumSet::max_quantum_number;
107  }
108  assert(key < this->max_key());
109  return key;
110  }
111 
113  LIBINT2_UINT_LEAST64 max_key() const {
114  LIBINT2_UINT_LEAST64 max_key = 1;
115  const int maxi = ((int)num_quanta()) - 1;
116  for(int i=maxi; i>=0; i--) {
117  max_key *= QuantumSet::max_quantum_number;
118  }
119  return max_key;
120  }
121 
122  };
123 
124  template<typename T, unsigned int N>
125  QuantumNumbers<T,N>::QuantumNumbers(const vector<T>& qn) :
126  qn_(qn)
127  {
128  }
129 
130  template<typename T, unsigned int N>
131  QuantumNumbers<T,N>::QuantumNumbers(const SafePtr<QuantumNumbers>& sptr) :
132  qn_(sptr->qn_)
133  {
134  }
135 
136  template<typename T, unsigned int N>
137  QuantumNumbers<T,N>::QuantumNumbers(const SafePtr<QuantumSet>& sptr)
138  {
139  const SafePtr< QuantumNumbers<T,N> > sptr_cast = dynamic_pointer_cast<QuantumNumbers,QuantumSet>(sptr);
140 #if CHECK_SAFETY
141  if (sptr_cast == 0)
142  throw std::runtime_error("QuantumNumbers<T,N>::QuantumNumbers(const SafePtr<QuantumSet>& sptr) -- type of sptr is incompatible with QuantumNumbers");
143 #endif
144 
145  qn_ = sptr_cast->qn_;
146  }
147 
148  template<typename T, unsigned int N>
149  QuantumNumbers<T,N>::QuantumNumbers(const SafePtr<ConstructablePolymorphically>& sptr)
150  {
151  const SafePtr< QuantumNumbers<T,N> > sptr_cast = dynamic_pointer_cast<QuantumNumbers,ConstructablePolymorphically>(sptr);
152 #if CHECK_SAFETY
153  if (sptr_cast == 0)
154  throw std::runtime_error("QuantumNumbers<T,N>::QuantumNumbers(const SafePtr<ConstructablePolymorphically>& sptr) -- type of sptr is incompatible with QuantumNumbers");
155 #endif
156 
157  qn_ = sptr_cast->qn_;
158  }
159 
160  template<typename T, unsigned int N>
161  QuantumNumbers<T,N>::QuantumNumbers(const ConstructablePolymorphically& sptr)
162  {
163  const QuantumNumbers<T,N>& sptr_cast = dynamic_cast<const QuantumNumbers&>(sptr);
164  qn_ = sptr_cast.qn_;
165  }
166 
167  template<typename T, unsigned int N>
168  QuantumNumbers<T,N>::~QuantumNumbers()
169  {
170  }
171 
172  template<typename T, unsigned int N>
173  bool
174  QuantumNumbers<T,N>::operator==(const QuantumNumbers& a) const
175  {
176  return qn_ == a.qn_;
177  }
178 
179  template<typename T, unsigned int N>
180  std::string
181  QuantumNumbers<T,N>::label() const
182  {
183  std::ostringstream oss;
184  oss << "{";
185  if (qn_.size() > 0)
186  oss << qn_[0];
187  for(int i=1; i<qn_.size(); i++)
188  oss << "," << qn_[i];
189  oss << "}";
190  return oss.str();
191  }
192 
193  //typedef QuantumNumbers<unsigned int,0> NullQuantumSet;
194 
195 
200  template<typename T, unsigned int N> class QuantumNumbersA : public QuantumSet {
201 
202  T qn_[N];
203 
204  public:
205  typedef QuantumSet parent_type;
208 
209  // Set all quanta to val
210  QuantumNumbersA(const T& val);
211  QuantumNumbersA(const T* qn);
212  QuantumNumbersA(const vector<T>& qn);
213  QuantumNumbersA(const SafePtr<QuantumNumbersA>&);
214  QuantumNumbersA(const SafePtr<QuantumSet>&);
215  QuantumNumbersA(const SafePtr<ConstructablePolymorphically>&);
216  ~QuantumNumbersA();
217 
218  bool operator==(const QuantumNumbersA&) const;
219  std::string label() const;
220 
222  void inc(unsigned int i) { ++qn_[i]; }
224  void dec(unsigned int i) {
225 #if CHECK_SAFETY
226  if (qn_[i] == T(0))
227  throw std::runtime_error("QuantumNumbersA::dec -- quantum number already zero");
228 #endif
229  --qn_[i];
230  }
231 
233  const T elem(unsigned int i) const {
234  return qn_[i];
235  }
236 
238  void set_elem(unsigned int i, const T& value) {
239  qn_[i] = value;
240  }
241 
243  unsigned int num_quanta() const {
244  return N;
245  }
246 
248  LIBINT2_UINT_LEAST64 key() const {
249  LIBINT2_UINT_LEAST64 key = 0;
250  LIBINT2_UINT_LEAST64 pfac = 1;
251  const int maxi = ((int)num_quanta()) - 1;
252  for(int i=maxi; i>=0; i--) {
253  key += pfac*qn_[i];
255  }
256  assert(key < this->max_key());
257  return key;
258  }
259 
261  LIBINT2_UINT_LEAST64 max_key() const {
262  LIBINT2_UINT_LEAST64 max_key = 1;
263  const int maxi = ((int)num_quanta()) - 1;
264  for(int i=maxi; i>=0; i--) {
266  }
267  return max_key;
268  }
269 
270  };
271 
272  template<typename T, unsigned int N>
273  QuantumNumbersA<T,N>::QuantumNumbersA(const T& val)
274  {
275  for(unsigned int i=0; i<N; i++)
276  qn_[i] = val;
277  }
278 
279  template<typename T, unsigned int N>
280  QuantumNumbersA<T,N>::QuantumNumbersA(const T* qn)
281  {
282  for(int i=0; i<N; i++)
283  qn_[i] = qn[i];
284  }
285 
286  template<typename T, unsigned int N>
287  QuantumNumbersA<T,N>::QuantumNumbersA(const vector<T>& qn)
288  {
289  for(int i=0; i<N; i++)
290  qn_[i] = qn[i];
291  }
292 
293  template<typename T, unsigned int N>
294  QuantumNumbersA<T,N>::QuantumNumbersA(const SafePtr<QuantumNumbersA>& sptr)
295  {
296  T* qn = sptr->qn_;
297  for(unsigned int i=0; i<N; i++)
298  qn_[i] = qn[i];
299  }
300 
301  template<typename T, unsigned int N>
302  QuantumNumbersA<T,N>::QuantumNumbersA(const SafePtr<QuantumSet>& sptr)
303  {
304  const SafePtr< QuantumNumbersA<T,N> > sptr_cast = dynamic_pointer_cast<QuantumNumbersA,QuantumSet>(sptr);
305 #if CHECK_SAFETY
306  if (sptr_cast == 0)
307  throw std::runtime_error("QuantumNumbersA<T,N>::QuantumNumbersA(const SafePtr<QuantumSet>& sptr) -- type of sptr is incompatible with QuantumNumbersA");
308 #endif
309 
310  T* qn = sptr_cast->qn_;
311  for(int i=0; i<N; i++)
312  qn_[i] = qn[i];
313  }
314 
315  template<typename T, unsigned int N>
316  QuantumNumbersA<T,N>::QuantumNumbersA(const SafePtr<ConstructablePolymorphically>& sptr)
317  {
318  const SafePtr< QuantumNumbersA<T,N> > sptr_cast = dynamic_pointer_cast<QuantumNumbersA,ConstructablePolymorphically>(sptr);
319 #if CHECK_SAFETY
320  if (sptr_cast == 0)
321  throw std::runtime_error("QuantumNumbersA<T,N>::QuantumNumbersA(const SafePtr<ConstructablePolymorphically>& sptr) -- type of sptr is incompatible with QuantumNumbersA");
322 #endif
323  T* qn = sptr_cast->qn_;
324  for(int i=0; i<N; i++)
325  qn_[i] = qn[i];
326  }
327 
328  template<typename T, unsigned int N>
329  QuantumNumbersA<T,N>::~QuantumNumbersA()
330  {
331  }
332 
333  template<typename T, unsigned int N>
334  bool
335  QuantumNumbersA<T,N>::operator==(const QuantumNumbersA& a) const
336  {
337  const T* qn0 = qn_;
338  const T* qn1 = a.qn_;
339  for(int i=0; i<N; i++, ++qn0, ++qn1)
340  if (*qn0 != *qn1)
341  return false;
342 
343  return true;
344  }
345 
346  template<typename T, unsigned int N>
347  std::string
348  QuantumNumbersA<T,N>::label() const
349  {
350  std::ostringstream oss;
351  oss << "{";
352  if (N > 0)
353  oss << qn_[0];
354  for(unsigned int i=1; i<N; i++)
355  oss << "," << qn_[i];
356  oss << "}";
357  return oss.str();
358  }
359 
361  template<typename T> class QuantumNumbersA<T,0> : public QuantumSet {
362 
363  public:
364  typedef QuantumSet parent_type;
367 
368  QuantumNumbersA() {}
369  QuantumNumbersA(const T* qn) {}
370  QuantumNumbersA(const vector<T>& qn) {}
371  QuantumNumbersA(const SafePtr<QuantumNumbersA>&) {}
372  QuantumNumbersA(const SafePtr<QuantumSet>&) {}
373  QuantumNumbersA(const SafePtr<ConstructablePolymorphically>&) {}
374  ~QuantumNumbersA() {}
375 
376  bool operator==(const QuantumNumbersA&) const { return true; }
377  std::string label() const { return "{}"; }
378 
380  void inc(unsigned int i) { throw std::runtime_error("QuantumNumbersA<T,0>::inc -- no quantum numbers to increment"); }
382  void dec(unsigned int i) {
383  throw std::runtime_error("QuantumNumbersA<T,0>::inc -- no quantum numbers to decrement");
384  }
386  const T elem(unsigned int i) const { throw std::runtime_error("QuantumNumbersA<T,0>::inc -- no quantum numbers to return"); }
388  unsigned int num_quanta() const { return 0; }
389 
391  LIBINT2_UINT_LEAST64 key() const { return 0; }
392 
394  LIBINT2_UINT_LEAST64 max_key() const { return 1; }
395 
396  };
397 
399  template <typename T, unsigned int N>
403  };
412 
413 };
414 
415 #endif
const T elem(unsigned int i) const
Return i-th quantum number.
Definition: quanta.h:90
LIBINT2_UINT_LEAST64 key() const
Implements Hashable::key()
Definition: quanta.h:100
QuantumNumbersA iter_type
QuantumSet is a set of one QuantumSet.
Definition: quanta.h:366
static const LIBINT2_UINT_LEAST64 max_quantum_number
Quantum numbers lie in range [0,max_quantum_number)
Definition: quanta.h:44
ConstructablePolymorphically is a base for all objects which can be constructed using a SafePtr to a ...
Definition: polyconstr.h:31
QuantumSet is the base class for all (sets of) quantum numbers.
Definition: quanta.h:39
void dec(unsigned int i)
Decrement quantum number i.
Definition: quanta.h:81
Defaults definitions for various parameters assumed by Libint.
Definition: algebra.cc:24
Objects of Hashable<T> class provide hashing function key() which computes keys of type KeyType.
Definition: hashable.h:73
unsigned int num_quanta() const
Return i-th quantum number.
Definition: quanta.h:95
QuantumNumbers<T,N> is a set of N quantum numbers of type T implemented in terms of std::vector.
Definition: quanta.h:59
DefaultQuantumNumbers< unsigned int, 1 >::Result mType
mType is the type that describes the auxiliary index of standard 2-body repulsion integrals
Definition: quanta.h:411
void dec(unsigned int i)
Decrement quantum number i.
Definition: quanta.h:382
void inc(unsigned int i)
Increment quantum number i.
Definition: quanta.h:380
QuantumNumbersA<T,N> is a set of N quantum numbers of type T implemented in terms of a C-style array.
Definition: quanta.h:200
void set_elem(unsigned int i, const T &value)
Return i-th quantum number.
Definition: quanta.h:238
void inc(unsigned int i)
Increment quantum number i.
Definition: quanta.h:79
LIBINT2_UINT_LEAST64 max_key() const
key is in range [0,max_key())
Definition: quanta.h:113
LIBINT2_UINT_LEAST64 key() const
Implements Hashable::key()
Definition: quanta.h:391
unsigned int num_quanta() const
Implementation of QuantumSet::num_quanta()
Definition: quanta.h:388
const T elem(unsigned int i) const
Return i-th quantum number.
Definition: quanta.h:386
const T elem(unsigned int i) const
Return i-th quantum number.
Definition: quanta.h:233
unsigned int num_quanta() const
Implementation of QuantumSet::num_quanta()
Definition: quanta.h:243
LIBINT2_UINT_LEAST64 max_key() const
key is in range [0,max_key())
Definition: quanta.h:394
QuantumNumbers iter_type
QuantumSet is a set of one QuantumSet.
Definition: quanta.h:66
void inc(unsigned int i)
Increment quantum number i.
Definition: quanta.h:222
void dec(unsigned int i)
Decrement quantum number i.
Definition: quanta.h:224
Default implementation of QuantumNumbers.
Definition: quanta.h:400
QuantumNumbersA iter_type
QuantumSet is a set of one QuantumSet.
Definition: quanta.h:207
LIBINT2_UINT_LEAST64 key() const
Implements Hashable::key()
Definition: quanta.h:248
LIBINT2_UINT_LEAST64 max_key() const
key is in range [0,max_key())
Definition: quanta.h:261
QuantumNumbersA< T, N > Result
This defines which QuantumNumbers implementation to use.
Definition: quanta.h:402
DefaultQuantumNumbers< int, 0 >::Result EmptySet
EmptySet is the type that describes null set of auxiliary indices.
Definition: quanta.h:407