/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2012 by M. Ferrero, O. Parcollet
*
* TRIQS 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.
*
* TRIQS 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
* TRIQS. If not, see .
*
******************************************************************************/
#ifndef TRIQS_GF_LOCAL_TAIL_H
#define TRIQS_GF_LOCAL_TAIL_H
#include
#include
#include
#include
namespace triqs { namespace gfs { namespace local {
namespace details {
static constexpr double small = 1.e-10;
}
namespace tqa= triqs::arrays; namespace tql= triqs::clef; namespace mpl= boost::mpl;
typedef std::complex dcomplex;
class tail; // the value class
class tail_view; // the view class
template struct LocalTail : mpl::false_{}; // a boolean trait to identify the objects modelling the concept LocalTail
template<> struct LocalTail : mpl::true_{};
template<> struct LocalTail: mpl::true_{};
template<> struct LocalTail>: mpl::true_{};
// a trait to find the scalar of the algebra i.e. the true scalar and the matrix ...
template struct is_scalar_or_element : mpl::or_< tqa::ImmutableMatrix, utility::is_in_ZRC > {};
// ---------------------- implementation --------------------------------
/// A common implementation class. Idiom : ValueView
template class tail_impl {
public :
typedef void has_view_type_tag; // Idiom : ValueView
typedef tail_view view_type;
typedef tail non_view_type;
typedef arrays::array data_non_view_type;
typedef arrays::array_view data_view_type;
typedef typename mpl::if_c::type data_type;
typedef arrays::array mask_non_view_type;
typedef arrays::array_view mask_view_type;
typedef typename mpl::if_c::type mask_type;
typedef arrays::matrix_view mv_type;
typedef arrays::matrix_view const_mv_type;
//typedef arrays::matrix_view const_mv_type;
data_view_type data() { return _data;}
const data_view_type data() const { return _data;}
mask_view_type mask_view() { return mask;}
const mask_view_type mask_view() const { return mask;}
long order_min() const {return omin;}
long order_max() const {return min_element(mask);}
size_t size() const {return _data.shape()[0];}
long smallest_nonzero() const {
long om = omin;
while ((om < this->order_max()) && (max_element(abs(_data(om-omin,tqa::range(),tqa::range()))) < details::small)) om++;
return om;
}
typedef tqa::mini_vector shape_type;
shape_type shape() const { return shape_type(_data.shape()[1], _data.shape()[2]);}
size_t shape(int i) const { return _data.shape()[i];}
bool is_decreasing_at_infinity() const { return (smallest_nonzero() >=1);}
protected:
long omin;
mask_type mask;
data_type _data;
// All constructors
tail_impl(): omin(0), mask(), _data() {} // all arrays of zero size (empty)
tail_impl(size_t N1, size_t N2, size_t size_, long order_min):
omin(order_min), mask(tqa::make_shape(N1,N2)), _data(tqa::make_shape(size_,N1,N2)) {
mask() = order_min+size_-1;
_data() = 0;
}
tail_impl(data_type const &d, long order_min, mask_type const &om): omin(order_min), mask(om), _data(d) {}
// tail_impl(tail_impl const & x): omin(x.omin), mask(x.mask), _data(x._data){}
tail_impl(tail_impl const & x): omin(x.omin), mask(x.mask), _data(x._data){}
tail_impl(tail_impl const &) = default;
tail_impl(tail_impl &&) = default;
friend class tail_impl;
public:
mv_type operator() (int n) {
if (n>this->order_max()) TRIQS_RUNTIME_ERROR<<" n > Max Order. n= "< Max Order. n= "<
void serialize(Archive & ar, const unsigned int version) {
ar & boost::serialization::make_nvp("omin",omin);
ar & boost::serialization::make_nvp("mask",mask);
ar & boost::serialization::make_nvp("data",_data);
}
friend std::ostream & operator << (std::ostream & out, tail_impl const & x) {
out <<"tail/tail_view: min/smallest/max = "<< x.order_min() << " " << x.smallest_nonzero() << " "<< x.order_max();
for (long u = x.order_min(); u <= x.order_max(); ++u) out <<"\n ... Order "< {
typedef tail_impl B;
friend class tail;
public :
template tail_view(tail_impl const & t): B(t){}
tail_view(B::data_type const &d, long order_min, B::mask_type const &om): B(d, order_min, om){}
tail_view(tail_view const &) = default;
tail_view(tail_view &&) = default;
void rebind( tail_view const &X) {
omin = X.omin;
mask.rebind(X.mask);
_data.rebind(X._data);
}
inline void rebind( tail const &X);
//using B::operator=; // import operator = from impl. class or the default = is synthetized
//tail_view & operator=(const tail_view & rhs) { if (this->data.is_empty()) rebind(rhs); else B::operator=(rhs); return *this; }
// operator = for views
tail_view & operator = (const tail_view & rhs) {
if (this->_data.is_empty()) rebind(rhs);
else {
if (rhs.omin < omin) TRIQS_RUNTIME_ERROR<<"rhs has too small omin";
if ((_data.shape()[1] != rhs._data.shape()[1]) || (_data.shape()[2] != rhs._data.shape()[2]))
TRIQS_RUNTIME_ERROR<<"rhs has different shape";
for (size_t i=0; i const & x) {
if (omin > 0) TRIQS_RUNTIME_ERROR<<"lhs has too large omin";
for (size_t n=0; n {
typedef tail_impl B;
friend class tail_view;
public :
tail():B() {}
typedef tqa::mini_vector shape_type;
tail(size_t N1, size_t N2, size_t size_ = 10, long order_min=-1): B(N1,N2,size_,order_min) {}
tail(shape_type const & sh, size_t size_ = 10, long order_min=-1): B(sh[0],sh[1],size_,order_min) {}
tail(tail const & g): B(g){}
tail(tail_view const & g): B(g){}
tail(tail &&) = default;
// operator = for values
tail & operator = (tail_view const & rhs) {
omin = rhs.omin;
mask = rhs.mask;
_data = rhs._data;
return *this;
}
tail & operator = (tail const & rhs) {
omin = rhs.omin;
mask = rhs.mask;
_data = rhs._data;
return *this;
}
using B::operator();
/// The simplest tail corresponding to : omega
static tail_view omega(size_t N1, size_t N2, size_t size_) {
tail t(N1, N2, size_, -1);
t(-1) = 1;
return t;
}
/// The simplest tail corresponding to : omega, constructed from a shape for convenience
static tail_view omega(tail::shape_type const & sh, size_t size_) { return omega(sh[0],sh[1],size_);}
};
template void assign_from_expression(tail_view & t,RHS const & rhs) { t = rhs( tail::omega(t.shape(),t.size())); }
inline void tail_view::rebind( tail const &X) {
omin = X.omin;
mask.rebind(X.mask);
_data.rebind(X._data);
}
inline tail_view & tail_view::operator = (const tail & rhs) {
if (this->_data.is_empty()) rebind(rhs);
else {
if (rhs.omin < omin) TRIQS_RUNTIME_ERROR<<"rhs has too small omin";
if ((_data.shape()[1] != rhs._data.shape()[1]) || (_data.shape()[2] != rhs._data.shape()[2]))
TRIQS_RUNTIME_ERROR<<"rhs has different shape";
for (size_t i=0; i tail_view slice_target(tail_impl const & t, tqa::range R1, tqa::range R2) {
return tail_view(t.data()(tqa::range(),R1,R2),t.order_min(),t.mask_view()(R1,R2));
}
inline tail inverse(tail_view const & t) {
// find in t
long omin1 = - t.smallest_nonzero();
long omax1 = t.order_max() + 2*omin1;
size_t si = omax1-omin1+1;
tail t_inv(t.shape(), si, omin1);
t_inv(omin1) = inverse(t(-omin1));
for (size_t n=1; n= a.n_min and n-p <=b.n_max and n-p >= b.n_min
// hence p <= min ( a.n_max, n-b.n_min ) and p >= max ( a.n_min, n- b.n_max)
const long pmin = std::max(l.smallest_nonzero(), n - r.order_max() );
const long pmax = std::min(l.order_max(), n - r.smallest_nonzero() );
for (long p = pmin; p <= pmax; ++p) { res(n) += l(p) * r(n-p);}
}
return res;
}
template
TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>)
operator* (T1 const & a, T2 const & b) { return mult_impl(a,b); }
template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>)
operator* (T1 const & a, T2 const & b) {
tail res(b); for (long n=res.order_min(); n<=res.order_max(); ++n) res(n)=a*res(n); return res;
}
template TYPE_ENABLE_IF(tail,mpl::and_, tqa::ImmutableMatrix>)
operator* (T1 const & a, T2 const & b) {
tail res(a); for (long n=res.order_min(); n<=res.order_max(); ++n) res(n)=res(n)*b; return res;
}
inline tail operator * (dcomplex a, tail_view const & r) { tail res(r); res.data()*=a; return res;}
inline tail operator * (tail_view const & r, dcomplex a) { return a*r; }
template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>)
operator/ (T1 const & a, T2 const & b) { return a *inverse(b); }
inline tail operator / (tail_view const & r, dcomplex a) { tail res(r); res.data() /=a; return res;}
inline tail operator / (dcomplex a, tail_view const & r) { return a * inverse(r); }
template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>)
operator + (T1 const & l, T2 const& r) {
using arrays::range;
if (l.shape() != r.shape()) TRIQS_RUNTIME_ERROR<< "tail addition : shape mismatch";
long omin1 = std::min(l.smallest_nonzero(),r.smallest_nonzero());
long omax1 = std::min(l.order_max(),r.order_max());
size_t si = omax1-omin1+1;
tail res(l.shape(), si, omin1);
for (long i = res.order_min(); i<=res.order_max(); ++i) res(i) = l(i) + r(i);
return res;
}
template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>)
operator - (T1 const & l, T2 const& r) {
using arrays::range;
if (l.shape() != r.shape()) TRIQS_RUNTIME_ERROR<< "tail substraction : shape mismatch";
long omin1 = std::min(l.smallest_nonzero(),r.smallest_nonzero());
long omax1 = std::min(l.order_max(),r.order_max());
size_t si = omax1-omin1+1;
tail res(l.shape(), si, omin1);
for (long i = res.order_min(); i<=res.order_max(); ++i) res(i) = l(i) - r(i);
return res;
}
template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>)
operator + (T1 const & a, T2 const & t) {
tail res(t);
res(0) += a;
return res;
}
template TYPE_ENABLE_IF(tail,mpl::and_, is_scalar_or_element>)
operator + (T1 const & t, T2 const & a) { return a+t;}
template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>)
operator - (T1 const & a, T2 const & t) { return (-a) + t;}
template TYPE_ENABLE_IF(tail,mpl::and_, is_scalar_or_element>)
operator - (T1 const & t, T2 const & a) { return (-a) + t;}
}}}
#endif