/******************************************************************************* * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * * Copyright (C) 2013 by M. Ferrero, O. Parcollet, I. Krivenko * * 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_CTQMC_KRYLOV_TIME_PT_HPP #define TRIQS_CTQMC_KRYLOV_TIME_PT_HPP #include #include #include #include namespace triqs { namespace utility { /// A point on a very thin grid, as uint64_t struct time_pt { time_pt() { beta = 1; val =0; n = 0;} explicit time_pt(double b) { beta = b; val =0; n = 0;} private : // too dangerous because of rounding to be left public time_pt(double v, double beta_) { beta = beta_; val =v; n = std::floor(Nmax*(v/beta));} time_pt(uint64_t n_, double beta_, bool) { beta = beta_; val = beta*(double(n_)/Nmax); n = n_;} public : // random case : to be improved, using rng only for integer for reproducibility.... template static time_pt random(RNG & rng, T1 l, T2 beta_) { return time_pt(rng(double(l)), double(beta_));} time_pt (time_pt const &) = default; time_pt (time_pt && x) = default; time_pt & operator = (time_pt const &) = default ; #ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS time_pt & operator = (time_pt && x) = default; #else time_pt & operator = (time_pt && x) noexcept { using std::swap; swap(n,x.n); swap(beta, x.beta); swap(val, x.val); return *this;} #endif //this is also dangerous for reproducibility time_pt & operator = (double v) = delete; // factories static time_pt make_beta(double beta_) { time_pt r; r.beta = beta_; r.n = Nmax; r.val = beta_; return r;} static time_pt make_zero(double beta_) { time_pt r; r.beta = beta_; r.n = 0; r.val = 0; return r;} static time_pt make_from_double(double x, double beta_) { return time_pt(x,beta_);} static time_pt epsilon(double beta) { return time_pt(1,beta,true);} static time_pt epsilon(time_pt const & beta) { return time_pt(1,beta.beta,true);} bool operator == (const time_pt & tp) const { return n == tp.n; } bool operator != (const time_pt & tp) const { return n != tp.n; } bool operator < (const time_pt & tp) const { return n < tp.n; } bool operator <= (const time_pt & tp) const { return n <= tp.n; } bool operator > (const time_pt & tp) const { return n > tp.n; } bool operator >= (const time_pt & tp) const { return n >= tp.n; } // adding and substracting is cyclic on [0, beta] inline friend time_pt operator+(time_pt const & a, time_pt const & b) { return time_pt(a.n + b.n, a.beta, true); } inline friend time_pt operator-(time_pt const & a, time_pt const & b) { uint64_t n = (a.n>= b.n ? a.n - b.n : Nmax - (b.n - a.n)); return time_pt(n, a.beta,true); } //unary inline friend time_pt operator-(time_pt const & a) { uint64_t n = Nmax - a.n; return time_pt(n, a.beta,true); } // division by integer inline friend time_pt div_by_int(time_pt const & a, size_t b) { return time_pt(a.n/ b, a.beta, true); } // floor_div(x,y) = floor (x/y), but computed on the grid. inline friend size_t floor_div(time_pt const & a, time_pt const & b){return a.n/b.n;} // only EXPLICIT cast explicit operator double() const {return val;} // cast to a double friend std::ostream & operator<< (std::ostream & out, time_pt const & p) { return out << p.val << " [time_pt : beta = "<< p.beta<< " n = "<< p.n<<"]" ; } private: static constexpr uint64_t Nmax = std::numeric_limits::max(); uint64_t n; double val, beta; }; // all operations below decay to double inline double operator*(time_pt const & a, time_pt const & b) { return double(a)*double(b); } inline double operator/(time_pt const & a, time_pt const & b) { return double(a)/double(b); } #define IMPL_OP(OP) \ inline double operator OP(time_pt const & x, double y) {return static_cast(x) OP y;} \ inline double operator OP(double y, time_pt const & x) {return y OP static_cast(x);} IMPL_OP(+); IMPL_OP(-); IMPL_OP(*); IMPL_OP(/); #undef IMPL_OP // all other operations : first cast into a double and do the operation /*#define IMPL_OP(OP) \ template auto operator OP(time_pt const & x, T y) -> decltype(double(0) OP y) {return static_cast(x) OP y;} \ template auto operator OP(T y, time_pt const & x) -> decltype(y OP double(0)) {return y OP static_cast(x);} \ IMPL_OP(+); IMPL_OP(-); IMPL_OP(*); IMPL_OP(/); #undef IMPL_OP*/ }} #endif