2008-02-26 14:55:23 +01:00
/*
LA : linear algebra C + + interface library
2019-11-13 00:52:44 +01:00
Copyright ( C ) 2008 - 2019 Jiri Pittner < jiri . pittner @ jh - inst . cas . cz > or < jiri @ pittnerovi . com >
2008-02-26 14:55:23 +01:00
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2004-03-17 04:07:21 +01:00
# ifndef _fourindex_included
# define _fourindex_included
2006-04-01 06:48:01 +02:00
# include <iostream>
2019-11-13 00:52:44 +01:00
# include <stdio.h>
2005-12-08 12:44:36 +01:00
# include <string.h>
2006-04-03 00:54:40 +02:00
# include <sys/types.h>
2006-04-25 16:49:43 +02:00
# include <sys/vfs.h>
# include <sys/mman.h>
# include <sys/stat.h>
2006-04-03 00:54:40 +02:00
# include <unistd.h>
2019-11-11 21:12:42 +01:00
# include <stdint.h>
2006-04-25 16:49:43 +02:00
# include <sys/stat.h>
2006-04-06 00:06:24 +02:00
# include "laerror.h"
2009-11-12 22:01:19 +01:00
# include "vec.h"
# include "smat.h"
# include "mat.h"
# include "nonclass.h"
2004-03-17 04:07:21 +01:00
2009-11-12 22:01:19 +01:00
namespace LA {
2006-04-25 16:49:43 +02:00
static unsigned int hcd0 ( unsigned int big , unsigned int small )
{
register unsigned int help ;
if ( big = = 0 )
{
if ( small = = 0 ) laerror ( " bad arguments in hcd " ) ;
return small ;
}
if ( small = = 0 ) return big ;
if ( small = = 1 | | big = = 1 ) return 1 ;
if ( small > big ) { help = big ; big = small ; small = help ; }
do {
help = small ;
small = big % small ;
big = help ;
}
while ( small ! = 0 ) ;
return big ;
}
2006-04-25 16:52:44 +02:00
static inline unsigned int lcm0 ( unsigned int i , unsigned int j )
2006-04-25 16:49:43 +02:00
{
return ( i / hcd0 ( i , j ) * j ) ;
}
2004-03-17 04:07:21 +01:00
//element of a linked list, indices in a portable way, no bit shifts and endianity problems any more!
2005-09-11 22:04:24 +02:00
//note: nn is never compared with individual indices, so indexing from 1 as well as from 0 is possible
2006-04-03 00:54:40 +02:00
//it is actually not needed for the algorithms here, but may be useful for the
//user of this class to keep this piece of information along with the data
2004-03-17 04:07:21 +01:00
2006-04-06 23:45:51 +02:00
//when patient enough, make const_casts for piterators to have pbegin() const
2006-04-02 22:07:29 +02:00
template < class I >
2021-08-28 17:05:54 +02:00
struct indiv_index {
2006-04-02 22:07:29 +02:00
I i ;
I j ;
I k ;
I l ;
2021-08-28 17:05:54 +02:00
}
# ifdef __GNUC__
__attribute__ ( ( packed ) )
# endif
;
template < class I >
union packed_index {
I packed [ 4 ] ;
struct indiv_index < I > indiv ;
}
# ifdef __GNUC__
__attribute__ ( ( packed ) )
# endif
;
2004-03-17 04:07:21 +01:00
template < class I , class T >
struct matel4
{
T elem ;
matel4 * next ;
2006-04-02 22:07:29 +02:00
union packed_index < I > index ;
2004-03-17 04:07:21 +01:00
} ;
2021-08-28 17:05:54 +02:00
//should not be packed
2004-03-17 04:07:21 +01:00
2006-04-02 22:07:29 +02:00
template < class I , class T >
2007-04-18 14:30:59 +02:00
struct matel4stored
2006-04-02 22:07:29 +02:00
{
T elem ;
union packed_index < I > index ;
2007-04-18 14:30:59 +02:00
}
# ifdef __GNUC__
__attribute__ ( ( packed ) )
# endif
;
2006-04-02 22:07:29 +02:00
2006-04-03 21:56:20 +02:00
//later add symmetry of complex integrals
2019-11-11 21:12:42 +01:00
typedef enum {
undefined_symmetry = - 1 ,
nosymmetry = 0 ,
2019-11-13 00:52:44 +01:00
twoelectronrealmullikan = 1 , twoelectronrealmullikanAA = 1 ,
2019-11-11 21:12:42 +01:00
twoelectronrealdirac = 2 ,
T2ijab_aces = 3 ,
trdm2AA = 3 ,
antisymtwoelectronrealdirac = 4 , rdm2AA = 4 ,
T2IjAb_aces = 5 , trdm2AB = 5 ,
twoelectronrealmullikanAB = 6 ,
T2ijab_unitary = 7 ,
T2IjAb_unitary = 8 ,
2021-09-30 14:55:26 +02:00
antisymtwoelectronrealdiracAB = 9 , rdm2AB = 9 , twoelectroncomplexmullikan_without_conjugation = 9 ,
2019-11-11 21:12:42 +01:00
twoelectronrealmullikanreducedsymAA = 10 ,
twoelectronrealmullikanreducedsymAB = 11 ,
2021-09-30 14:55:26 +02:00
twoelectroncomplexmullikan = 12 ,
2019-11-11 21:12:42 +01:00
} fourindexsymtype ; //only permutation-nonequivalent elements are stored
2005-12-08 11:35:50 +01:00
// these should actually be static private members of the fourindex class, but leads to an ICE on gcc3.2
2021-09-30 14:55:26 +02:00
static const int fourindex_n_symmetrytypes = 13 ;
static const int fourindex_permnumbers [ fourindex_n_symmetrytypes ] = { 1 , 8 , 8 , 4 , 8 , 1 , 4 , 8 , 2 , 2 , 4 , 2 , 4 } ;
2019-11-11 21:12:42 +01:00
static const int fourindex_permutations [ fourindex_n_symmetrytypes ] [ 9 ] [ 5 ] =
2005-12-08 11:35:50 +01:00
{
2019-11-11 21:12:42 +01:00
{ { 0 , 1 , 2 , 3 , 1 } } , //nosymmetry
{ { 0 , 1 , 2 , 3 , 1 } , { 1 , 0 , 2 , 3 , 1 } , { 0 , 1 , 3 , 2 , 1 } , { 1 , 0 , 3 , 2 , 1 } , { 2 , 3 , 0 , 1 , 1 } , { 3 , 2 , 0 , 1 , 1 } , { 2 , 3 , 1 , 0 , 1 } , { 3 , 2 , 1 , 0 , 1 } } , //twoelectronrealmullikan
{ { 0 , 1 , 2 , 3 , 1 } , { 2 , 1 , 0 , 3 , 1 } , { 0 , 3 , 2 , 1 , 1 } , { 2 , 3 , 0 , 1 , 1 } , { 1 , 0 , 3 , 2 , 1 } , { 3 , 0 , 1 , 2 , 1 } , { 1 , 2 , 3 , 0 , 1 } , { 3 , 2 , 1 , 0 , 1 } } , //twoelectronrealdirac
{ { 0 , 1 , 2 , 3 , 1 } , { 1 , 0 , 2 , 3 , - 1 } , { 0 , 1 , 3 , 2 , - 1 } , { 1 , 0 , 3 , 2 , 1 } } , //T2ijab_aces
{ { 0 , 1 , 2 , 3 , 1 } , { 1 , 0 , 2 , 3 , - 1 } , { 0 , 1 , 3 , 2 , - 1 } , { 1 , 0 , 3 , 2 , 1 } , { 2 , 3 , 0 , 1 , 1 } , { 3 , 2 , 0 , 1 , - 1 } , { 2 , 3 , 1 , 0 , - 1 } , { 3 , 2 , 1 , 0 , 1 } } , //antisymtwoelectronrealdirac
2008-06-17 16:01:57 +02:00
{ { 0 , 1 , 2 , 3 , 1 } } , //T2IjAb_aces is like nosymmetry but different index ranges
2019-11-11 21:12:42 +01:00
{ { 0 , 1 , 2 , 3 , 1 } , { 1 , 0 , 2 , 3 , 1 } , { 0 , 1 , 3 , 2 , 1 } , { 1 , 0 , 3 , 2 , 1 } } , //twoelectronrealmullikanAB
{ { 0 , 1 , 2 , 3 , 1 } , { 1 , 0 , 2 , 3 , - 1 } , { 0 , 1 , 3 , 2 , - 1 } , { 1 , 0 , 3 , 2 , 1 } , { 2 , 3 , 0 , 1 , - 1 } , { 3 , 2 , 0 , 1 , 1 } , { 2 , 3 , 1 , 0 , 1 } , { 3 , 2 , 1 , 0 , - 1 } } , //T2ijab_unitary (antiherm exponent)
{ { 0 , 1 , 2 , 3 , 1 } , { 2 , 3 , 0 , 1 , - 1 } } , //T2IjAb_unitary (antihermitian exponent)
{ { 0 , 1 , 2 , 3 , 1 } , { 2 , 3 , 0 , 1 , 1 } } , //antisymtwoelectronrealdiracAB
{ { 0 , 1 , 2 , 3 , 1 } , { 2 , 3 , 0 , 1 , 1 } , { 1 , 0 , 3 , 2 , 1 } , { 3 , 2 , 1 , 0 , 1 } } , //twoelectronrealmullikanreducedsymAA (e.g. unitary downfolded CC eff. integrals)
{ { 0 , 1 , 2 , 3 , 1 } , { 1 , 0 , 3 , 2 , 1 } } , //twoelectronrealmullikanreducedsymAB (e.g. unitary downfolded CC eff. integrals)
2021-09-30 14:55:26 +02:00
{ { 0 , 1 , 2 , 3 , 1 } , { 2 , 3 , 0 , 1 , 1 } , { 1 , 0 , 3 , 2 , 2 } , { 3 , 2 , 1 , 0 , 2 } } , //twoelectroncomplexmullikan ... 2 means complex conjugation
2005-12-08 11:35:50 +01:00
} ;
2004-03-17 04:07:21 +01:00
2006-04-03 21:56:20 +02:00
template < class I , class T >
void symmetry_faktor ( const fourindexsymtype symmetry , const union packed_index < I > & index , T & elem )
{
switch ( symmetry )
{
2019-11-13 00:52:44 +01:00
case twoelectronrealmullikanreducedsymAA :
if ( index . indiv . i = = index . indiv . j & & index . indiv . k = = index . indiv . l ) elem * = .5 ;
if ( index . indiv . i = = index . indiv . k & & index . indiv . j = = index . indiv . l ) elem * = .5 ;
break ;
case twoelectronrealmullikanreducedsymAB :
if ( index . indiv . i = = index . indiv . j & & index . indiv . k = = index . indiv . l ) elem * = .5 ;
break ;
2008-06-17 16:01:57 +02:00
case antisymtwoelectronrealdirac :
2019-11-11 21:12:42 +01:00
case antisymtwoelectronrealdiracAB :
2008-06-17 16:01:57 +02:00
laerror ( " not implemented " ) ;
2006-04-03 21:56:20 +02:00
case twoelectronrealmullikan :
if ( index . indiv . i = = index . indiv . j ) elem * = .5 ;
if ( index . indiv . k = = index . indiv . l ) elem * = .5 ;
if ( index . indiv . i = = index . indiv . k & & index . indiv . j = = index . indiv . l
| | index . indiv . i = = index . indiv . l & & index . indiv . j = = index . indiv . k ) elem * = .5 ;
break ;
case twoelectronrealdirac :
if ( index . indiv . i = = index . indiv . k ) elem * = .5 ;
if ( index . indiv . j = = index . indiv . l ) elem * = .5 ;
if ( index . indiv . i = = index . indiv . j & & index . indiv . k = = index . indiv . l
| | index . indiv . k = = index . indiv . j & & index . indiv . i = = index . indiv . l ) elem * = .5 ;
break ;
2006-09-09 21:51:04 +02:00
case T2ijab_aces : break ; //result will automatically vanish due to generated antisymmetry; i!=a from principle
case T2IjAb_aces : break ; //no actual symmetry
2006-04-03 21:56:20 +02:00
case nosymmetry : break ;
2019-11-13 00:52:44 +01:00
default : laerror ( " illegal symmetry or symmetry-redundant scaling factor not implemented " ) ;
2006-04-03 21:56:20 +02:00
}
}
2004-03-17 04:07:21 +01:00
template < class I , class T >
class fourindex {
protected :
fourindexsymtype symmetry ;
2005-12-08 12:44:36 +01:00
I nn ;
2004-03-17 04:07:21 +01:00
int * count ;
matel4 < I , T > * list ;
2019-11-13 00:52:44 +01:00
I terminator ;
bool doscaling ;
2004-03-17 04:07:21 +01:00
private :
void deletelist ( ) ;
void copylist ( const matel4 < I , T > * l ) ;
public :
//iterator
2008-11-26 14:30:30 +01:00
class iterator {
2004-03-17 04:07:21 +01:00
private :
matel4 < I , T > * p ;
public :
iterator ( ) { } ;
~ iterator ( ) { } ;
iterator ( matel4 < I , T > * list ) : p ( list ) { } ;
2005-12-08 11:35:50 +01:00
bool operator = = ( const iterator & rhs ) const { return p = = rhs . p ; }
bool operator ! = ( const iterator & rhs ) const { return p ! = rhs . p ; }
2005-12-08 12:44:36 +01:00
iterator & operator + + ( ) { p = p - > next ; return * this ; }
iterator operator + + ( int ) { iterator q ( p ) ; p = p - > next ; return q ; }
matel4 < I , T > & operator * ( ) { return * p ; }
matel4 < I , T > * operator - > ( ) { return p ; }
const matel4 < I , T > * operator - > ( ) const { return p ; }
const matel4 < I , T > & operator * ( ) const { return * p ; }
2004-03-17 04:07:21 +01:00
} ;
2019-11-13 00:52:44 +01:00
void setterminator ( const I terminator0 ) { terminator = terminator0 ; }
I getterminator ( ) const { return terminator ; }
void setscaling ( const bool doscaling0 ) { doscaling = doscaling0 ; }
2004-03-17 04:07:21 +01:00
iterator begin ( ) const { return list ; }
iterator end ( ) const { return NULL ; }
2005-12-08 11:35:50 +01:00
2019-11-13 00:52:44 +01:00
//permiterator ... iterates also over all permutations, with a possibly scaled matrix element for redundant results of the permutations
//it is assumed the original fourindex is the symmetry-reduced petite list, then the results of piterator contributions can be accumulated
2005-12-08 11:35:50 +01:00
//has to take into account the symmetry type of the fourindex
2008-11-26 14:30:30 +01:00
class piterator {
2005-12-08 11:35:50 +01:00
private :
2005-12-08 12:44:36 +01:00
fourindexsymtype symmetry ;
2005-12-08 11:35:50 +01:00
matel4 < I , T > * p ;
matel4 < I , T > my ;
int permindex ;
2019-11-13 00:52:44 +01:00
bool doscaling ;
2005-12-08 12:44:36 +01:00
void setup ( void ) //make a copy of *p to my with scaled element and anti/permuted indices
2005-12-08 11:35:50 +01:00
{
2006-04-03 03:43:02 +02:00
if ( symmetry = = undefined_symmetry ) laerror ( " fourindex symmetry has not been set " ) ;
2005-12-08 12:44:36 +01:00
if ( ! p ) { permindex = 0 ; memset ( & my , 0 , sizeof ( my ) ) ; return ; }
for ( int i = 0 ; i < 4 ; + + i )
my . index . packed [ i ] = p - > index . packed [ fourindex_permutations [ symmetry ] [ permindex ] [ i ] ] ;
my . elem = p - > elem * fourindex_permutations [ symmetry ] [ permindex ] [ 4 ] ;
2006-04-03 21:56:20 +02:00
//now treat the redundancy due to possibly equal indices by a scaling factor
2005-12-08 14:03:07 +01:00
//if the processing of individual term becomes very costly, an alternative would be to screen permutations yielding identical result
2019-11-13 00:52:44 +01:00
if ( doscaling ) symmetry_faktor ( symmetry , p - > index , my . elem ) ;
2005-12-08 11:35:50 +01:00
} ;
public :
piterator ( ) { } ;
2019-11-13 00:52:44 +01:00
piterator ( matel4 < I , T > * pp ) : symmetry ( nosymmetry ) , p ( pp ) , permindex ( 0 ) , doscaling ( true ) { } ;
2005-12-08 11:35:50 +01:00
~ piterator ( ) { } ;
2019-11-13 00:52:44 +01:00
piterator ( const fourindex & x ) : symmetry ( x . symmetry ) , p ( x . list ) , permindex ( 0 ) , doscaling ( x . doscaling ) { setup ( ) ; } ;
2005-12-08 13:06:23 +01:00
piterator & operator + + ( ) { if ( + + permindex > = fourindex_permnumbers [ symmetry ] ) { permindex = 0 ; p = p - > next ; } setup ( ) ; return * this ; }
2005-12-08 12:44:36 +01:00
const matel4 < I , T > & operator * ( ) const { return my ; }
const matel4 < I , T > * operator - > ( ) const { return & my ; }
2019-11-13 00:52:44 +01:00
piterator operator + + ( int ) { laerror ( " postincrement not possible on permute-iterator " ) ; return * this ; }
2006-04-03 00:54:40 +02:00
bool operator ! = ( const piterator & rhs ) const { return p ! = rhs . p ; } //should only be used for comparison with pend()
2005-12-08 14:03:07 +01:00
bool end ( void ) { return ! p ; }
bool notend ( void ) { return p ; }
2005-12-08 11:35:50 +01:00
} ;
2005-12-08 13:06:23 +01:00
piterator pbegin ( ) const { return piterator ( * this ) ; }
2006-04-03 00:54:40 +02:00
piterator pend ( ) const { return piterator ( NULL ) ; } //inefficient, use end() or notend() instead
2004-03-17 04:07:21 +01:00
//constructors etc.
2019-11-13 00:52:44 +01:00
inline fourindex ( ) : symmetry ( undefined_symmetry ) , nn ( 0 ) , count ( NULL ) , list ( NULL ) , terminator ( - 1 ) , doscaling ( true ) { } ;
inline fourindex ( const I n , const fourindexsymtype symmetry0 = undefined_symmetry , const I terminator0 = - 1 , const bool doscaling0 = true ) : nn ( n ) , count ( new int ( 1 ) ) , list ( NULL ) , symmetry ( symmetry0 ) , terminator ( terminator0 ) , doscaling ( doscaling0 ) { } ;
2004-03-17 04:07:21 +01:00
fourindex ( const fourindex & rhs ) ; //copy constructor
inline int getcount ( ) const { return count ? * count : 0 ; }
fourindex & operator = ( const fourindex & rhs ) ;
fourindex & operator + = ( const fourindex & rhs ) ;
2006-04-06 05:45:50 +02:00
void setsymmetry ( fourindexsymtype s ) { symmetry = s ; }
fourindexsymtype getsymmetry ( ) const { return symmetry ; }
2004-03-17 04:07:21 +01:00
fourindex & join ( fourindex & rhs ) ; //more efficient +=, rhs will be emptied
inline ~ fourindex ( ) ;
inline matel4 < I , T > * getlist ( ) const { return list ; }
inline I size ( ) const { return nn ; }
void resize ( const I n ) ;
2011-01-18 15:37:05 +01:00
void dealloc ( void ) { resize ( 0 ) ; }
2004-03-17 04:07:21 +01:00
void copyonwrite ( ) ;
2006-04-02 22:48:48 +02:00
unsigned long length ( ) const ;
2004-03-17 04:07:21 +01:00
inline void add ( const I i , const I j , const I k , const I l , const T elem )
{ matel4 < I , T > * ltmp = new matel4 < I , T > ; ltmp - > next = list ; list = ltmp ; list - > index . indiv . i = i ; list - > index . indiv . j = j ; list - > index . indiv . k = k ; list - > index . indiv . l = l ; list - > elem = elem ; }
2006-04-02 22:07:29 +02:00
inline void add ( const union packed_index < I > & index , const T elem )
2004-03-17 04:07:21 +01:00
{ matel4 < I , T > * ltmp = new matel4 < I , T > ; ltmp - > next = list ; list = ltmp ; list - > index = index ; list - > elem = elem ; }
inline void add ( const I ( & index ) [ 4 ] , const T elem )
2006-04-02 22:07:29 +02:00
{ matel4 < I , T > * ltmp = new matel4 < I , T > ; ltmp - > next = list ; list = ltmp ; memcpy ( & list - > index . packed , & index , sizeof ( union packed_index < I > ) ) ; list - > elem = elem ; }
2006-09-09 21:51:04 +02:00
inline void add ( const matel4 < I , T > & rhs )
{ matel4 < I , T > * ltmp = new matel4 < I , T > ; ltmp - > next = list ; list = ltmp ; memcpy ( & list - > index . packed , & rhs . index , sizeof ( union packed_index < I > ) ) ; list - > elem = rhs . elem ; }
inline void add ( const matel4stored < I , T > & rhs )
{ matel4 < I , T > * ltmp = new matel4 < I , T > ; ltmp - > next = list ; list = ltmp ; memcpy ( & list - > index . packed , & rhs . index , sizeof ( union packed_index < I > ) ) ; list - > elem = rhs . elem ; }
2006-04-06 00:06:24 +02:00
unsigned long put ( int fd , bool withattr = true ) const ;
unsigned long get ( int fd , bool withattr = true ) ;
2019-11-13 00:52:44 +01:00
void fscanf ( FILE * f ) ; //C-style formatted IO
void fprintf ( FILE * f , char * format ) const ;
2021-06-25 14:38:29 +02:00
void permuteme ( const NRPerm < int > & p , const bool inverse = false ) // index permutation
2021-06-25 11:45:11 +02:00
{
if ( p . size ( ) ! = nn ) laerror ( " inconsistent dimension in fourindex::permuteme " ) ;
copyonwrite ( ) ;
matel4 < I , T > * l = list ;
NRPerm < int > pp ; if ( inverse ) pp = p . inverse ( ) ; else pp = p ;
while ( l )
{
l - > index . indiv . i = ( I ) pp [ ( int ) l - > index . indiv . i ] ;
l - > index . indiv . j = ( I ) pp [ ( int ) l - > index . indiv . j ] ;
l - > index . indiv . k = ( I ) pp [ ( int ) l - > index . indiv . k ] ;
l - > index . indiv . l = ( I ) pp [ ( int ) l - > index . indiv . l ] ;
l = l - > next ;
}
}
2021-06-29 14:39:04 +02:00
void swap ( fourindex & rhs ) //more efficient swap than via tmp and constructors and operator=
{
I tmpnn = nn ; nn = rhs . nn ; rhs . nn = tmpnn ;
I tmpterminator = terminator ; terminator = rhs . terminator ; rhs . terminator = tmpterminator ;
int * tmpcount = count ; count = rhs . count ; rhs . count = tmpcount ;
matel4 < I , T > * tmplist = list ; list = rhs . list ; rhs . list = tmplist ;
bool tmpdoscaling = doscaling ; doscaling = rhs . doscaling ; rhs . doscaling = tmpdoscaling ;
fourindexsymtype tmpsymmetry = symmetry ; symmetry = rhs . symmetry ; rhs . symmetry = tmpsymmetry ;
}
2006-04-02 22:48:48 +02:00
} ;
2004-03-17 04:07:21 +01:00
2006-04-03 00:54:40 +02:00
//and a class for accessing a disc-stored fourindex, taking care of permutational index symmetry
2006-04-25 16:49:43 +02:00
//O_DIRECT approach to avoid filling of the buffer cache when reading
//large file sequentially is implemented:
//the user of the class must open the file with O_DIRECT
//NOTE!!! it will not work on linux 2.4, where O_DIRECT requires filesize to be a multiple of the block; 2.6 kernel is necessary!!!
2007-11-29 15:10:55 +01:00
//it used to work on older 2.6 kernels, but now does not work again since there is restriction to 512-byte alignment
2006-04-25 16:49:43 +02:00
2006-04-03 00:54:40 +02:00
template < class I , class T >
class fourindex_ext {
private : //at the moment for simplicity forbid some operations, otherwise reference counting on the buffer has to be done
fourindex_ext ( ) ;
fourindex_ext ( const fourindex_ext & rhs ) ;
fourindex_ext & operator = ( const fourindex_ext & rhs ) ;
protected :
2006-04-25 16:49:43 +02:00
matel4stored < I , T > * buffer0 ;
2006-04-03 00:54:40 +02:00
matel4stored < I , T > * buffer ;
matel4stored < I , T > * current ;
2006-04-03 04:01:45 +02:00
int fd ;
unsigned int bufsize ;
2006-04-03 00:54:40 +02:00
unsigned int nread ;
2006-04-03 04:01:45 +02:00
fourindexsymtype symmetry ;
I nn ;
2019-11-13 00:52:44 +01:00
bool doscaling ;
I terminator ;
2006-04-03 04:01:45 +02:00
//methods
2006-04-06 05:45:50 +02:00
void tryread ( ) const
2006-04-03 00:54:40 +02:00
{
2006-04-06 05:45:50 +02:00
const_cast < fourindex_ext < I , T > * > ( this ) - > current = NULL ;
2019-11-11 21:12:42 +01:00
errno = 0 ;
//printf("read %d %llx %d\n",fd,buffer,bufsize*sizeof(matel4stored<I,T>));
2006-04-03 00:54:40 +02:00
ssize_t r = read ( fd , buffer , bufsize * sizeof ( matel4stored < I , T > ) ) ;
2019-11-11 21:12:42 +01:00
if ( r < 0 ) { perror ( " read error " ) ; laerror ( " read error in fourindex_ext (might be bug of O_DIRECT) " ) ; }
2006-04-03 00:54:40 +02:00
if ( r % sizeof ( matel4stored < I , T > ) ) laerror ( " read inconsistency in fourindex_ext " ) ;
2006-04-06 05:45:50 +02:00
const_cast < fourindex_ext < I , T > * > ( this ) - > nread = r / sizeof ( matel4stored < I , T > ) ;
if ( nread ) const_cast < fourindex_ext < I , T > * > ( this ) - > current = buffer ;
2006-04-03 00:54:40 +02:00
}
2006-04-25 16:49:43 +02:00
void next ( ) const {
if ( current )
{
if ( ( unsigned int ) ( + + const_cast < fourindex_ext < I , T > * > ( this ) - > current - buffer ) > = nread ) tryread ( ) ;
}
}
2006-04-06 05:45:50 +02:00
bool eof ( ) const { return ! current ; } ;
2006-04-06 00:06:24 +02:00
2006-04-03 00:54:40 +02:00
public :
2019-11-13 00:52:44 +01:00
void setterminator ( const I terminator0 ) { terminator = terminator0 ; }
I getterminator ( ) const { return terminator ; }
void setscaling ( const bool doscaling0 ) { doscaling = doscaling0 ; }
2015-03-05 16:18:46 +01:00
void resize ( I n ) { nn = n ; }
2019-11-13 00:52:44 +01:00
fourindex_ext ( const int file , const fourindexsymtype s = undefined_symmetry , const I n = 0 , const unsigned int b = 1024 , const I terminator0 = - 1 , const bool doscaling0 = true ) : current ( NULL ) , fd ( file ) , nread ( 0 ) , symmetry ( s ) , nn ( n )
2006-04-25 16:49:43 +02:00
{
struct statfs sfs ;
2006-04-25 16:54:42 +02:00
struct stat64 sf ;
if ( fstat64 ( fd , & sf ) ) { perror ( " cannot fstat " ) ; laerror ( " I/O error " ) ; }
2006-04-25 16:49:43 +02:00
if ( fstatfs ( fd , & sfs ) ) { perror ( " cannot fstatfs " ) ; laerror ( " I/O error " ) ; }
const unsigned int pagesize = getpagesize ( ) ;
//make bufsize*sizeof(matel4stored<I,T>) a multiple of fs block size and page size
bufsize = b * sizeof ( matel4stored < I , T > ) ;
bufsize = lcm0 ( bufsize , pagesize ) ;
bufsize = lcm0 ( bufsize , sfs . f_bsize ) ;
bufsize = lcm0 ( bufsize , sf . st_blksize ) ;
buffer0 = new matel4stored < I , T > [ ( bufsize + pagesize ) / sizeof ( matel4stored < I , T > ) + 1 ] ; //ensure alignment at page boundary
unsigned char * buf = ( unsigned char * ) buffer0 ;
2019-11-11 21:12:42 +01:00
buf = buf + pagesize - ( ( uint64_t ) buf % pagesize ) ;
2006-04-25 16:49:43 +02:00
buffer = ( matel4stored < I , T > * ) buf ;
mlock ( buf , bufsize ) ; //ignore error when not root, hope we will not be paged out anyway
bufsize / = sizeof ( matel4stored < I , T > ) ;
2019-11-13 00:52:44 +01:00
terminator = terminator0 ;
doscaling = doscaling0 ;
2006-04-25 16:49:43 +02:00
}
~ fourindex_ext ( ) { if ( buffer0 ) delete [ ] buffer0 ; }
2006-04-03 00:54:40 +02:00
void setsymmetry ( fourindexsymtype s ) { symmetry = s ; } ;
2006-04-06 05:45:50 +02:00
fourindexsymtype getsymmetry ( ) const { return symmetry ; }
2006-04-25 16:49:43 +02:00
void rewind ( ) const { if ( 0 ! = lseek64 ( fd , 0L , SEEK_SET ) ) { perror ( " seek error " ) ; laerror ( " cannot seek in fourindex_ext " ) ; } } ;
2006-10-25 00:09:23 +02:00
//file output
void put ( const matel4stored < I , T > x )
{
if ( ! current ) current = buffer ;
* current + + = x ;
if ( current - buffer > = bufsize ) flush ( ) ;
}
void put ( I i , I j , I k , I l , const T & elem )
{
if ( ! current ) current = buffer ;
current - > index . indiv . i = i ;
current - > index . indiv . j = j ;
current - > index . indiv . k = k ;
current - > index . indiv . l = l ;
current - > elem = elem ;
+ + current ;
if ( current - buffer > = bufsize ) flush ( ) ;
}
void flush ( )
{
if ( current )
{
ssize_t r = write ( fd , buffer , ( current - buffer ) * sizeof ( matel4stored < I , T > ) ) ;
if ( r ! = ( current - buffer ) * sizeof ( matel4stored < I , T > ) ) laerror ( " write error in fourindex_ext " ) ;
}
current = NULL ;
}
2006-04-03 00:54:40 +02:00
inline I size ( ) const { return nn ; }
2006-04-19 16:04:52 +02:00
2006-04-03 00:54:40 +02:00
//iterator and permute-iterator are both implemented as poiters to the original class, using private functions of this class
//this is possible, since one instance of this class can have only one active iterator at a time
//iterator
2008-11-26 14:30:30 +01:00
class iterator {
2006-04-03 00:54:40 +02:00
private :
2006-04-06 05:45:50 +02:00
const fourindex_ext * base ;
2006-04-03 00:54:40 +02:00
public :
iterator ( ) { } ;
2006-04-06 05:45:50 +02:00
iterator ( const fourindex_ext * p ) : base ( p ) { } ;
2006-04-03 00:54:40 +02:00
~ iterator ( ) { } ;
bool operator ! = ( const iterator & rhs ) const { return base ! = rhs . base ; } //should only be used for comparison with end()
2006-04-03 04:01:45 +02:00
iterator & operator + + ( ) { if ( base ) base - > next ( ) ; if ( base - > eof ( ) ) base = NULL ; return * this ; }
2019-11-13 00:52:44 +01:00
iterator operator + + ( int ) { laerror ( " postincrement not possible " ) ; return * this ; }
2006-04-03 00:54:40 +02:00
const matel4stored < I , T > * operator - > ( ) const { return base - > current ; }
const matel4stored < I , T > & operator * ( ) const { return * base - > current ; }
2006-04-03 04:53:22 +02:00
bool notNULL ( ) const { return base ; }
2006-04-03 00:54:40 +02:00
} ;
2006-04-06 05:45:50 +02:00
iterator begin ( ) const { rewind ( ) ; tryread ( ) ; if ( ! eof ( ) ) return this ; else return NULL ; }
2006-04-03 04:01:45 +02:00
iterator end ( ) const { return iterator ( NULL ) ; }
2006-04-03 00:54:40 +02:00
2006-04-25 16:49:43 +02:00
2006-04-03 04:53:22 +02:00
//piterator ... iterate over all allowed permutations; conveniently expressed via the basic iterator which does the block-buffering
2008-11-26 14:30:30 +01:00
class piterator {
2006-04-03 04:53:22 +02:00
private :
fourindex_ext * base ;
2007-06-26 11:57:15 +02:00
matel4 < I , T > my ;
2006-04-03 04:53:22 +02:00
int permindex ;
2006-07-29 21:46:41 +02:00
typename fourindex_ext : : iterator it ;
2006-04-03 04:53:22 +02:00
//private methods
void setup ( void ) //make a copy of *it to my with scaled element and anti/permuted indices
{
if ( base - > symmetry = = undefined_symmetry ) laerror ( " fourindex symmetry has not been set " ) ;
if ( ! it . notNULL ( ) ) { permindex = 0 ; memset ( & my , 0 , sizeof ( my ) ) ; return ; } //we rely that end() is NULL
for ( int i = 0 ; i < 4 ; + + i )
my . index . packed [ i ] = it - > index . packed [ fourindex_permutations [ base - > symmetry ] [ permindex ] [ i ] ] ;
my . elem = it - > elem * fourindex_permutations [ base - > symmetry ] [ permindex ] [ 4 ] ;
2006-04-03 21:56:20 +02:00
//redundancy due to possibly equal indices
2006-04-03 04:53:22 +02:00
//if the processing of individual term becomes very costly, an alternative would be to screen permutations yielding identical result
2019-11-13 00:52:44 +01:00
if ( base - > doscaling ) symmetry_faktor ( base - > symmetry , it - > index , my . elem ) ;
2006-04-03 04:53:22 +02:00
} ;
public :
piterator ( ) { } ;
piterator ( fourindex_ext * p ) : base ( p ) , permindex ( 0 ) { if ( p ) { it = p - > begin ( ) ; setup ( ) ; } } ;
piterator ( fourindex_ext & x ) : base ( & x ) , permindex ( 0 ) { it = x . begin ( ) ; setup ( ) ; } ;
~ piterator ( ) { } ;
bool operator ! = ( const piterator & rhs ) const { return base ! = rhs . base ; } //should only be used for comparison with end()
piterator & operator + + ( ) { if ( + + permindex > = fourindex_permnumbers [ base - > symmetry ] ) { permindex = 0 ; + + it ; } if ( it . notNULL ( ) ) setup ( ) ; else base = NULL ; return * this ; }
2019-11-13 00:52:44 +01:00
piterator operator + + ( int ) { laerror ( " postincrement not possible " ) ; return * this ; }
2007-06-26 11:57:15 +02:00
const matel4 < I , T > * operator - > ( ) const { return & my ; }
const matel4 < I , T > & operator * ( ) const { return my ; }
2006-04-03 04:53:22 +02:00
bool end ( void ) { return ! base ; }
bool notend ( void ) { return base ; }
} ;
piterator pbegin ( ) { return piterator ( * this ) ; }
piterator pend ( ) const { return piterator ( NULL ) ; } //inefficient, use end() or notend() instead
2006-04-03 00:54:40 +02:00
} ;
2006-04-02 22:48:48 +02:00
/////////////////////////////implementations///////////////////////////////////
template < class I , class T >
2006-04-06 00:06:24 +02:00
unsigned long fourindex < I , T > : : put ( int fd , bool withattr ) const
2006-04-02 22:48:48 +02:00
{
unsigned long n = 0 ;
matel4 < I , T > * l = list ;
matel4stored < I , T > buf ;
2006-04-06 00:06:24 +02:00
if ( withattr )
{
union { fourindexsymtype sym ; I n ; T padding ; } u ;
u . sym = symmetry ;
if ( sizeof ( u ) ! = write ( fd , & u , sizeof ( u ) ) ) laerror ( " write error in fourindex::put " ) ;
u . n = nn ;
if ( sizeof ( u ) ! = write ( fd , & u , sizeof ( u ) ) ) laerror ( " write error in fourindex::put " ) ;
}
2006-04-02 22:48:48 +02:00
while ( l )
{
+ + n ;
buf . elem = l - > elem ;
2006-04-03 03:43:02 +02:00
buf . index = l - > index ;
if ( sizeof ( buf ) ! = write ( fd , & buf , sizeof ( buf ) ) ) laerror ( " write error in fourindex::put " ) ;
2006-04-02 22:48:48 +02:00
l = l - > next ;
}
return n ;
}
template < class I , class T >
2006-04-06 00:06:24 +02:00
unsigned long fourindex < I , T > : : get ( int fd , bool withattr )
2006-04-02 22:48:48 +02:00
{
unsigned long n = 0 ;
matel4stored < I , T > buf ;
2006-04-06 00:06:24 +02:00
if ( withattr )
{
union { fourindexsymtype sym ; I n ; T padding ; } u ;
if ( sizeof ( u ) ! = read ( fd , & u , sizeof ( u ) ) ) laerror ( " read inconsistency in fourindex::put " ) ;
symmetry = u . sym ;
if ( sizeof ( u ) ! = read ( fd , & u , sizeof ( u ) ) ) laerror ( " read inconsistency in fourindex::put " ) ;
nn = u . n ;
}
2006-04-03 03:43:02 +02:00
while ( sizeof ( buf ) = = read ( fd , & buf , sizeof ( buf ) ) ) { + + n ; add ( buf . index , buf . elem ) ; }
2006-04-02 22:48:48 +02:00
return n ;
}
2004-03-17 04:07:21 +01:00
//destructor
template < class I , class T >
fourindex < I , T > : : ~ fourindex ( )
{
if ( ! count ) return ;
if ( - - ( * count ) < = 0 )
{
deletelist ( ) ;
delete count ;
}
}
//copy constructor (sort arrays are not going to be copied)
template < class I , class T >
fourindex < I , T > : : fourindex ( const fourindex < I , T > & rhs )
{
# ifdef debug
if ( ! & rhs ) laerror ( " fourindex copy constructor with NULL argument " ) ;
# endif
nn = rhs . nn ;
if ( rhs . list & & ! rhs . count ) laerror ( " some inconsistency in fourindex contructors or assignments " ) ;
list = rhs . list ;
if ( list ) { count = rhs . count ; ( * count ) + + ; } else count = new int ( 1 ) ; //make the matrix defined, but empty and not shared
2019-11-13 00:52:44 +01:00
terminator = rhs . terminator ;
doscaling = rhs . doscaling ;
2004-03-17 04:07:21 +01:00
}
//assignment operator
template < class I , class T >
fourindex < I , T > & fourindex < I , T > : : operator = ( const fourindex < I , T > & rhs )
{
if ( this ! = & rhs )
{
if ( count )
if ( - - ( * count ) = = 0 ) { deletelist ( ) ; delete count ; } // old stuff obsolete
list = rhs . list ;
nn = rhs . nn ;
2019-11-13 00:52:44 +01:00
terminator = rhs . terminator ;
doscaling = rhs . doscaling ;
2004-03-17 04:07:21 +01:00
if ( list ) count = rhs . count ; else count = new int ( 0 ) ; //make the matrix defined, but empty and not shared, count will be incremented below
if ( count ) ( * count ) + + ;
}
return * this ;
}
template < class I , class T >
fourindex < I , T > & fourindex < I , T > : : operator + = ( const fourindex < I , T > & rhs )
{
if ( nn ! = rhs . nn ) laerror ( " incompatible dimensions for += " ) ;
if ( ! count ) { count = new int ; * count = 1 ; list = NULL ; }
else copyonwrite ( ) ;
register matel4 < I , T > * l = rhs . list ;
while ( l )
{
add ( l - > index , l - > elem ) ;
l = l - > next ;
}
return * this ;
}
template < class I , class T >
fourindex < I , T > & fourindex < I , T > : : join ( fourindex < I , T > & rhs )
{
if ( nn ! = rhs . nn ) laerror ( " incompatible dimensions for join " ) ;
if ( * rhs . count ! = 1 ) laerror ( " shared rhs in join() " ) ;
if ( ! count ) { count = new int ; * count = 1 ; list = NULL ; }
else copyonwrite ( ) ;
matel4 < I , T > * * last = & list ;
while ( * last ) last = & ( ( * last ) - > next ) ;
* last = rhs . list ;
rhs . list = NULL ;
return * this ;
}
template < class I , class T >
void fourindex < I , T > : : resize ( const I n )
{
if ( n < = 0 ) laerror ( " illegal fourindex dimension " ) ;
if ( count )
{
if ( * count > 1 ) { ( * count ) - - ; count = NULL ; list = NULL ; } //detach from previous
else if ( * count = = 1 ) deletelist ( ) ;
}
nn = n ;
count = new int ( 1 ) ; //empty but defined matrix
list = NULL ;
}
template < class I , class T >
void fourindex < I , T > : : deletelist ( )
{
if ( * count > 1 ) laerror ( " trying to delete shared list " ) ;
matel4 < I , T > * l = list ;
while ( l )
{
matel4 < I , T > * ltmp = l ;
l = l - > next ;
delete ltmp ;
}
list = NULL ;
delete count ;
count = NULL ;
}
template < class I , class T >
void fourindex < I , T > : : copylist ( const matel4 < I , T > * l )
{
list = NULL ;
while ( l )
{
add ( l - > index , l - > elem ) ;
l = l - > next ;
}
}
template < class I , class T >
void fourindex < I , T > : : copyonwrite ( )
{
if ( ! count ) laerror ( " probably an assignment to undefined fourindex " ) ;
if ( * count > 1 )
{
( * count ) - - ;
count = new int ; * count = 1 ;
if ( ! list ) laerror ( " empty list with count>1 " ) ;
copylist ( list ) ;
}
}
template < class I , class T >
2006-04-02 22:48:48 +02:00
unsigned long fourindex < I , T > : : length ( ) const
2004-03-17 04:07:21 +01:00
{
2006-04-02 22:48:48 +02:00
unsigned long n = 0 ;
2004-03-17 04:07:21 +01:00
matel4 < I , T > * l = list ;
while ( l )
{
+ + n ;
l = l - > next ;
}
return n ;
}
2019-11-13 00:52:44 +01:00
2006-04-03 00:54:40 +02:00
template < class I , class T >
2009-11-12 22:01:19 +01:00
std : : ostream & operator < < ( std : : ostream & s , const fourindex_ext < I , T > & x )
2006-04-03 00:54:40 +02:00
{
int n ;
n = x . size ( ) ;
s < < n < < ' \n ' ;
2006-05-28 16:53:36 +02:00
typename fourindex_ext < I , T > : : iterator it = x . begin ( ) ;
2006-04-03 00:54:40 +02:00
while ( it ! = x . end ( ) )
{
2006-04-03 03:43:02 +02:00
s < < ( typename LA_traits_io < I > : : IOtype ) it - > index . indiv . i < < ' ' < < ( typename LA_traits_io < I > : : IOtype ) it - > index . indiv . j < < ' ' < < ( typename LA_traits_io < I > : : IOtype ) it - > index . indiv . k < < ' ' < < ( typename LA_traits_io < I > : : IOtype ) it - > index . indiv . l < < ' ' < < ( typename LA_traits_io < T > : : IOtype ) it - > elem < < ' \n ' ;
2006-04-03 00:54:40 +02:00
+ + it ;
}
2019-11-13 00:52:44 +01:00
s < < ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) < < ' ' < < ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) < < ' ' < < ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) < < ' ' < < ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) < < ' ' < < ( typename LA_traits_io < T > : : IOtype ) 0 < < ' \n ' ;
2006-04-03 00:54:40 +02:00
return s ;
}
2004-03-17 04:07:21 +01:00
template < class I , class T >
2009-11-12 22:01:19 +01:00
std : : ostream & operator < < ( std : : ostream & s , const fourindex < I , T > & x )
2004-03-17 04:07:21 +01:00
{
int n ;
n = x . size ( ) ;
s < < n < < ' \n ' ;
2004-03-25 16:27:19 +01:00
typename fourindex < I , T > : : iterator it = x . begin ( ) , end = x . end ( ) ;
while ( it ! = end )
2004-03-17 04:07:21 +01:00
{
2006-04-03 03:43:02 +02:00
s < < ( typename LA_traits_io < I > : : IOtype ) it - > index . indiv . i < < ' ' < < ( typename LA_traits_io < I > : : IOtype ) it - > index . indiv . j < < ' ' < < ( typename LA_traits_io < I > : : IOtype ) it - > index . indiv . k < < ' ' < < ( typename LA_traits_io < I > : : IOtype ) it - > index . indiv . l < < ' ' < < ( typename LA_traits_io < T > : : IOtype ) it - > elem < < ' \n ' ;
2004-03-17 04:07:21 +01:00
+ + it ;
}
2019-11-13 00:52:44 +01:00
s < < ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) < < ' ' < < ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) < < ' ' < < ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) < < ' ' < < ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) < < ' ' < < ( typename LA_traits_io < T > : : IOtype ) 0 < < ' \n ' ;
2004-03-17 04:07:21 +01:00
return s ;
}
template < class I , class T >
2009-11-12 22:01:19 +01:00
std : : istream & operator > > ( std : : istream & s , fourindex < I , T > & x )
2004-03-17 04:07:21 +01:00
{
2006-04-03 03:43:02 +02:00
typename LA_traits_io < I > : : IOtype i , j , k , l ;
2006-04-02 22:07:29 +02:00
typename LA_traits_io < T > : : IOtype elem ;
2004-03-17 04:07:21 +01:00
int n ;
s > > n ;
x . resize ( n ) ;
s > > i > > j > > k > > l ;
2019-11-13 00:52:44 +01:00
while ( i ! = ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) & & j ! = ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) & & k ! = ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) & & l ! = ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) )
2004-03-17 04:07:21 +01:00
{
s > > elem ;
2006-04-03 03:43:02 +02:00
x . add ( ( I ) i , ( I ) j , ( I ) k , ( I ) l , ( T ) elem ) ;
2005-09-11 22:04:24 +02:00
s > > i > > j > > k > > l ;
2004-03-17 04:07:21 +01:00
}
return s ;
}
2015-03-05 16:18:46 +01:00
template < class I , class T >
std : : istream & operator > > ( std : : istream & s , fourindex_ext < I , T > & x )
{
int n ;
s > > n ;
x . resize ( n ) ;
typename LA_traits_io < I > : : IOtype i , j , k , l ;
typename LA_traits_io < T > : : IOtype elem ;
s > > i > > j > > k > > l ;
2019-11-13 00:52:44 +01:00
while ( i ! = ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) & & j ! = ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) & & k ! = ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) & & l ! = ( typename LA_traits_io < I > : : IOtype ) x . getterminator ( ) )
2015-03-05 16:18:46 +01:00
{
s > > elem ;
x . put ( ( I ) i , ( I ) j , ( I ) k , ( I ) l , ( T ) elem ) ;
s > > i > > j > > k > > l ;
}
x . flush ( ) ;
return s ;
}
2006-09-09 21:51:04 +02:00
2006-04-06 04:12:19 +02:00
/////////////////////densely stored fourindex///////////////////////////////////
//not all symmetry cases implemented yet, but a general template declaration used
//we use a general template forward declaration, but then it has to be done differently for (almost) each case
//by means of partial template specialization
2006-04-07 07:00:44 +02:00
//note - loops for the twoelectronrealmullikan integral to be unique and in canonical order
// i=1..n, j=1..i, k=1..i, l=1..(i==k?j:k)
2006-09-18 23:46:45 +02:00
//general template declaration
2006-04-06 04:12:19 +02:00
template < fourindexsymtype S , class T , class DUMMY > class fourindex_dense ;
2006-09-18 23:46:45 +02:00
//traits class
template < fourindexsymtype S , class T , class DUMMY >
struct LA_traits < fourindex_dense < S , T , DUMMY > > {
typedef T elementtype ;
typedef typename LA_traits < T > : : normtype normtype ;
} ;
2006-04-06 04:12:19 +02:00
//make it as a derived class in order to be able to use it in a base class context - "supermatrix" operations
2021-06-30 16:13:24 +02:00
//note - loops for the twoelectronrealmullikanAB integral to be unique and in canonical order
// i=1..n, j=1..i, k=1..n, l=1..k
2006-04-06 04:12:19 +02:00
template < class T , class I >
2013-11-04 15:56:39 +01:00
class fourindex_dense < twoelectronrealmullikanAB , T , I > : public NRMat < T > {
public :
fourindex_dense ( ) : NRMat < T > ( ) { } ;
explicit fourindex_dense ( const int n ) : NRMat < T > ( n * ( n + 1 ) / 2 , n * ( n + 1 ) / 2 ) { } ;
fourindex_dense ( const NRMat < T > & rhs ) : NRMat < T > ( rhs ) { } ; //be able to convert the parent class transparently to this
fourindex_dense ( const T & a , const int n ) : NRMat < T > ( a , n * ( n + 1 ) / 2 , n * ( n + 1 ) / 2 ) { } ;
fourindex_dense ( const T * a , const int n ) : NRMat < T > ( a , n * ( n + 1 ) / 2 , n * ( n + 1 ) / 2 ) { } ;
//and also construct it from sparse and externally stored fourindex classes
//it seems not possible to nest template<class I> just for the two constructors
fourindex_dense ( const fourindex < I , T > & rhs ) ;
fourindex_dense ( const fourindex_ext < I , T > & rhs ) ;
T & operator ( ) ( unsigned int i , unsigned int j , unsigned int k , unsigned int l ) ;
const T & operator ( ) ( unsigned int i , unsigned int j , unsigned int k , unsigned int l ) const ;
void resize ( const int n ) { ( * this ) . NRMat < T > : : resize ( n * ( n + 1 ) / 2 , n * ( n + 1 ) / 2 ) ; } ;
void putext ( int f , T thr = 1e-15 ) ;
int nbas ( ) const { return ( int ) std : : sqrt ( 2 * ( * this ) . nrows ( ) ) ; } ;
} ;
template < class T , class I >
void fourindex_dense < twoelectronrealmullikanAB , T , I > : : putext ( int f , T thr )
{
T y ;
for ( int i = 1 ; i < = nbas ( ) ; + + i ) for ( int j = 1 ; j < = i ; + + j )
for ( int k = 1 ; k < = nbas ( ) ; + + k ) for ( int l = 1 ; l < = k ; + + l )
2021-09-24 17:32:20 +02:00
{
y = ( * this ) ( i , j , k , l ) ;
if ( abs ( y ) > thr )
2013-11-04 15:56:39 +01:00
{
matel4stored < I , T > x ;
x . elem = y ;
x . index . indiv . i = i ;
x . index . indiv . j = j ;
x . index . indiv . k = k ;
x . index . indiv . l = l ;
if ( sizeof ( matel4stored < I , T > ) ! = write ( f , & x , sizeof ( matel4stored < I , T > ) ) )
laerror ( " write error in putext " ) ;
}
2021-09-24 17:32:20 +02:00
}
2013-11-04 15:56:39 +01:00
}
template < class T , class I >
fourindex_dense < twoelectronrealmullikanAB , T , I > : : fourindex_dense ( const fourindex < I , T > & rhs ) : NRMat < T > ( ( T ) 0 , rhs . size ( ) * ( rhs . size ( ) + 1 ) / 2 , rhs . size ( ) * ( rhs . size ( ) + 1 ) / 2 )
{
if ( rhs . getsymmetry ( ) ! = twoelectronrealmullikanAB ) laerror ( " fourindex_dense symmetry mismatch " ) ;
typename fourindex < I , T > : : iterator p ;
# ifdef DEBUG
unsigned int IJ = SMat_index_1 ( p - > index . indiv . i , p - > index . indiv . j ) ;
unsigned int KL = SMat_index_1 ( p - > index . indiv . k , p - > index . indiv . l ) ;
if ( IJ < 0 | | IJ > = ( unsigned int ) NRMat < T > : : nn | | KL < 0 | | KL > = ( unsigned int ) NRMat < T > : : mm ) laerror ( " fourindex_dense index out of range in constructor " ) ;
# endif
for ( p = rhs . begin ( ) ; p ! = rhs . end ( ) ; + + p ) ( * this ) ( p - > index . indiv . i , p - > index . indiv . j , p - > index . indiv . k , p - > index . indiv . l ) = p - > elem ;
}
template < class T , class I >
fourindex_dense < twoelectronrealmullikanAB , T , I > : : fourindex_dense ( const fourindex_ext < I , T > & rhs ) : NRMat < T > ( ( T ) 0 , rhs . size ( ) * ( rhs . size ( ) + 1 ) / 2 , rhs . size ( ) * ( rhs . size ( ) + 1 ) / 2 )
{
if ( rhs . getsymmetry ( ) ! = twoelectronrealmullikanAB ) laerror ( " fourindex_dense symmetry mismatch " ) ;
typename fourindex_ext < I , T > : : iterator p ;
for ( p = rhs . begin ( ) ; p ! = rhs . end ( ) ; + + p )
{
# ifdef DEBUG
unsigned int IJ = SMat_index_1 ( p - > index . indiv . i , p - > index . indiv . j ) ;
unsigned int KL = SMat_index_1 ( p - > index . indiv . k , p - > index . indiv . l ) ;
if ( IJ < 0 | | IJ > = ( unsigned int ) NRMat < T > : : nn | | KL < 0 | | KL > = ( unsigned int ) NRMat < T > : : mm ) laerror ( " fourindex_dense index out of range in constructor " ) ;
# endif
( * this ) ( p - > index . indiv . i , p - > index . indiv . j , p - > index . indiv . k , p - > index . indiv . l ) = p - > elem ;
}
}
template < class T , class DUMMY >
T & fourindex_dense < twoelectronrealmullikanAB , T , DUMMY > : : operator ( ) ( unsigned int i , unsigned int j , unsigned int k , unsigned int l )
{
int I = SMat_index_1 ( i , j ) ;
int J = SMat_index_1 ( k , l ) ;
//I,J act as indices of a NRmat
# ifdef DEBUG
if ( * NRMat < T > : : count ! = 1 ) laerror ( " lval (i,j,k,l) with count > 1 in fourindex_dense " ) ;
if ( I < 0 | | I > = NRMat < T > : : nn | | J < 0 | | J > = NRMat < T > : : mm ) laerror ( " fourindex_dense index out of range " ) ;
if ( ! NRMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
# endif
return NRMat < T > : : operator ( ) ( I , J ) ;
}
template < class T , class DUMMY >
const T & fourindex_dense < twoelectronrealmullikanAB , T , DUMMY > : : operator ( ) ( unsigned int i , unsigned int j , unsigned int k , unsigned int l ) const
{
int I = SMat_index_1 ( i , j ) ;
int J = SMat_index_1 ( k , l ) ;
//I,J act as indices of a NRSmat
# ifdef DEBUG
if ( I < 0 | | I > = NRMat < T > : : nn | | J < 0 | | J > = NRMat < T > : : mm ) laerror ( " fourindex_dense index out of range " ) ;
if ( ! NRMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
# endif
return NRMat < T > : : operator ( ) ( I , J ) ;
}
////////////////////
template < class T , class I >
2006-04-06 04:12:19 +02:00
class fourindex_dense < twoelectronrealmullikan , T , I > : public NRSMat < T > {
public :
fourindex_dense ( ) : NRSMat < T > ( ) { } ;
explicit fourindex_dense ( const int n ) : NRSMat < T > ( n * ( n + 1 ) / 2 ) { } ;
fourindex_dense ( const NRSMat < T > & rhs ) : NRSMat < T > ( rhs ) { } ; //be able to convert the parent class transparently to this
fourindex_dense ( const T & a , const int n ) : NRSMat < T > ( a , n * ( n + 1 ) / 2 ) { } ;
fourindex_dense ( const T * a , const int n ) : NRSMat < T > ( a , n * ( n + 1 ) / 2 ) { } ;
//and also construct it from sparse and externally stored fourindex classes
//it seems not possible to nest template<class I> just for the two constructors
fourindex_dense ( const fourindex < I , T > & rhs ) ;
fourindex_dense ( const fourindex_ext < I , T > & rhs ) ;
T & operator ( ) ( unsigned int i , unsigned int j , unsigned int k , unsigned int l ) ;
const T & operator ( ) ( unsigned int i , unsigned int j , unsigned int k , unsigned int l ) const ;
2007-11-29 15:10:55 +01:00
void resize ( const int n ) { ( * this ) . NRSMat < T > : : resize ( n * ( n + 1 ) / 2 ) ; } ;
2008-07-15 15:35:08 +02:00
void putext ( int f , T thr = 1e-15 ) ;
2009-11-12 22:01:19 +01:00
int nbas ( ) const { return ( int ) std : : sqrt ( 2 * ( * this ) . nrows ( ) ) ; } ;
2006-04-06 04:12:19 +02:00
} ;
2008-07-15 15:35:08 +02:00
template < class T , class I >
2008-07-15 16:28:38 +02:00
void fourindex_dense < twoelectronrealmullikan , T , I > : : putext ( int f , T thr )
2008-07-15 15:35:08 +02:00
{
T y ;
for ( int i = 1 ; i < = nbas ( ) ; + + i ) for ( int j = 1 ; j < = i ; + + j )
for ( int k = 1 ; k < = i ; + + k ) for ( int l = 1 ; l < = ( i = = k ? j : k ) ; + + l )
2021-09-24 17:32:20 +02:00
{
y = ( * this ) ( i , j , k , l ) ;
if ( abs ( y ) > thr )
2008-07-15 15:35:08 +02:00
{
matel4stored < I , T > x ;
x . elem = y ;
x . index . indiv . i = i ;
x . index . indiv . j = j ;
x . index . indiv . k = k ;
x . index . indiv . l = l ;
2008-07-15 16:28:38 +02:00
if ( sizeof ( matel4stored < I , T > ) ! = write ( f , & x , sizeof ( matel4stored < I , T > ) ) )
2008-07-15 15:35:08 +02:00
laerror ( " write error in putext " ) ;
}
2021-09-24 17:32:20 +02:00
}
2008-07-15 15:35:08 +02:00
}
2006-04-06 04:12:19 +02:00
template < class T , class I >
2006-09-10 22:06:44 +02:00
fourindex_dense < twoelectronrealmullikan , T , I > : : fourindex_dense ( const fourindex < I , T > & rhs ) : NRSMat < T > ( ( T ) 0 , rhs . size ( ) * ( rhs . size ( ) + 1 ) / 2 )
2006-04-06 04:12:19 +02:00
{
2006-04-06 05:45:50 +02:00
if ( rhs . getsymmetry ( ) ! = twoelectronrealmullikan ) laerror ( " fourindex_dense symmetry mismatch " ) ;
2006-04-06 04:12:19 +02:00
typename fourindex < I , T > : : iterator p ;
2006-08-16 23:43:45 +02:00
# ifdef DEBUG
2006-09-09 21:51:04 +02:00
unsigned int IJ = SMat_index_1 ( p - > index . indiv . i , p - > index . indiv . j ) ;
unsigned int KL = SMat_index_1 ( p - > index . indiv . k , p - > index . indiv . l ) ;
if ( IJ < 0 | | IJ > = ( unsigned int ) NRSMat < T > : : nn | | KL < 0 | | KL > = ( unsigned int ) NRSMat < T > : : nn ) laerror ( " fourindex_dense index out of range in constructor " ) ;
2006-08-16 23:43:45 +02:00
# endif
2006-04-06 04:12:19 +02:00
for ( p = rhs . begin ( ) ; p ! = rhs . end ( ) ; + + p ) ( * this ) ( p - > index . indiv . i , p - > index . indiv . j , p - > index . indiv . k , p - > index . indiv . l ) = p - > elem ;
}
template < class T , class I >
2006-09-10 22:06:44 +02:00
fourindex_dense < twoelectronrealmullikan , T , I > : : fourindex_dense ( const fourindex_ext < I , T > & rhs ) : NRSMat < T > ( ( T ) 0 , rhs . size ( ) * ( rhs . size ( ) + 1 ) / 2 )
2006-04-06 04:12:19 +02:00
{
2006-04-06 05:45:50 +02:00
if ( rhs . getsymmetry ( ) ! = twoelectronrealmullikan ) laerror ( " fourindex_dense symmetry mismatch " ) ;
2006-04-06 04:12:19 +02:00
typename fourindex_ext < I , T > : : iterator p ;
2006-09-11 18:00:39 +02:00
for ( p = rhs . begin ( ) ; p ! = rhs . end ( ) ; + + p )
{
2006-08-16 23:43:45 +02:00
# ifdef DEBUG
2006-09-09 21:51:04 +02:00
unsigned int IJ = SMat_index_1 ( p - > index . indiv . i , p - > index . indiv . j ) ;
unsigned int KL = SMat_index_1 ( p - > index . indiv . k , p - > index . indiv . l ) ;
if ( IJ < 0 | | IJ > = ( unsigned int ) NRSMat < T > : : nn | | KL < 0 | | KL > = ( unsigned int ) NRSMat < T > : : nn ) laerror ( " fourindex_dense index out of range in constructor " ) ;
2006-08-16 23:43:45 +02:00
# endif
2006-09-11 18:00:39 +02:00
( * this ) ( p - > index . indiv . i , p - > index . indiv . j , p - > index . indiv . k , p - > index . indiv . l ) = p - > elem ;
}
2006-04-06 04:12:19 +02:00
}
template < class T , class DUMMY >
T & fourindex_dense < twoelectronrealmullikan , T , DUMMY > : : operator ( ) ( unsigned int i , unsigned int j , unsigned int k , unsigned int l )
{
2008-06-17 17:01:37 +02:00
int I = SMat_index_1 ( i , j ) ;
int J = SMat_index_1 ( k , l ) ;
2006-04-06 04:12:19 +02:00
//I,J act as indices of a NRSmat
# ifdef DEBUG
2006-07-29 22:07:02 +02:00
if ( * NRSMat < T > : : count ! = 1 ) laerror ( " lval (i,j,k,l) with count > 1 in fourindex_dense " ) ;
2008-06-17 17:01:37 +02:00
if ( I < 0 | | I > = NRSMat < T > : : nn | | J < 0 | | J > = NRSMat < T > : : nn ) laerror ( " fourindex_dense index out of range " ) ;
2006-07-29 21:46:41 +02:00
if ( ! NRSMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
2006-04-06 04:12:19 +02:00
# endif
2006-07-29 21:46:41 +02:00
return NRSMat < T > : : v [ SMat_index ( I , J ) ] ;
2006-04-06 04:12:19 +02:00
}
2006-07-29 22:07:02 +02:00
2006-04-06 04:12:19 +02:00
template < class T , class DUMMY >
const T & fourindex_dense < twoelectronrealmullikan , T , DUMMY > : : operator ( ) ( unsigned int i , unsigned int j , unsigned int k , unsigned int l ) const
{
2008-06-17 17:01:37 +02:00
int I = SMat_index_1 ( i , j ) ;
int J = SMat_index_1 ( k , l ) ;
2006-04-06 04:12:19 +02:00
//I,J act as indices of a NRSmat
# ifdef DEBUG
2008-06-17 17:01:37 +02:00
if ( I < 0 | | I > = NRSMat < T > : : nn | | J < 0 | | J > = NRSMat < T > : : nn ) laerror ( " fourindex_dense index out of range " ) ;
2006-07-29 21:46:41 +02:00
if ( ! NRSMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
2006-04-06 04:12:19 +02:00
# endif
2006-07-29 21:46:41 +02:00
return NRSMat < T > : : v [ SMat_index ( I , J ) ] ;
2006-04-06 04:12:19 +02:00
}
2019-11-13 00:52:44 +01:00
template < class T , class I >
class fourindex_dense < nosymmetry , T , I > : public NRMat < T > {
protected :
unsigned int nn ;
friend class explicit_t2 ;
public :
fourindex_dense ( ) : NRMat < T > ( ) { nn = 0 ; } ;
void resize ( const int nnn ) { nn = nnn ; ( * this ) . NRMat < T > : : resize ( nn * nn , nn * nn ) ; } ;
explicit fourindex_dense ( const int nnn ) : NRMat < T > ( nnn * nnn , nnn * nnn ) { nn = nnn ; } ;
inline T & operator ( ) ( unsigned int i , unsigned int j , unsigned int a , unsigned int b )
{
# ifdef DEBUG
if ( i < 1 | | i > nn | | j < 1 | | j > nn | | a < 1 | | a > nn | | b < 1 | | b > nn ) laerror ( " nosymmetry fourindex out of range " ) ;
if ( ! NRMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
# endif
return ( * this ) . NRMat < T > : : operator ( ) ( ( j - 1 ) * nn + i - 1 , ( b - 1 ) * nn + a - 1 ) ;
}
inline const T & operator ( ) ( unsigned int i , unsigned int j , unsigned int a , unsigned int b ) const
{
# ifdef DEBUG
if ( i < 1 | | i > nn | | j < 1 | | j > nn | | a < 1 | | a > nn | | b < 1 | | b > nn ) laerror ( " nosymmetry fourindex out of range " ) ;
if ( ! NRMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
# endif
return ( * this ) . NRMat < T > : : operator ( ) ( ( j - 1 ) * nn + i - 1 , ( b - 1 ) * nn + a - 1 ) ;
}
void print ( std : : ostream & out ) const
{
unsigned int i , j , a , b ;
for ( i = 1 ; i < = nn ; + + i ) for ( j = 1 ; j < = nn ; + + j ) for ( a = 1 ; a < = nn ; + + a ) for ( b = 1 ; b < = nn ; + + b ) out < < i < < " " < < j < < " " < < a < < " " < < b < < " " < < ( * this ) ( i , j , a , b ) < < std : : endl ;
}
} ;
2006-04-06 04:12:19 +02:00
2006-09-09 21:51:04 +02:00
//access to spin-blocks of T2 amplitudes in aces storage order
//both occupied and virtual indices start from 1
template < class T , class I >
class fourindex_dense < T2IjAb_aces , T , I > : public NRMat < T > {
2008-07-15 15:35:08 +02:00
protected :
2006-09-09 21:51:04 +02:00
unsigned int noca , nocb , nvra , nvrb ;
2008-07-15 15:35:08 +02:00
friend class explicit_t2 ;
2006-09-09 21:51:04 +02:00
public :
fourindex_dense ( ) : NRMat < T > ( ) { noca = nocb = nvra = nvrb = 0 ; } ;
2006-09-18 00:21:54 +02:00
void resize ( const int nocca , const int noccb , const int nvrta , const int nvrtb ) { noca = nocca ; nocb = noccb ; nvra = nvrta ; nvrb = nvrtb ; ( * this ) . NRMat < T > : : resize ( nocca * noccb , nvrta * nvrtb ) ; } ;
2006-09-09 21:51:04 +02:00
explicit fourindex_dense ( const int nocca , const int noccb , const int nvrta , const int nvrtb ) : NRMat < T > ( nocca * noccb , nvrta * nvrtb ) { noca = nocca ; nocb = noccb ; nvra = nvrta ; nvrb = nvrtb ; } ;
//here i,a are alpha j,b beta
inline T & operator ( ) ( unsigned int i , unsigned int j , unsigned int a , unsigned int b )
{
# ifdef DEBUG
2006-09-11 17:56:49 +02:00
if ( i < 1 | | i > noca | | j < 1 | | j > nocb | | a < 1 | | a > nvra | | b < 1 | | b > nvrb ) laerror ( " T2IjAb_aces fourindex out of range " ) ;
2006-09-09 21:51:04 +02:00
if ( ! NRMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
# endif
return ( * this ) . NRMat < T > : : operator ( ) ( ( j - 1 ) * noca + i - 1 , ( b - 1 ) * nvra + a - 1 ) ;
}
inline const T & operator ( ) ( unsigned int i , unsigned int j , unsigned int a , unsigned int b ) const
{
# ifdef DEBUG
2006-09-11 17:56:49 +02:00
if ( i < 1 | | i > noca | | j < 1 | | j > nocb | | a < 1 | | a > nvra | | b < 1 | | b > nvrb ) laerror ( " T2IjAb_aces fourindex out of range " ) ;
2006-09-09 21:51:04 +02:00
if ( ! NRMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
# endif
return ( * this ) . NRMat < T > : : operator ( ) ( ( j - 1 ) * noca + i - 1 , ( b - 1 ) * nvra + a - 1 ) ;
}
2008-06-02 18:15:55 +02:00
2009-11-12 22:01:19 +01:00
void print ( std : : ostream & out ) const
2008-06-02 18:15:55 +02:00
{
unsigned int i , j , a , b ;
2009-11-12 22:01:19 +01:00
for ( i = 1 ; i < = noca ; + + i ) for ( j = 1 ; j < = nocb ; + + j ) for ( a = 1 ; a < = nvra ; + + a ) for ( b = 1 ; b < = nvrb ; + + b ) out < < i < < " " < < j < < " " < < a < < " " < < b < < " " < < ( * this ) ( i , j , a , b ) < < std : : endl ;
2008-06-02 18:15:55 +02:00
}
2006-09-09 21:51:04 +02:00
} ;
2019-11-11 21:12:42 +01:00
template < class T , class I >
class fourindex_dense < antisymtwoelectronrealdiracAB , T , I > : public NRSMat < T > {
protected :
unsigned int nbas ;
friend class explicit_t2 ;
public :
fourindex_dense ( ) : NRSMat < T > ( ) { nbas = 0 ; } ;
void resize ( const int n ) { nbas = n ; ( * this ) . NRSMat < T > : : resize ( nbas * nbas ) ; } ;
explicit fourindex_dense ( const int n ) : NRSMat < T > ( n * n ) { nbas = n ; } ;
//here i,a are alpha j,b beta
inline T & operator ( ) ( unsigned int i , unsigned int j , unsigned int a , unsigned int b )
{
# ifdef DEBUG
if ( i < 1 | | i > nbas | | j < 1 | | j > nbas | | a < 1 | | a > nbas | | b < 1 | | b > nbas ) laerror ( " antisymtwoelectronrealdiracAB fourindex out of range " ) ;
if ( ! NRSMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
# endif
return ( * this ) . NRSMat < T > : : operator ( ) ( ( j - 1 ) * nbas + i - 1 , ( b - 1 ) * nbas + a - 1 ) ;
}
inline const T & operator ( ) ( unsigned int i , unsigned int j , unsigned int a , unsigned int b ) const
{
# ifdef DEBUG
if ( i < 1 | | i > nbas | | j < 1 | | j > nbas | | a < 1 | | a > nbas | | b < 1 | | b > nbas ) laerror ( " antisymtwoelectronrealdiracAB fourindex out of range " ) ;
if ( ! NRSMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
# endif
return ( * this ) . NRSMat < T > : : operator ( ) ( ( j - 1 ) * nbas + i - 1 , ( b - 1 ) * nbas + a - 1 ) ;
}
void print ( std : : ostream & out ) const
{
unsigned int i , j , a , b ;
for ( i = 1 ; i < = nbas ; + + i ) for ( j = 1 ; j < = nbas ; + + j )
for ( a = 1 ; a < = i ; + + a ) for ( b = 1 ; b < = ( a < i ? nbas : j ) ; + + b )
out < < i < < " " < < j < < " " < < a < < " " < < b < < " " < < ( * this ) ( i , j , a , b ) < < std : : endl ;
}
} ;
2006-09-09 21:51:04 +02:00
template < class T , class I >
class fourindex_dense < T2ijab_aces , T , I > : public NRMat < T > {
2008-07-15 15:35:08 +02:00
protected :
2006-09-09 21:51:04 +02:00
unsigned int nocc , nvrt , ntri ;
2008-07-15 15:35:08 +02:00
friend class explicit_t2 ;
2006-09-09 21:51:04 +02:00
public :
fourindex_dense ( ) : NRMat < T > ( ) { nocc = nvrt = ntri = 0 ; } ;
explicit fourindex_dense ( const int noc , const int nvr ) : NRMat < T > ( noc * ( noc - 1 ) / 2 , nvr * ( nvr - 1 ) / 2 ) { nocc = noc ; nvrt = nvr ; ntri = nvr * ( nvr - 1 ) / 2 ; } ;
2006-09-18 00:45:40 +02:00
void resize ( const int noc , const int nvr ) { ( * this ) . NRMat < T > : : resize ( noc * ( noc - 1 ) / 2 , nvr * ( nvr - 1 ) / 2 ) ; nocc = noc ; nvrt = nvr ; ntri = nvr * ( nvr - 1 ) / 2 ; } ;
2006-09-09 21:51:04 +02:00
//we cannot return reference due to the possible sign change
//stored values are for i>j a>b
2006-09-11 17:49:34 +02:00
inline T operator ( ) ( unsigned int i , unsigned int j , unsigned int a , unsigned int b ) const
2006-09-09 21:51:04 +02:00
{
# ifdef DEBUG
2006-09-11 17:56:49 +02:00
if ( i < 1 | | i > nocc | | j < 1 | | j > nocc | | a < 1 | | a > nvrt | | b < 1 | | b > nvrt ) laerror ( " T2ijab_aces fourindex out of range " ) ;
2006-09-09 21:51:04 +02:00
if ( ! NRMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
# endif
int minus = 0 ;
2006-09-16 15:52:42 +02:00
if ( i = = j | | a = = b ) return ( T ) 0 ; //important, needed
2006-09-09 21:51:04 +02:00
if ( i < j ) { minus + + ; unsigned int t = i ; i = j ; j = t ; }
if ( a < b ) { minus + + ; unsigned int t = a ; a = b ; b = t ; }
T val = ( * this ) . NRMat < T > : : operator ( ) ( ( i - 2 ) * ( i - 1 ) / 2 + j - 1 , ( a - 2 ) * ( a - 1 ) / 2 + b - 1 ) ;
return ( minus & 1 ) ? - val : val ;
}
2006-09-17 20:44:40 +02:00
inline void set ( unsigned int i , unsigned int j , unsigned int a , unsigned int b , T elem )
{
# ifdef DEBUG
if ( i < 1 | | i > nocc | | j < 1 | | j > nocc | | a < 1 | | a > nvrt | | b < 1 | | b > nvrt ) laerror ( " T2ijab_aces fourindex out of range " ) ;
if ( ! NRMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
if ( i = = j | | a = = b & & elem ) laerror ( " antisymmetry violation in fourindex_dense<T2ijab_aces> " ) ;
# endif
int minus = 0 ;
if ( i < j ) { minus + + ; unsigned int t = i ; i = j ; j = t ; }
if ( a < b ) { minus + + ; unsigned int t = a ; a = b ; b = t ; }
( * this ) . NRMat < T > : : operator ( ) ( ( i - 2 ) * ( i - 1 ) / 2 + j - 1 , ( a - 2 ) * ( a - 1 ) / 2 + b - 1 ) = minus ? - elem : elem ;
}
2006-09-18 01:58:58 +02:00
inline void add ( unsigned int i , unsigned int j , unsigned int a , unsigned int b , T elem )
{
# ifdef DEBUG
if ( i < 1 | | i > nocc | | j < 1 | | j > nocc | | a < 1 | | a > nvrt | | b < 1 | | b > nvrt ) laerror ( " T2ijab_aces fourindex out of range " ) ;
if ( ! NRMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
if ( i = = j | | a = = b & & elem ) laerror ( " antisymmetry violation in fourindex_dense<T2ijab_aces> " ) ;
# endif
int minus = 0 ;
if ( i < j ) { minus + + ; unsigned int t = i ; i = j ; j = t ; }
if ( a < b ) { minus + + ; unsigned int t = a ; a = b ; b = t ; }
( * this ) . NRMat < T > : : operator ( ) ( ( i - 2 ) * ( i - 1 ) / 2 + j - 1 , ( a - 2 ) * ( a - 1 ) / 2 + b - 1 ) + = minus ? - elem : elem ;
}
2006-09-17 20:44:40 +02:00
2009-11-12 22:01:19 +01:00
void print ( std : : ostream & out ) const
2008-06-02 18:15:55 +02:00
{
unsigned int i , j , a , b ;
2009-11-12 22:01:19 +01:00
for ( i = 1 ; i < = nocc ; + + i ) for ( j = 1 ; j < i ; + + j ) for ( a = 1 ; a < = nvrt ; + + a ) for ( b = 1 ; b < a ; + + b ) out < < i < < " " < < j < < " " < < a < < " " < < b < < " " < < ( * this ) ( i , j , a , b ) < < std : : endl ;
2008-06-02 18:15:55 +02:00
}
2006-09-09 21:51:04 +02:00
} ;
2008-06-17 16:01:57 +02:00
//compact in-core storage of antisymmetrized two-electron integrals
template < class T , class I >
class fourindex_dense < antisymtwoelectronrealdirac , T , I > : public NRSMat < T > {
private :
int nbas ;
public :
fourindex_dense ( ) : NRSMat < T > ( ) { } ;
explicit fourindex_dense ( const int n ) : nbas ( n ) , NRSMat < T > ( n * ( n - 1 ) / 2 ) { } ;
fourindex_dense ( const T & a , const int n ) : nbas ( n ) , NRSMat < T > ( a , n * ( n - 1 ) / 2 ) { } ;
fourindex_dense ( const T * a , const int n ) : nbas ( n ) , NRSMat < T > ( a , n * ( n - 1 ) / 2 ) { } ;
//and also construct it from sparse and externally stored fourindex classes
//it seems not possible to nest template<class I> just for the two constructors
fourindex_dense ( const fourindex < I , T > & rhs ) ;
fourindex_dense ( const fourindex_ext < I , T > & rhs ) ;
void set ( unsigned int i , unsigned int j , unsigned int k , unsigned int l , T elem ) ;
void add ( unsigned int i , unsigned int j , unsigned int k , unsigned int l , T elem ) ;
2008-06-17 16:37:27 +02:00
void add_unique ( unsigned int i , unsigned int j , unsigned int k , unsigned int l , T elem ) ;
2019-11-11 21:12:42 +01:00
const T operator ( ) ( unsigned int i , unsigned int j , unsigned int k , unsigned int l ) const ;
2008-06-17 16:01:57 +02:00
void resize ( const int n ) { nbas = n ; ( * this ) . NRSMat < T > : : resize ( n * ( n - 1 ) / 2 ) ; } ;
2009-11-12 22:01:19 +01:00
void print ( std : : ostream & out ) const
2008-06-17 16:01:57 +02:00
{
unsigned int i , j , k , l ;
for ( i = 1 ; i < = nbas ; + + i )
for ( k = 1 ; k < i ; + + k )
for ( j = 1 ; j < = i ; + + j )
for ( l = 1 ; l < j & & ( j = = i ? l < = k : 1 ) ; + + l )
2009-11-12 22:01:19 +01:00
std : : cout < < i < < " " < < k < < " " < < j < < " " < < l < < " " < < ( * this ) ( i , k , j , l ) < < std : : endl ;
2008-06-17 16:01:57 +02:00
}
} ;
2019-11-11 21:12:42 +01:00
//WARNING: assignment by regular pointer not possible due to the sign tracking - returns const value to prevent it, use set() for assignment
//therefore also operator() cannot be T& but T only - no legal lvalue
2008-06-17 16:01:57 +02:00
template < class T , class DUMMY >
2019-11-11 21:12:42 +01:00
const T fourindex_dense < antisymtwoelectronrealdirac , T , DUMMY > : : operator ( ) ( unsigned int i , unsigned int j , unsigned int k , unsigned int l ) const
2008-06-17 16:01:57 +02:00
{
int I = ASMat_index_1 ( i , j ) ;
int J = ASMat_index_1 ( k , l ) ;
if ( I < 0 | | J < 0 ) return 0. ;
2019-11-11 21:12:42 +01:00
int sign = 1 ;
if ( i < j ) sign = - sign ;
if ( k < l ) sign = - sign ;
2008-06-17 16:01:57 +02:00
# ifdef DEBUG
if ( I > = ( unsigned int ) NRSMat < T > : : nn | | J > = ( unsigned int ) NRSMat < T > : : nn ) laerror ( " index out of range " ) ;
if ( ! NRSMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
# endif
2019-11-11 21:12:42 +01:00
return sign = = 1 ? NRSMat < T > : : v [ SMat_index ( I , J ) ] : - NRSMat < T > : : v [ SMat_index ( I , J ) ] ;
2008-06-17 16:01:57 +02:00
}
template < class T , class DUMMY >
void fourindex_dense < antisymtwoelectronrealdirac , T , DUMMY > : : set ( unsigned int i , unsigned int j , unsigned int k , unsigned int l , T elem )
{
if ( i < j ) elem = - elem ;
if ( k < l ) elem = - elem ;
int I = ASMat_index_1 ( i , j ) ;
int J = ASMat_index_1 ( k , l ) ;
if ( I < 0 | | J < 0 ) laerror ( " assignment to nonexisting element " ) ;
# ifdef DEBUG
if ( I > = NRSMat < T > : : nn | | J > = NRSMat < T > : : nn ) laerror ( " index out of range " ) ;
if ( ! NRSMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
# endif
NRSMat < T > : : v [ SMat_index ( I , J ) ] = elem ;
}
template < class T , class DUMMY >
void fourindex_dense < antisymtwoelectronrealdirac , T , DUMMY > : : add ( unsigned int i , unsigned int j , unsigned int k , unsigned int l , T elem )
{
if ( i < j ) elem = - elem ;
if ( k < l ) elem = - elem ;
int I = ASMat_index_1 ( i , j ) ;
int J = ASMat_index_1 ( k , l ) ;
if ( I < 0 | | J < 0 ) laerror ( " assignment to nonexisting element " ) ;
# ifdef DEBUG
if ( I > = NRSMat < T > : : nn | | J > = NRSMat < T > : : nn ) laerror ( " index out of range " ) ;
if ( ! NRSMat < T > : : v ) laerror ( " access to unallocated fourindex_dense " ) ;
# endif
NRSMat < T > : : v [ SMat_index ( I , J ) ] + = elem ;
}
2008-06-17 16:37:27 +02:00
template < class T , class DUMMY >
void fourindex_dense < antisymtwoelectronrealdirac , T , DUMMY > : : add_unique ( unsigned int i , unsigned int j , unsigned int k , unsigned int l , T elem )
{
if ( i < = j | | k < = l ) return ;
int I = ASMat_index_1 ( i , j ) ;
int J = ASMat_index_1 ( k , l ) ;
if ( I < 0 | | J < 0 | | I < J ) return ;
NRSMat < T > : : v [ SMat_index ( I , J ) ] + = elem ;
}
2008-06-17 16:01:57 +02:00
template < class T , class I >
fourindex_dense < antisymtwoelectronrealdirac , T , I > : : fourindex_dense ( const fourindex < I , T > & rhs ) : nbas ( rhs . size ( ) ) , NRSMat < T > ( ( T ) 0 , rhs . size ( ) * ( rhs . size ( ) - 1 ) / 2 )
{
if ( rhs . getsymmetry ( ) ! = twoelectronrealmullikan ) laerror ( " fourindex_dense symmetry mismatch " ) ;
2008-06-17 16:37:27 +02:00
typename fourindex_ext < I , T > : : piterator p ; //we have to run over equivalents in non-canonical order to build the antisymmetrization properly; it could be done less elegantly but more efficiently moving the if's to outer parts of the piterator loop, if needed
for ( p = const_cast < fourindex_ext < I , T > * > ( & rhs ) - > pbegin ( ) ; p . notend ( ) ; + + p )
{
I i = p - > index . indiv . i ;
I j = p - > index . indiv . j ;
I k = p - > index . indiv . k ;
I l = p - > index . indiv . l ;
add_unique ( i , k , j , l , p - > elem ) ;
add_unique ( i , k , l , j , - p - > elem ) ;
}
2008-06-17 16:01:57 +02:00
}
template < class T , class I >
fourindex_dense < antisymtwoelectronrealdirac , T , I > : : fourindex_dense ( const fourindex_ext < I , T > & rhs ) : nbas ( rhs . size ( ) ) , NRSMat < T > ( ( T ) 0 , rhs . size ( ) * ( rhs . size ( ) - 1 ) / 2 )
{
if ( rhs . getsymmetry ( ) ! = twoelectronrealmullikan ) laerror ( " fourindex_dense symmetry mismatch " ) ;
2008-06-17 16:37:27 +02:00
typename fourindex_ext < I , T > : : piterator p ; //we have to run over equivalents in non-canonical order to build the antisymmetrization properly; it could be done less elegantly but more efficiently moving the if's to outer parts of the piterator loop, if needed
for ( p = const_cast < fourindex_ext < I , T > * > ( & rhs ) - > pbegin ( ) ; p . notend ( ) ; + + p )
2008-06-17 16:01:57 +02:00
{
2008-06-17 16:37:27 +02:00
I i = p - > index . indiv . i ;
I j = p - > index . indiv . j ;
I k = p - > index . indiv . k ;
I l = p - > index . indiv . l ;
add_unique ( i , k , j , l , p - > elem ) ;
add_unique ( i , k , l , j , - p - > elem ) ;
2008-06-17 16:01:57 +02:00
}
}
2009-11-12 22:01:19 +01:00
} //namespace
2008-06-17 16:01:57 +02:00
2019-11-11 21:12:42 +01:00
//TODO:
//implement fourindex_dense for unitary t2 symmetry types
2004-03-17 04:07:21 +01:00
# endif /*_fourindex_included*/