-
Notifications
You must be signed in to change notification settings - Fork 1
/
vector_arith.hpp
159 lines (133 loc) · 3.56 KB
/
vector_arith.hpp
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#pragma once
#include <cassert>
#include <vector>
namespace cu
{
namespace vector_arith
{
namespace detail
{
template <typename View>
struct Expression : View
{
using View::View;
using View::operator[];
using View::size;
};
template <typename T>
struct WrapperView
{
WrapperView( const T & wrapped_ )
: wrapped(wrapped_)
{
}
WrapperView & operator=(WrapperView) = delete;
decltype(auto) operator[]( std::size_t index ) const
{
return wrapped[index];
}
std::size_t size() const
{
return wrapped.size();
}
const T & wrapped;
};
template <typename T>
Expression<WrapperView<T>> makeWrapperView( const T & wrapped )
{
return { wrapped };
}
template <typename T1,
typename T2,
typename F>
struct CombinedView
{
CombinedView( T1 lhs_, T2 rhs_, F f_ )
: lhs(lhs_)
, rhs(rhs_)
, f(std::move(f_))
{
}
decltype(auto) operator[]( std::size_t index ) const
{
return f( lhs[index], rhs[index] );
}
std::size_t size() const
{
return lhs.size();
}
const T1 lhs;
const T2 rhs;
F f;
};
template <typename T1,
typename T2,
typename F>
Expression<CombinedView<T1,T2,F>> makeCombinedView(
T1 lhs, T2 rhs, F f )
{
return { lhs, rhs, f };
}
template <typename View1,
typename View2>
auto operator+( Expression<View1> lhs, Expression<View2> rhs )
{
return detail::makeCombinedView( lhs, rhs,
[]( const auto & lhs, const auto & rhs ) { return lhs+rhs; } );
}
template <typename View,
typename T>
auto operator+( Expression<View> lhs, const std::vector<T> & rhs )
{
return lhs + makeWrapperView( rhs );
}
template <typename T,
typename View>
auto operator+( const std::vector<T> & lhs, const Expression<View> & rhs )
{
return makeWrapperView( lhs ) + rhs;
}
template <typename View1,
typename View2>
auto operator-( const Expression<View1> & lhs, const Expression<View2> & rhs )
{
return detail::makeCombinedView( lhs, rhs,
[]( const auto & lhs, const auto & rhs ) { return lhs-rhs; } );
}
template <typename View,
typename T>
auto operator-( const Expression<View> & lhs, const std::vector<T> & rhs )
{
return lhs - makeWrapperView( rhs );
}
template <typename T,
typename View>
auto operator-( const std::vector<T> & lhs, const Expression<View> & rhs )
{
return makeWrapperView( lhs ) - rhs;
}
} // namespace detail
template <typename T1,
typename T2>
auto operator+( const std::vector<T1> & lhs, const std::vector<T2> & rhs )
{
return detail::makeWrapperView( lhs ) + detail::makeWrapperView( rhs );
}
template <typename T1,
typename T2>
auto operator-( const std::vector<T1> & lhs, const std::vector<T2> & rhs )
{
return detail::makeWrapperView( lhs ) - detail::makeWrapperView( rhs );
}
template <typename T,
typename F>
void assign( std::vector<T> & v, detail::Expression<F> && expr )
{
const auto size = expr.size();
v.clear();
v.reserve(size);
for ( std::size_t i = 0; i < size; ++i )
v.push_back( expr[i] );
}
} // namespace vector_arith
} // namespace cu