]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - TEvtGen/EvtGen/EvtGenBase/EvtSpinAmp.cpp
Converting TEvtGen to native cmake
[u/mrichter/AliRoot.git] / TEvtGen / EvtGen / EvtGenBase / EvtSpinAmp.cpp
diff --git a/TEvtGen/EvtGen/EvtGenBase/EvtSpinAmp.cpp b/TEvtGen/EvtGen/EvtGenBase/EvtSpinAmp.cpp
new file mode 100644 (file)
index 0000000..7ffaa79
--- /dev/null
@@ -0,0 +1,498 @@
+#include "EvtGenBase/EvtPatches.hh"
+#include "EvtGenBase/EvtReport.hh"
+#include "EvtGenBase/EvtSpinAmp.hh"
+#include <stdlib.h>
+
+using std::endl;
+
+std::ostream&
+operator<<( std::ostream& os, const EvtSpinAmp& amp )
+{
+    vector<int> index = amp.iterinit();
+    
+    os << ":";
+    do {
+        os<<"<";
+        for(size_t i=0; i<index.size()-1; ++i) {
+            os<<index[i];
+        }
+        os<<index[index.size()-1]<<">"<<amp(index)<<":";
+    } while( amp.iterate( index ) );
+
+    return os;
+}
+
+EvtSpinAmp operator*( const EvtComplex& real, const EvtSpinAmp& cont )
+{
+    EvtSpinAmp ret( cont );
+
+    for( size_t i=0; i<ret._elem.size(); ++i ) {
+        ret._elem[i] *= real;
+    }
+
+    return ret;
+}
+
+EvtSpinAmp operator*( const EvtSpinAmp& cont, const EvtComplex& real )
+{
+    return real*cont;
+}
+
+EvtSpinAmp operator/( const EvtSpinAmp& cont, const EvtComplex& real )
+{
+    EvtSpinAmp ret( cont );
+
+    for( size_t i=0; i<ret._elem.size(); ++i ) {
+        ret._elem[i] /= real;
+    }
+
+    return ret;
+}
+
+vector<unsigned int> EvtSpinAmp::calctwospin( const vector<EvtSpinType::spintype>& type  ) const
+{
+    vector<unsigned int> twospin;
+
+    for( size_t i=0; i<type.size(); ++i ) {
+        twospin.push_back( EvtSpinType::getSpin2( type[i] ) );
+    } 
+
+    return twospin;
+}
+
+EvtSpinAmp::EvtSpinAmp( const vector<EvtSpinType::spintype>& type )
+{
+    int num = 1;
+    _type = type;
+    _twospin=calctwospin( type );
+    
+    for( size_t i=0; i<_twospin.size(); ++i )
+        num*=_twospin[i]+1;
+
+    _elem=vector<EvtComplex>( num );
+}
+
+EvtSpinAmp::EvtSpinAmp( const vector<EvtSpinType::spintype>& type, const EvtComplex & val )
+{
+    int num = 1;
+    _type = type;
+    _twospin=calctwospin( type );
+
+    for( size_t i=0; i<_twospin.size(); ++i )
+        num*=_twospin[i]+1;
+
+    _elem=vector<EvtComplex>( num, val );
+}
+
+EvtSpinAmp::EvtSpinAmp( const vector<EvtSpinType::spintype>& type, 
+        const vector<EvtComplex>& elem )
+{  
+    size_t num = 1;
+
+    _type = type;
+    _twospin=calctwospin( type );
+    _elem=elem;
+    
+    for( size_t i=0; i<_twospin.size(); ++i ){
+        num*=(_twospin[i]+1);
+    }
+
+    if(_elem.size() != num ) {
+        report(ERROR,"EvtGen")<<"Wrong number of elements input:"
+            <<_elem.size()<<" vs. "<<num<<endl;
+       ::abort(); 
+    }
+
+}
+
+EvtSpinAmp::EvtSpinAmp( const EvtSpinAmp& copy )
+{
+    _twospin = copy._twospin;
+    _elem = copy._elem;
+    _type = copy._type;
+}
+
+void EvtSpinAmp::checktwospin( const vector<unsigned int>& twospin ) const
+{
+    if( _twospin == twospin )
+        return;
+
+    report( ERROR, "EvtGen" )
+        <<"Dimension or order of tensors being operated on does not match"
+        <<endl;
+    ::abort();
+}
+
+void EvtSpinAmp::checkindexargs( const vector<int>& index ) const
+{
+    if( index.size()==0 ) {
+        report(ERROR,"EvtGen") << "EvtSpinAmp can't handle no indices" << endl;
+        ::abort();
+    }
+
+    if( index.size() != _twospin.size() ) {
+        report( ERROR, "EvtGen" ) << "Rank of EvtSpinAmp index does not match: " 
+            <<_twospin.size()<<" expected "<<index.size()<<" input."<<endl;
+        ::abort();
+    }
+
+    for( size_t i=0; i<_twospin.size(); ++i ) {
+        if( static_cast<int>(_twospin[i])>=abs(index[i]) && static_cast<int>(_twospin[i])%2==index[i]%2 )
+            continue; 
+        report(ERROR,"EvtGen")<<"EvtSpinAmp index out of range" << endl;
+        report(ERROR,"EvtGen")<<" Index: ";
+        for(size_t j=0; j<_twospin.size(); ++j )
+            report(ERROR," ")<<_twospin[j];
+
+        report(ERROR, " ")<<endl<<" Index: ";
+        for(size_t j=0; j<index.size(); ++j )
+            report(ERROR," ")<<index[j];
+        report(ERROR, " ")<<endl;
+        ::abort();
+    }
+}
+
+int EvtSpinAmp::findtrueindex( const vector<int>& index ) const
+{
+    int trueindex = 0;
+
+    for( size_t i = index.size()-1; i>0; --i ) {
+        trueindex += (index[i]+_twospin[i])/2;
+        trueindex *= _twospin[i-1]+1;
+    }
+    
+    trueindex += (index[0]+_twospin[0])/2;
+
+    return trueindex;
+}
+
+EvtComplex & EvtSpinAmp::operator()( const vector<int>& index )
+{
+    checkindexargs( index );
+    
+    size_t trueindex = findtrueindex(index);
+    if(trueindex >= _elem.size()) {
+        report(ERROR,"EvtGen")<<"indexing error "<<trueindex<<" "<<_elem.size()<<endl;
+        for(size_t i=0; i<_twospin.size(); ++i) {
+            report(ERROR,"")<<_twospin[i]<<" ";
+        }
+        report(ERROR,"")<<endl;
+
+        for(size_t i=0; i<index.size(); ++i) {
+            report(ERROR,"")<<index[i]<<" ";
+        }
+        report(ERROR,"")<<endl;
+
+        ::abort();
+    }
+
+    return _elem[trueindex];
+}
+
+const EvtComplex & EvtSpinAmp::operator()( const vector<int>& index ) const
+{
+    checkindexargs( index );
+    
+    size_t trueindex = findtrueindex(index);
+    if(trueindex >= _elem.size()) {
+        report(ERROR,"EvtGen")<<"indexing error "<<trueindex<<" "<<_elem.size()<<endl;
+        for(size_t i=0; i<_twospin.size(); ++i) {
+            report(ERROR,"")<<_twospin[i]<<" ";
+        }
+        report(ERROR,"")<<endl;
+
+        for(size_t i=0; i<index.size(); ++i) {
+            report(ERROR,"")<<index[i]<<" ";
+        }
+        report(ERROR,"")<<endl;
+
+        ::abort();
+    }
+    
+    return _elem[trueindex];
+}
+
+EvtComplex & EvtSpinAmp::operator()( int i, ... )
+{
+    va_list ap;
+    vector<int> index( _twospin.size() );
+    
+    va_start(ap, i);
+    
+    index[0]=i;
+    for(size_t n=1; n<_twospin.size(); ++n )
+        index[n]=va_arg( ap, int );
+
+    va_end(ap);
+
+    return (*this)( index );
+}
+
+const EvtComplex & EvtSpinAmp::operator()( int i, ... ) const
+{
+    vector<int> index( _twospin.size() );
+    va_list ap;
+
+    va_start(ap, i);
+
+    index[0]=i;
+    for(size_t n=1; n<_twospin.size(); ++n )
+        index[n]=va_arg( ap, int );
+
+    va_end(ap);
+
+    return (*this)( index );
+}
+
+EvtSpinAmp& EvtSpinAmp::operator=( const EvtSpinAmp& cont ) 
+{
+    _twospin=cont._twospin;
+    _elem=cont._elem;
+    _type=cont._type;
+
+    return *this;
+}
+
+EvtSpinAmp EvtSpinAmp::operator+( const EvtSpinAmp & cont ) const
+{
+    checktwospin( cont._twospin );
+
+    EvtSpinAmp ret( cont );
+    for( size_t i=0; i<ret._elem.size(); ++i ) {
+        ret._elem[i]+=_elem[i];
+    }
+
+    return ret;
+}
+
+EvtSpinAmp& EvtSpinAmp::operator+=( const EvtSpinAmp&
+        cont ) 
+{
+    checktwospin( cont._twospin );
+
+    for( size_t i=0; i<_elem.size(); ++i )
+        _elem[i]+=cont._elem[i];
+
+    return *this;
+}
+
+EvtSpinAmp EvtSpinAmp::operator-( const EvtSpinAmp & cont ) const 
+{
+    checktwospin( cont._twospin );
+
+    EvtSpinAmp ret( *this );
+    for( size_t i=0; i<ret._elem.size(); ++i )
+        ret._elem[i]-=cont._elem[i];
+
+    return ret;
+}
+
+EvtSpinAmp& EvtSpinAmp::operator-=( const EvtSpinAmp& cont )
+{
+    checktwospin( cont._twospin );
+
+    for( size_t i=0; i<_elem.size(); ++i )
+        _elem[i]-=cont._elem[i];
+
+    return *this;
+}
+
+// amp = amp1 * amp2
+EvtSpinAmp EvtSpinAmp::operator*( const EvtSpinAmp & amp2 ) const
+{
+    vector<int> index(rank()+amp2.rank());
+    vector<int> index1(rank()), index2(amp2.rank()); 
+    EvtSpinAmp amp;
+    
+    amp._twospin=_twospin;
+    amp._type=_type;
+
+    for( size_t i=0; i<amp2._twospin.size(); ++i ) {
+        amp._twospin.push_back( amp2._twospin[i] );
+        amp._type.push_back( amp2._type[i] );
+    }
+    
+    amp._elem = vector<EvtComplex>( _elem.size() * amp2._elem.size() );
+
+    for( size_t i=0; i<index1.size(); ++i )
+        index[i]=index1[i]=-_twospin[i];
+    
+    for( size_t i=0; i<index2.size(); ++i )
+        index[i+rank()]=index2[i]=-amp2._twospin[i];
+
+    while(true) {
+        amp( index ) = (*this)( index1 )*amp2( index2 );
+        if(!amp.iterate( index )) break;
+        
+        for( size_t i=0; i<index1.size(); ++i )
+            index1[i]=index[i];
+
+        for( size_t i=0; i<index2.size(); ++i )
+            index2[i]=index[i+rank()];
+    }
+    
+    return amp;
+}
+
+EvtSpinAmp& EvtSpinAmp::operator*=( const EvtSpinAmp& cont ) 
+{
+    EvtSpinAmp ret = (*this)*cont;
+    *this=ret;
+    return *this;
+}
+
+EvtSpinAmp& EvtSpinAmp::operator*=( const EvtComplex& real )
+{
+    for( size_t i=0; i<_elem.size(); ++i )
+        _elem[i] *= real;
+
+    return *this;
+}
+
+EvtSpinAmp& EvtSpinAmp::operator/=( const EvtComplex& real )
+{
+    for( size_t i=0; i<_elem.size(); ++i )
+        _elem[i] /= real;
+    
+    return *this;
+}
+
+vector<int> EvtSpinAmp::iterinit() const
+{
+    vector<int> init( _twospin.size() );
+
+    for( size_t i=0; i<_twospin.size(); ++i )
+        init[i]=-_twospin[i];
+
+    return init;
+}
+
+bool EvtSpinAmp::iterate( vector<int>& index ) const
+{
+    int last = _twospin.size() - 1;
+
+    index[0]+=2;
+    for( size_t j=0; static_cast<int>(j)<last; ++j ) {
+        if( index[j] > static_cast<int>(_twospin[j]) ) {
+            index[j] = -_twospin[j];
+            index[j+1]+=2;
+        }
+    }
+
+    return (abs(index[last]))<=((int)_twospin[last]);
+}
+
+// Test whether a particular index is an allowed one (specifically to deal with
+// photons and possibly neutrinos)
+bool EvtSpinAmp::allowed( const vector<int>& index ) const
+{
+    if( index.size() != _type.size() ) {
+        report(ERROR,"EvtGen")
+            <<"Wrong dimensino index input to allowed."<<endl;
+        ::abort();
+    }
+    
+    for(size_t i=0; i<index.size(); ++i) {
+        switch(_type[i]) {
+            case EvtSpinType::PHOTON: 
+                if(abs(index[i])!=2) return false;
+                break;
+            case EvtSpinType::NEUTRINO:
+                report(ERROR,"EvtGen")
+                    <<"EvMultibody currently cannot handle neutrinos."<<endl;
+                ::abort();
+           default:
+             break;
+        }
+    }
+    
+    return true;
+}
+
+bool EvtSpinAmp::iterateallowed( vector<int>& index ) const
+{
+    while(true) {
+        if(!iterate( index ))
+            return false;
+        if(allowed( index )) 
+            return true;
+    }
+}
+
+vector<int> EvtSpinAmp::iterallowedinit() const
+{
+    vector<int> init = iterinit();
+    while(!allowed(init)) {
+        iterate(init);
+    }
+
+    return init;
+}
+
+void EvtSpinAmp::intcont( size_t a, size_t b )
+{
+  
+    if(rank()<=2) {
+      report(ERROR,"EvtGen")<<"EvtSpinAmp can't handle no indices" << endl;
+      ::abort();
+    }
+
+    size_t newrank=rank()-2;
+
+    if(_twospin[a]!=_twospin[b]) {
+        report(ERROR,"EvtGen")
+            <<"Contaction called on indices of different dimension" 
+            <<endl;
+        report(ERROR,"EvtGen")
+            <<"Called on "<<_twospin[a]<<" and "<<_twospin[b]
+            <<endl;
+        ::abort();
+    }
+
+    vector<int> newtwospin( newrank );
+    vector<EvtSpinType::spintype> newtype( newrank );
+
+    for( size_t i=0, j=0; i<_twospin.size(); ++i ){
+        if(i==a || i==b) continue;
+
+        newtwospin[j] = _twospin[i];
+        newtype[j] = _type[i];
+        ++j;
+    }
+
+    EvtSpinAmp newamp( newtype );
+    vector<int> index( rank() ), newindex = newamp.iterinit();
+
+    for( size_t i=0; i<newrank; ++i )
+        newindex[i] = -newtwospin[i];
+
+    while(true) {
+        
+        for( size_t i=0, j=0; i<rank(); ++i ) {
+            if(i==a || i==b) continue;
+            index[i]=newindex[j];
+            ++j;
+        }
+        
+        index[b]=index[a]=-_twospin[a];
+        newamp(newindex) = (*this)(index);
+        for( size_t i=-_twospin[a]+2; i<=_twospin[a]; i+=2 ) {
+            index[b]=index[a]=i;
+            newamp(newindex) += (*this)(index);
+        }
+       
+        if(!newamp.iterate(newindex)) break;
+    }
+    
+    *this=newamp;
+}
+
+// In A.extcont(B), a is the index in A and b is the index in B - note that this
+// routine can be extremely improved!
+void EvtSpinAmp::extcont( const EvtSpinAmp& cont, int a, int b )
+{
+    EvtSpinAmp ret = (*this)*cont;
+    ret.intcont( a, rank()+b );
+
+    *this=ret;
+}