28 #ifndef REMORA_VECTOR_EXPRESSION_HPP 29 #define REMORA_VECTOR_EXPRESSION_HPP 31 #include "detail/expression_optimizers.hpp" 38 template<
class T,
class VecV,
class Device>
39 typename std::enable_if<
40 std::is_convertible<T, typename VecV::value_type >::value,
41 vector_scalar_multiply<VecV>
43 operator* (vector_expression<VecV, Device>
const& v, T scalar){
44 typedef typename VecV::value_type value_type;
45 return vector_scalar_multiply<VecV>(v(), value_type(scalar));
47 template<
class T,
class VecV,
class Device>
48 typename std::enable_if<
49 std::is_convertible<T, typename VecV::value_type >::value,
50 vector_scalar_multiply<VecV>
52 operator* (T scalar, vector_expression<VecV, Device>
const& v){
53 typedef typename VecV::value_type value_type;
54 return vector_scalar_multiply<VecV>(v(), value_type(scalar));
57 template<
class VecV,
class Device>
58 vector_scalar_multiply<VecV> operator-(vector_expression<VecV, Device>
const& v){
59 typedef typename VecV::value_type value_type;
60 return vector_scalar_multiply<VecV>(v(), value_type(-1));
68 typename std::enable_if<std::is_arithmetic<T>::value, scalar_vector<T, cpu_tag> >::type
69 repeat(T scalar, std::size_t elements){
70 return scalar_vector<T, cpu_tag>(elements,scalar);
74 #define REMORA_UNARY_VECTOR_TRANSFORMATION(name, F)\ 75 template<class VecV, class Device>\ 76 vector_unary<VecV,typename device_traits<Device>:: template F<typename VecV::value_type> >\ 77 name(vector_expression<VecV, Device> const& v){\ 78 typedef typename device_traits<Device>:: template F<typename VecV::value_type> functor_type;\ 79 return vector_unary<VecV, functor_type >(v(), functor_type());\ 99 #undef REMORA_UNARY_VECTOR_TRANSFORMATION 102 template<
class VecV1,
class VecV2,
class Device>
103 vector_addition<VecV1, VecV2 > operator+ (
104 vector_expression<VecV1, Device>
const& v1,
105 vector_expression<VecV2, Device>
const& v2
107 REMORA_SIZE_CHECK(v1().size() == v2().size());
108 return vector_addition<VecV1, VecV2>(v1(),v2());
111 template<
class VecV1,
class VecV2,
class Device>
112 vector_addition<VecV1, vector_scalar_multiply<VecV2> > operator- (
113 vector_expression<VecV1, Device>
const& v1,
114 vector_expression<VecV2, Device>
const& v2
116 REMORA_SIZE_CHECK(v1().size() == v2().size());
117 return vector_addition<VecV1, vector_scalar_multiply<VecV2> >(v1(),-v2());
121 template<
class VecV,
class T,
class Device>
122 typename std::enable_if<
123 std::is_convertible<T, typename VecV::value_type>::value,
124 vector_addition<VecV, scalar_vector<T, Device> >
126 vector_expression<VecV, Device>
const& v,
129 return v + scalar_vector<T, Device>(v().size(),t);
133 template<
class T,
class VecV,
class Device>
134 typename std::enable_if<
135 std::is_convertible<T, typename VecV::value_type>::value,
136 vector_addition<VecV, scalar_vector<T, Device> >
139 vector_expression<VecV, Device>
const& v
141 return v + scalar_vector<T, Device>(v().size(),t);
145 template<
class VecV,
class T,
class Device>
146 typename std::enable_if<
147 std::is_convertible<T, typename VecV::value_type>::value ,
148 vector_addition<VecV, vector_scalar_multiply<scalar_vector<T, Device> > >
150 vector_expression<VecV, Device>
const& v,
153 return v - scalar_vector<T, Device>(v().size(),t);
157 template<
class VecV,
class T,
class Device>
158 typename std::enable_if<
159 std::is_convertible<T, typename VecV::value_type>::value,
160 vector_addition<scalar_vector<T, Device>, vector_scalar_multiply<VecV> >
163 vector_expression<VecV, Device>
const& v
165 return scalar_vector<T, Device>(v().size(),t) - v;
168 #define REMORA_BINARY_VECTOR_EXPRESSION(name, F)\ 169 template<class VecV1, class VecV2, class Device>\ 170 vector_binary<VecV1, VecV2, typename device_traits<Device>:: template F<typename common_value_type<VecV1,VecV2>::type> >\ 171 name(vector_expression<VecV1, Device> const& v1, vector_expression<VecV2, Device> const& v2){\ 172 REMORA_SIZE_CHECK(v1().size() == v2().size());\ 173 typedef typename common_value_type<VecV1,VecV2>::type type;\ 174 typedef typename device_traits<Device>:: template F<type> functor_type;\ 175 return vector_binary<VecV1, VecV2, functor_type >(v1(),v2(), functor_type());\ 184 #undef REMORA_BINARY_VECTOR_EXPRESSION 188 #define REMORA_VECTOR_SCALAR_TRANSFORMATION(name, F)\ 189 template<class T, class VecV, class Device> \ 190 typename std::enable_if< \ 191 std::is_convertible<T, typename VecV::value_type >::value,\ 192 vector_binary<VecV, scalar_vector<typename VecV::value_type, Device>, \ 193 typename device_traits<Device>:: template F<typename VecV::value_type> > \ 195 name (vector_expression<VecV, Device> const& v, T t){ \ 196 typedef typename VecV::value_type type;\ 197 typedef typename device_traits<Device>:: template F<type> functor_type;\ 198 return vector_binary<VecV, scalar_vector<type, Device>, functor_type >(v(), scalar_vector<type, Device>(v().size(),(type)t), functor_type()); \ 210 #undef REMORA_VECTOR_SCALAR_TRANSFORMATION 213 #define REMORA_VECTOR_SCALAR_TRANSFORMATION_2(name, F)\ 214 template<class T, class VecV, class Device> \ 215 typename std::enable_if< \ 216 std::is_convertible<T, typename VecV::value_type >::value,\ 217 vector_binary<scalar_vector<typename VecV::value_type, Device>, VecV, typename device_traits<Device>:: template F<typename VecV::value_type> > \ 219 name (T t, vector_expression<VecV, Device> const& v){ \ 220 typedef typename VecV::value_type type;\ 221 typedef typename device_traits<Device>:: template F<type> functor_type;\ 222 return vector_binary<scalar_vector<T, Device>, VecV, functor_type >(scalar_vector<T, Device>(v().size(),t), v() ,functor_type()); \ 226 #undef REMORA_VECTOR_SCALAR_TRANSFORMATION_2 228 template<
class VecV1,
class VecV2,
class Device>
229 vector_binary<VecV1, VecV2,
230 typename device_traits<Device>:: template safe_divide<typename common_value_type<VecV1,VecV2>::type >
233 vector_expression<VecV1, Device>
const& v1,
234 vector_expression<VecV2, Device>
const& v2,
235 typename common_value_type<VecV1,VecV2>::type defaultValue
237 REMORA_SIZE_CHECK(v1().size() == v2().size());
238 typedef typename common_value_type<VecV1,VecV2>::type result_type;
240 typedef typename device_traits<Device>:: template safe_divide<result_type> functor_type;
241 return vector_binary<VecV1, VecV2, functor_type>(v1(),v2(), functor_type(defaultValue));
247 template<
class VecV,
class Device>
248 typename VecV::value_type
249 sum(vector_expression<VecV, Device>
const& v) {
250 typedef typename VecV::value_type value_type;
251 typedef typename device_traits<Device>:: template add<value_type> functor_type;
252 auto const& elem_result = eval_block(v);
253 value_type result = 0;
254 kernels::vector_fold<functor_type>(elem_result,result);
259 template<
class VecV,
class Device>
260 typename VecV::value_type
261 max(vector_expression<VecV, Device>
const& v) {
262 typedef typename VecV::value_type value_type;
263 typedef typename device_traits<Device>:: template max<value_type> functor_type;
264 auto const& elem_result = eval_block(v);
265 value_type result = std::numeric_limits<value_type>::lowest();
266 kernels::vector_fold<functor_type>(elem_result,result);
271 template<
class VecV,
class Device>
272 typename VecV::value_type
273 min(vector_expression<VecV, Device>
const& v) {
274 typedef typename VecV::value_type value_type;
275 typedef typename device_traits<Device>:: template min<value_type> functor_type;
276 auto const& elem_result = eval_block(v);
277 value_type result = std::numeric_limits<value_type>::max();
278 kernels::vector_fold<functor_type>(elem_result,result);
283 template<
class VecV,
class Device>
284 std::size_t arg_max(vector_expression<VecV, Device>
const& v) {
285 REMORA_SIZE_CHECK(v().size() > 0);
286 auto const& elem_result = eval_block(v);
287 return kernels::vector_max(elem_result);
291 template<
class VecV,
class Device>
292 std::size_t arg_min(vector_expression<VecV, Device>
const& v) {
293 REMORA_SIZE_CHECK(v().size() > 0);
304 template<
class VecV,
class Device>
305 typename VecV::value_type
306 soft_max(vector_expression<VecV, Device>
const& v) {
307 typename VecV::value_type maximum = max(v);
309 return log(sum(exp(v - maximum))) + maximum;
316 template<
class VecV,
class Device>
317 typename real_traits<typename VecV::value_type >::type
318 norm_1(vector_expression<VecV, Device>
const& v) {
319 return sum(abs(eval_block(v)));
323 template<
class VecV,
class Device>
324 typename real_traits<typename VecV::value_type >::type
325 norm_sqr(vector_expression<VecV, Device>
const& v) {
326 return sum(
sqr(eval_block(v)));
330 template<
class VecV,
class Device>
331 typename real_traits<typename VecV::value_type >::type
332 norm_2(vector_expression<VecV, Device>
const& v) {
334 return sqrt(norm_sqr(v));
338 template<
class VecV,
class Device>
339 typename real_traits<typename VecV::value_type >::type
340 norm_inf(vector_expression<VecV, Device>
const& v){
341 return max(abs(eval_block(v)));
345 template<
class VecV,
class Device>
346 std::size_t index_norm_inf(vector_expression<VecV, Device>
const& v){
347 return arg_max(abs(eval_block(v)));
351 template<
class VecV1,
class VecV2,
class Device>
353 typename VecV1::value_type() *
typename VecV2::value_type()
356 vector_expression<VecV1, Device>
const& v1,
357 vector_expression<VecV2, Device>
const& v2
359 REMORA_SIZE_CHECK(v1().size() == v2().size());
361 typename VecV1::value_type() *
typename VecV2::value_type()
363 value_type result = value_type();
364 kernels::dot(eval_block(v1),eval_block(v2),result);
375 template<
class VecV1,
class VecV2,
class Device>
376 vector_concat<VecV1,VecV2> operator|(
377 vector_expression<VecV1, Device>
const& v1,
378 vector_expression<VecV2, Device>
const& v2
380 return vector_concat<VecV1,VecV2>(v1(),v2());
386 template<
class VecV,
class T,
class Device>
387 typename std::enable_if<
388 std::is_convertible<T, typename VecV::value_type>::value,
389 vector_concat<VecV, scalar_vector<T, Device> >
391 vector_expression<VecV, Device>
const& v,
394 return v | scalar_vector<T, Device>(1,t);
400 template<
class T,
class VecV,
class Device>
401 typename std::enable_if<
402 std::is_convertible<T, typename VecV::value_type>::value,
403 vector_concat<scalar_vector<T, Device>,VecV >
406 vector_expression<VecV, Device>
const& v
408 return scalar_vector<T, Device>(1,t) | v;
412 E
const& copy_to_cpu(vector_expression<E, cpu_tag>
const& e){
418 #ifdef REMORA_USE_GPU