/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011 by 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_ARRAYS_EXPRESSION_MAP_H
#define TRIQS_ARRAYS_EXPRESSION_MAP_H
#include "../impl/common.hpp"
#include
namespace triqs { namespace arrays {
template class map_impl;
/**
* Given a function f : arg_type -> result_type, map(f) is the function promoted to arrays
* map(f) : array --> array
*/
template map_impl map (F const & f) { return map_impl(f,true); }
template map_impl map2 (F const & f) { return map_impl(f,true); }
// ----------- implementation -------------------------------------
// NB The bool is to make constructor not ambiguous
// clang on os X with lib++ has a pb otherwise (not clear what the pb is)
template class map_impl {
F f;
public :
// map_impl(F const & f_):f(f_) {}
map_impl(F const & f_, bool):f(f_) {}
map_impl(F && f_, bool):f(f_) {}
map_impl(map_impl const &) = default;
//map_impl(map_impl &&) = default;
template class m_result;
template class m_result >::type> : TRIQS_MODEL_CONCEPT(ImmutableCuboidArray) {
public:
typedef typename std::result_of::type value_type;
typedef typename A::domain_type domain_type;
A const & a; F f;
m_result(F const & f_, A const & a_):a(a_),f(f_) {}
domain_type domain() const { return a.domain(); }
template value_type operator() (Args const & ... args) const { return f(a(args...)); }
//value_type operator[] ( typename domain_type::index_value_type const & key) const { return f(a[key]); }
friend std::ostream & operator<<(std::ostream & out, m_result const & x){ return out<<"lazy matrix resulting of a mapping";}
};
template class m_result >::type> : TRIQS_MODEL_CONCEPT(ImmutableMatrix) {
public:
typedef typename std::result_of::type value_type;
typedef typename A::domain_type domain_type;
A const & a; F f;
m_result(F const & f_, A const & a_):a(a_),f(f_) {}
domain_type domain() const { return a.domain(); }
size_t dim0() const { return a.dim0();}
size_t dim1() const { return a.dim1();}
template value_type operator() (Args const & ... args) const { return f(a(args...)); }
//value_type operator[] ( typename domain_type::index_value_type const & key) const { return f(a[key]); }
friend std::ostream & operator<<(std::ostream & out, m_result const & x){ return out<<"lazy matrix resulting of a mapping";}
};
template class m_result >::type> : TRIQS_MODEL_CONCEPT(ImmutableVector) {
public:
typedef typename std::result_of::type value_type;
typedef typename A::domain_type domain_type;
A const & a; F f;
m_result(F const & f_, A const & a_):a(a_),f(f_) {}
domain_type domain() const { return a.domain(); }
size_t size() const { return a.size();}
template value_type operator() (Args const & ... args) const { return f(a(args...)); }
//value_type operator[] ( typename domain_type::index_value_type const & key) const { return f(a[key]); }
value_type operator() ( size_t i) const { return f(a(i)); }
friend std::ostream & operator<<(std::ostream & out, m_result const & x){ return out<<"lazy matrix resulting of a mapping";}
};
template struct result;
template struct result { typedef m_result type;};
template< class A > m_result operator()(A const & a) const {
//static_assert( (ImmutableArray::value), "map : A does not model ImmutableArray");
return m_result(f,a);
}
friend std::ostream & operator<<(std::ostream & out, map_impl const & x){ return out<<"map("<<"F"<<")";}
};
// ----------- // TO DO : make this with preprocessor ....
template class map_impl {
F f;
public :
map_impl(F const & f_, bool):f(f_) {}
map_impl(F && f_, bool):f(f_) {}
map_impl(map_impl const &) = default;
//map_impl(map_impl &&) = default;
template class m_result : TRIQS_MODEL_CONCEPT(ImmutableArray) {
static_assert( (std::is_same::value), "type mismatch");
public:
typedef typename std::result_of::type value_type;
typedef typename A::domain_type domain_type;
A const & a; B const & b; F f;
m_result(F const & f_, A const & a_, B const & b_):a(a_),b(b_),f(f_) {
if (a.domain() != b.domain()) TRIQS_RUNTIME_ERROR<<"map2 : domain mismatch";
}
domain_type domain() const { return a.domain(); }
template value_type operator() (Args const & ... args) const { return f(a(args...),b(args...)); }
//value_type operator[] ( typename domain_type::index_value_type const & key) const { return f(a[key],b[key]); }
friend std::ostream & operator<<(std::ostream & out, m_result const & x){ return out<<"lazy matrix resulting of a mapping";}
};
template struct result;
template struct result { typedef m_result type;};
template< class A, class B > m_result operator()(A const & a, B const & b) {
static_assert( (ImmutableArray::value), "map1 : A does not model ImmutableArray");
static_assert( (ImmutableArray::value), "map1 : B does not model ImmutableArray");
return m_result(f,a,b);
}
friend std::ostream & operator<<(std::ostream & out, map_impl const & x){ return out<<"map("<<"F"<<")";}
};
}}//namespace triqs::arrays
#endif