# storage.h

    00001 //
    00002 // storage.h
    00003 //
    00004 // Copyright (C) 1996 Limit Point Systems, Inc.
    00005 //
    00006 // Author: Curtis Janssen <cljanss@limitpt.com>
    00007 // Maintainer: LPS
    00008 //
    00009 // This file is part of the SC Toolkit.
    00010 //
    00011 // The SC Toolkit is free software; you can redistribute it and/or modify
    00012 // it under the terms of the GNU Library General Public License as published by
    00013 // the Free Software Foundation; either version 2, or (at your option)
    00014 // any later version.
    00015 //
    00016 // The SC Toolkit is distributed in the hope that it will be useful,
    00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00019 // GNU Library General Public License for more details.
    00020 //
    00021 // You should have received a copy of the GNU Library General Public License
    00022 // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
    00023 // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00024 //
    00025 // The U.S. Government is granted a limited license as per AL 91-7.
    00026 //
    00027
    00028 #ifndef _chemistry_qc_intv3_storage_h
    00029 #define _chemistry_qc_intv3_storage_h
    00030
    00031 #ifdef __GNUC__
    00032 #pragma interface
    00033 #endif
    00034
    00035 #ifdef __cplusplus
    00036
    00037 #include <stddef.h>
    00038 #include <util/class/class.h>
    00039 #include <util/keyval/keyval.h>
    00040 #include <util/container/eavlmmap.h>
    00041
    00042 namespace sc {
    00043
    00044 // the max shell number is 2^15 (sizeof(int) must be >= 4)
    00045 #define SH_BITS 15 // the number of bits holding a shell index
    00046 #define PE_BITS 1  // the number of bits holding a permutation
    00047
    00048 #define SH_MASK ((1<<SH_BITS)-1)
    00049 #define PE_MASK ((1<<PE_BITS)-1)
    00050
    00051 #define SH0_SHIFT 0
    00052 #define SH1_SHIFT (SH_BITS + SH0_SHIFT)
    00053 #define P12_SHIFT (SH_BITS + SH1_SHIFT)
    00054 #define P34_SHIFT (PE_BITS + P12_SHIFT)
    00055 #define SH2_SHIFT 0
    00056 #define SH3_SHIFT (SH_BITS + SH2_SHIFT)
    00057 #define P13P24_SHIFT (SH_BITS + SH3_SHIFT)
    00058 class IntegralKey {
    00059   public:
    00060     unsigned int sh0_sh1_p12_p34;
    00061     unsigned int sh2_sh3_p13p24;
    00062   public:
    00063     IntegralKey(int,int,int,int,int,int,int);
    00064     IntegralKey(const IntegralKey&);
    00065     bool operator == (const IntegralKey &k) const {
    00066       return    (sh0_sh1_p12_p34 == k.sh0_sh1_p12_p34)
    00067              && (sh2_sh3_p13p24  == k.sh2_sh3_p13p24);
    00068     }
    00069     bool operator < (const IntegralKey &k) const {
    00070       return ((sh0_sh1_p12_p34 < k.sh0_sh1_p12_p34)?
    00071               true:(sh2_sh3_p13p24 < k.sh2_sh3_p13p24));
    00072     }
    00073     int sh0() const { return (sh0_sh1_p12_p34>>SH0_SHIFT) & SH_MASK; }
    00074     int sh1() const { return (sh0_sh1_p12_p34>>SH1_SHIFT) & SH_MASK; }
    00075     int p12() const { return (sh0_sh1_p12_p34>>P12_SHIFT) & PE_MASK; }
    00076     int p34() const { return (sh0_sh1_p12_p34>>P34_SHIFT) & PE_MASK; }
    00077     int sh2() const { return (sh2_sh3_p13p24>>SH2_SHIFT) & SH_MASK; }
    00078     int sh3() const { return (sh2_sh3_p13p24>>SH3_SHIFT) & SH_MASK; }
    00079     int p13p24() const { return (sh2_sh3_p13p24>>P13P24_SHIFT) & PE_MASK; }
    00080 };
    00081
    00082 inline
    00083 IntegralKey::IntegralKey(int sh1_, int sh2_, int sh3_, int sh4_,
    00084                          int p12_, int p34_, int p13p24_)
    00085 {
    00086   sh0_sh1_p12_p34 = (sh1_<<SH0_SHIFT)
    00087                     |(sh2_<<SH1_SHIFT)
    00088                     |(p12_<<P12_SHIFT)
    00089                     |(p34_<<P34_SHIFT);
    00090   sh2_sh3_p13p24 = (sh3_<<SH2_SHIFT)
    00091                    |(sh4_<<SH3_SHIFT)
    00092                    |(p13p24_<<P13P24_SHIFT);
    00093 }
    00094
    00095 inline
    00096 IntegralKey::IntegralKey(const IntegralKey& ik)
    00097 {
    00098   sh0_sh1_p12_p34 = ik.sh0_sh1_p12_p34;
    00099   sh2_sh3_p13p24 = ik.sh2_sh3_p13p24;
    00100 }
    00101
    00102 inline int
    00103 compare(const IntegralKey&k1, const IntegralKey&k2)
    00104 {
    00105   if (k1.sh0_sh1_p12_p34 < k2.sh0_sh1_p12_p34) return -1;
    00106   else if (k1.sh0_sh1_p12_p34 > k2.sh0_sh1_p12_p34) return 1;
    00107
    00108   if (k1.sh2_sh3_p13p24 < k2.sh2_sh3_p13p24) return -1;
    00109   else if (k1.sh2_sh3_p13p24 > k2.sh2_sh3_p13p24) return 1;
    00110   else return 0;
    00111 }
    00112
    00113 class IntegralLink {
    00114   public:
    00115     EAVLMMapNode<IntegralKey, IntegralLink> intlist;
    00116     EAVLMMapNode<int, IntegralLink> costlist;
    00117     int size;
    00118   public:
    00119     IntegralLink(IntegralKey& key, int cost, int size);
    00120     static int size_to_actualsize(int size);
    00121     ~IntegralLink();
    00122     int actualsize() const;
    00123     int hash() const;
    00124     static int shells_to_hash(int,int,int,int);
    00125     int cost() const { return costlist.key; }
    00126     void print();
    00127
    00128     // the integrals are squirreled away after this
    00129     double* buffer() { return (double*)&this[1]; }
    00130     void* operator new(size_t, int);
    00131     void operator delete(void*, int);
    00132     void operator delete(void*);
    00133 };
    00134
    00135 inline int
    00136 IntegralLink::shells_to_hash(int sh1,int sh2,int sh3,int sh4)
    00137 {
    00138   return sh1 ^ (sh4<<4) ^ (sh2<<8) ^ (sh3<<12);
    00139 }
    00140
    00141 inline int
    00142 IntegralLink::hash() const
    00143 {
    00144   return shells_to_hash(intlist.key.sh0(),
    00145                         intlist.key.sh1(),
    00146                         intlist.key.sh2(),
    00147                         intlist.key.sh3());
    00148 }
    00149
    00150 inline int
    00151 IntegralLink::size_to_actualsize(int size)
    00152 {
    00153   return size*sizeof(double) + sizeof(IntegralLink) + sizeof(void*)*2;
    00154 }
    00155
    00156 inline int
    00157 IntegralLink::actualsize() const
    00158 {
    00159   return size_to_actualsize(size);
    00160 }
    00161
    00162 class IntegralStorer: public DescribedClass {
    00163   private:
    00164     int table_size_;
    00165     EAVLMMap<int,IntegralLink> costlist;
    00166     EAVLMMap<IntegralKey,IntegralLink>* table_;
    00167     int maxsize_;
    00168     int currentsize_;
    00169     int n_integrals_;
    00170     int n_shellquart_;
    00171   public:
    00172     IntegralStorer();
    00173     IntegralStorer(const Ref<KeyVal>&);
    00174     ~IntegralStorer();
    00175     void init(int nbytes);
    00176     void done();
    00177     IntegralLink *find(IntegralKey&);
    00178     int should_store(int cost, int actualsize);
    00179     void store(IntegralKey& key, const double *buf,
    00180                int size, int cost, int actualsize);
    00181     void print_stats();
    00182     int table_size() const { return table_size_; }
    00183 };
    00184
    00185 }
    00186
    00187 #endif
    00188
    00189 #endif
    00190
    00191 // Local Variables:
    00192 // mode: c++
    00193 // c-file-style: "CLJ"
    00194 // End: