liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//---------------------------------------------------------------------------//
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://boostorg.github.com/compute for more information.
//---------------------------------------------------------------------------//
 
#ifndef BOOST_COMPUTE_FUNCTIONAL_DETAIL_UNPACK_HPP
#define BOOST_COMPUTE_FUNCTIONAL_DETAIL_UNPACK_HPP
 
#include <boost/compute/functional/get.hpp>
#include <boost/compute/type_traits/is_vector_type.hpp>
#include <boost/compute/type_traits/result_of.hpp>
#include <boost/compute/type_traits/vector_size.hpp>
#include <boost/compute/detail/meta_kernel.hpp>
 
namespace boost {
namespace compute {
namespace detail {
 
template<class Function, class Arg, size_t Arity>
struct invoked_unpacked
{
    invoked_unpacked(const Function &f, const Arg &arg)
        : m_function(f),
          m_arg(arg)
    {
    }
 
    Function m_function;
    Arg m_arg;
};
 
template<class Function, class Arg, size_t Arity>
inline meta_kernel& operator<<(meta_kernel &k, const invoked_unpacked<Function, Arg, Arity> &expr);
 
template<class Function, class Arg>
inline meta_kernel& operator<<(meta_kernel &k, const invoked_unpacked<Function, Arg, 1> &expr)
{
    return k << expr.m_function(get<0>()(expr.m_arg));
}
 
template<class Function, class Arg>
inline meta_kernel& operator<<(meta_kernel &k, const invoked_unpacked<Function, Arg, 2> &expr)
{
    return k << expr.m_function(get<0>()(expr.m_arg), get<1>()(expr.m_arg));
}
 
template<class Function, class Arg>
inline meta_kernel& operator<<(meta_kernel &k, const invoked_unpacked<Function, Arg, 3> &expr)
{
    return k << expr.m_function(get<0>()(expr.m_arg), get<1>()(expr.m_arg), get<2>()(expr.m_arg));
}
 
template<class Function>
struct unpacked
{
    template<class T, class Enable = void>
    struct aggregate_length
    {
        BOOST_STATIC_CONSTANT(size_t, value = boost::tuples::length<T>::value);
    };
 
    template<class T>
    struct aggregate_length<T, typename enable_if<is_vector_type<T> >::type>
    {
        BOOST_STATIC_CONSTANT(size_t, value = vector_size<T>::value);
    };
 
    template<class TupleArg, size_t TupleSize>
    struct result_impl {};
 
    template<class TupleArg>
    struct result_impl<TupleArg, 1>
    {
        typedef typename detail::get_result_type<0, TupleArg>::type T1;
 
        typedef typename boost::compute::result_of<Function(T1)>::type type;
    };
 
    template<class TupleArg>
    struct result_impl<TupleArg, 2>
    {
        typedef typename detail::get_result_type<0, TupleArg>::type T1;
        typedef typename detail::get_result_type<1, TupleArg>::type T2;
 
        typedef typename boost::compute::result_of<Function(T1, T2)>::type type;
    };
 
    template<class TupleArg>
    struct result_impl<TupleArg, 3>
    {
        typedef typename detail::get_result_type<0, TupleArg>::type T1;
        typedef typename detail::get_result_type<1, TupleArg>::type T2;
        typedef typename detail::get_result_type<2, TupleArg>::type T3;
 
        typedef typename boost::compute::result_of<Function(T1, T2, T3)>::type type;
    };
 
    template<class Signature>
    struct result {};
 
    template<class This, class Arg>
    struct result<This(Arg)>
    {
        typedef typename result_impl<Arg, aggregate_length<Arg>::value>::type type;
    };
 
    unpacked(const Function &f)
        : m_function(f)
    {
    }
 
    template<class Arg>
    detail::invoked_unpacked<
        Function, Arg, aggregate_length<typename Arg::result_type>::value
    >
    operator()(const Arg &arg) const
    {
        return detail::invoked_unpacked<
                   Function,
                   Arg,
                   aggregate_length<typename Arg::result_type>::value
                >(m_function, arg);
    }
 
    Function m_function;
};
 
template<class Function>
inline unpacked<Function> unpack(const Function &f)
{
    return unpacked<Function>(f);
}
 
} // end detail namespace
} // end compute namespace
} // end boost namespace
 
#endif // BOOST_COMPUTE_FUNCTIONAL_DETAIL_UNPACK_HPP