/*******************************************************************************
*
* 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
//#include "../../utility/function_arg_ret_type.hpp"
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::arity> map (F f) { return {std::move(f),true}; }
template map_impl map (F f) { return {std::move(f),true}; }
template map_impl map2 (F f) { return {std::move(f),true}; }
// ----------- implementation -------------------------------------
template struct map_impl_result;
template struct map_impl_result {
typedef typename std::result_of::type::value_type)>::type value_type;
typedef typename std::remove_reference::type::domain_type domain_type;
F f;
typename std::add_const::type a; // A is a T or a T& : add const to them.
domain_type domain() const { return a.domain(); }
template value_type operator() (Args && ... args) const { return f(a(std::forward(args)...)); }
friend std::ostream & operator<<(std::ostream & out, map_impl_result const & x){ return out<<"mapping result";}
// rest is only for vector
template
TYPE_ENABLE_IFC(size_t,vec) size() const { return a.size();}
template
TYPE_ENABLE_IFC(value_type,vec) operator[] (Args && args) const { return f(a[std::forward(args)]);}
};
// possible to generalize to N order using tuple techniques ...
template struct map_impl_result {
typedef typename std::result_of::type::value_type, typename remove_cv_ref::type::value_type)>::type value_type;
typedef typename remove_cv_ref::type::domain_type domain_type;
F f;
typename std::add_const::type a;
typename std::add_const::type b;
domain_type domain() const { return a.domain(); }
template value_type operator() (Args && ... args) const { return f(a(std::forward(args)...),b(std::forward(args)...)); }
friend std::ostream & operator<<(std::ostream & out, map_impl_result const & x){ return out<<"mapping result";}
// rest is only for vector
template
TYPE_ENABLE_IFC(size_t,vec) size() const { return a.size();}
template
TYPE_ENABLE_IFC(value_type,vec) operator[] (Args && args) const { return f(a[std::forward(args)],b[std::forward(args)]);}
};
template struct _and;
template struct _and : std::integral_constant::value>{};
template struct _and : T{};
template struct ImmutableCuboidArray> : std::true_type{};
template struct ImmutableArray > : _and::type>::type...>{};
template struct ImmutableMatrix> : _and::type>::type...>{};
template struct ImmutableVector> : _and::type>::type...>{};
//template struct ImmutableArray > : ImmutableArray {};
//template struct ImmutableMatrix> : ImmutableMatrix{};
//template struct ImmutableVector> : ImmutableVector{};
// 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 f_, bool):f(std::move(f_)) {}
map_impl(map_impl const &) = default;
map_impl(map_impl &&) = default;
map_impl & operator = (map_impl const &) = default;
map_impl & operator = (map_impl &&) = default;
template map_impl_result::type...>::value,A...>
operator()(A&&... a) const { return {f,std::forward(a)...}; }
friend std::ostream & operator<<(std::ostream & out, map_impl const & x){ return out<<"map("<<"F"<<")";}
};
}}//namespace triqs::arrays
#endif