33 #ifndef REMORA_ASSIGNMENT_HPP 34 #define REMORA_ASSIGNMENT_HPP 38 #include "detail/traits.hpp" 40 #include <type_traits> 52 template<
class E,
class Device>
53 typename std::conditional<
56 typename E::evaluation_category
58 typename vector_temporary<E>::type,
61 eval_block(vector_expression<E, Device>
const& e){
69 template<
class E,
class Device>
70 typename std::conditional<
73 typename E::evaluation_category
75 typename matrix_temporary<E>::type,
78 eval_block(matrix_expression<E, Device>
const& e){
88 template<
class E,
class Device>
89 typename std::conditional<
92 typename E::storage_type
94 typename vector_temporary<E>::type,
97 eval_expression(vector_expression<E, Device>
const& e){
105 template<
class E,
class Device>
106 typename std::conditional<
109 typename E::storage_type
111 typename matrix_temporary<E>::type,
114 eval_expression(matrix_expression<E, Device>
const& e){
123 template<
class VecX,
class VecV,
class Device>
124 void assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v,elementwise_tag){
125 kernels::assign(x,v);
127 template<
class VecX,
class VecV,
class Device>
129 vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v,
130 elementwise_tag,
typename VecX::value_type alpha
132 typename device_traits<Device>:: template multiply_assign<typename common_value_type<VecX,VecV>::type> f(alpha);
133 kernels::assign(x, v,f);
135 template<
class VecX,
class VecV,
class Device>
137 vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v,
138 blockwise_tag,
typename VecX::value_type alpha = 1
140 v().assign_to(x,alpha);
142 template<
class VecX,
class VecV,
class Device>
143 void plus_assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v,elementwise_tag){
144 kernels::assign<typename device_traits<Device>:: template add<typename common_value_type<VecX,VecV>::type> > (x, v);
146 template<
class VecX,
class VecV,
class Device>
148 vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v,
149 elementwise_tag,
typename VecX::value_type alpha
151 typename device_traits<Device>:: template multiply_and_add<typename common_value_type<VecX,VecV>::type> f(alpha);
152 kernels::assign(x, v,f);
154 template<
class VecX,
class VecV,
class Device>
156 vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v,
157 blockwise_tag,
typename VecX::value_type alpha = 1
159 v().plus_assign_to(x,alpha);
168 template<
class VecX,
class VecV,
class Device>
169 VecX& assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
170 REMORA_SIZE_CHECK(x().size() == v().size());
171 detail::assign(x,v,
typename VecV::evaluation_category());
179 template<
class VecX,
class VecV,
class Device>
180 VecX& assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v,
typename VecX::value_type alpha){
181 REMORA_SIZE_CHECK(x().size() == v().size());
182 detail::assign(x,v,
typename VecV::evaluation_category(),alpha);
190 template<
class VecX,
class VecV,
class Device>
191 VecX& plus_assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
192 REMORA_SIZE_CHECK(x().size() == v().size());
193 detail::plus_assign(x,v,
typename VecV::evaluation_category());
201 template<
class VecX,
class VecV,
class Device>
202 VecX& plus_assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v,
typename VecX::value_type alpha){
203 REMORA_SIZE_CHECK(x().size() == v().size());
204 detail::plus_assign(x,v,
typename VecV::evaluation_category(),alpha);
212 template<
class VecX,
class VecV,
class Device>
213 VecX& multiply_assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
214 REMORA_SIZE_CHECK(x().size() == v().size());
215 auto&& veval = eval_block(v);
216 kernels::assign<typename device_traits<Device>:: template multiply<typename common_value_type<VecX,VecV>::type>> (x, veval);
224 template<
class VecX,
class VecV,
class Device>
225 VecX& divide_assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
226 REMORA_SIZE_CHECK(x().size() == v().size());
227 auto&& veval = eval_block(v);
228 kernels::assign<typename device_traits<Device>:: template divide<typename common_value_type<VecX,VecV>::type>> (x, veval);
237 template<
class MatA,
class MatB,
class Device>
238 void assign(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B,elementwise_tag){
239 kernels::assign(A,B);
241 template<
class MatA,
class MatB,
class Device>
243 matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B,
244 elementwise_tag,
typename MatA::value_type alpha
246 typename device_traits<Device>:: template multiply_assign<typename common_value_type<MatA,MatB>::type> f(alpha);
247 kernels::assign(A,B,f);
249 template<
class MatA,
class MatB,
class Device>
251 matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B,
252 blockwise_tag,
typename MatA::value_type alpha = 1
254 B().assign_to(A,alpha);
256 template<
class MatA,
class MatB,
class Device>
257 void plus_assign(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B,elementwise_tag){
258 kernels::assign<typename device_traits<Device>:: template add<typename common_value_type<MatA,MatB>::type> > (A, B);
260 template<
class MatA,
class MatB,
class Device>
262 matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B,
263 elementwise_tag,
typename MatA::value_type alpha
265 typename device_traits<Device>:: template multiply_and_add<typename common_value_type<MatA,MatB>::type> f(alpha);
266 kernels::assign(A,B,f);
268 template<
class MatA,
class MatB,
class Device>
270 matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B,
271 blockwise_tag,
typename MatA::value_type alpha = 1
273 B().plus_assign_to(A,alpha);
282 template<
class MatA,
class MatB,
class Device>
283 MatA& assign(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
284 REMORA_SIZE_CHECK(A().size1() == B().size1());
285 REMORA_SIZE_CHECK(A().size2() == B().size2());
286 detail::assign(A,B,
typename MatB::evaluation_category());
294 template<
class MatA,
class MatB,
class Device>
295 MatA& assign(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B,
typename MatA::value_type alpha){
296 REMORA_SIZE_CHECK(A().size1() == B().size1());
297 REMORA_SIZE_CHECK(A().size2() == B().size2());
298 detail::assign(A,B,
typename MatB::evaluation_category(),alpha);
306 template<
class MatA,
class MatB,
class Device>
307 MatA& plus_assign(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
308 REMORA_SIZE_CHECK(A().size1() == B().size1());
309 REMORA_SIZE_CHECK(A().size2() == B().size2());
310 detail::plus_assign(A,B,
typename MatB::evaluation_category());
318 template<
class MatA,
class MatB,
class Device>
319 MatA& plus_assign(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B,
typename MatA::value_type alpha){
320 REMORA_SIZE_CHECK(A().size1() == B().size1());
321 REMORA_SIZE_CHECK(A().size2() == B().size2());
322 detail::plus_assign(A,B,
typename MatB::evaluation_category(),alpha);
330 template<
class MatA,
class MatB,
class Device>
331 MatA& multiply_assign(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
332 REMORA_SIZE_CHECK(A().size1() == B().size1());
333 REMORA_SIZE_CHECK(A().size2() == B().size2());
334 auto&& Beval = eval_block(B);
335 kernels::assign<typename device_traits<Device>:: template multiply<typename common_value_type<MatA,MatB>::type> > (A, Beval);
343 template<
class MatA,
class MatB,
class Device>
344 MatA& divide_assign(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
345 REMORA_SIZE_CHECK(A().size1() == B().size1());
346 REMORA_SIZE_CHECK(A().size2() == B().size2());
347 auto&& Beval = eval_block(B);
348 kernels::assign<typename device_traits<Device>:: template divide<typename common_value_type<MatA,MatB>::type> > (A, Beval);
362 template<
class VecX,
class VecV,
class Device>
363 VecX& operator+=(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
364 REMORA_SIZE_CHECK(x().size() == v().size());
365 typename vector_temporary<VecX>::type temporary(v);
366 return plus_assign(x,temporary);
375 template<
class VecX,
class VecV,
class Device>
376 VecX& operator-=(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
377 REMORA_SIZE_CHECK(x().size() == v().size());
378 typename vector_temporary<VecX>::type temporary(v);
379 return plus_assign(x,temporary,
typename VecX::value_type(-1.0));
388 template<
class VecX,
class VecV,
class Device>
389 VecX& operator*=(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
390 REMORA_SIZE_CHECK(x().size() == v().size());
391 typename vector_temporary<VecX>::type temporary(v);
392 return multiply_assign(x,temporary);
401 template<
class VecX,
class VecV,
class Device>
402 VecX& operator/=(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
403 REMORA_SIZE_CHECK(x().size() == v().size());
404 typename vector_temporary<VecX>::type temporary(v);
405 return divide_assign(x,temporary);
411 template<
class VecX,
class T,
class Device>
412 typename std::enable_if<std::is_convertible<T, typename VecX::value_type>::value,VecX&>::type
413 operator+=(vector_expression<VecX, Device>& x, T t){
414 kernels::assign<typename device_traits<Device>:: template add<typename VecX::value_type> > (x, t);
421 template<
class VecX,
class T,
class Device>
422 typename std::enable_if<std::is_convertible<T, typename VecX::value_type>::value,VecX&>::type
423 operator-=(vector_expression<VecX, Device>& x, T t){
424 kernels::assign<typename device_traits<Device>:: template subtract<typename VecX::value_type> > (x, t);
431 template<
class VecX,
class T,
class Device>
432 typename std::enable_if<std::is_convertible<T, typename VecX::value_type>::value,VecX&>::type
433 operator*=(vector_expression<VecX, Device>& x, T t){
434 kernels::assign<typename device_traits<Device>:: template multiply<typename VecX::value_type> > (x, t);
441 template<
class VecX,
class T,
class Device>
442 typename std::enable_if<std::is_convertible<T, typename VecX::value_type>::value,VecX&>::type
443 operator/=(vector_expression<VecX, Device>& x, T t){
444 kernels::assign<typename device_traits<Device>:: template divide<typename VecX::value_type> > (x, t);
460 template<
class MatA,
class MatB,
class Device>
461 MatA& operator+=(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
462 REMORA_SIZE_CHECK(A().size1() == B().size1());
463 REMORA_SIZE_CHECK(A().size2() == B().size2());
464 typename matrix_temporary<MatA>::type temporary(B);
465 return plus_assign(A,temporary);
474 template<
class MatA,
class MatB,
class Device>
475 MatA& operator-=(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
476 REMORA_SIZE_CHECK(A().size1() == B().size1());
477 REMORA_SIZE_CHECK(A().size2() == B().size2());
478 typename matrix_temporary<MatA>::type temporary(B);
479 return plus_assign(A,temporary,
typename MatA::value_type(-1.0));
488 template<
class MatA,
class MatB,
class Device>
489 MatA& operator*=(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
490 REMORA_SIZE_CHECK(A().size1() == B().size1());
491 REMORA_SIZE_CHECK(A().size2() == B().size2());
492 typename matrix_temporary<MatA>::type temporary(B);
493 return multiply_assign(A,temporary);
502 template<
class MatA,
class MatB,
class Device>
503 MatA& operator/=(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
504 REMORA_SIZE_CHECK(A().size1() == B().size1());
505 REMORA_SIZE_CHECK(A().size2() == B().size2());
506 typename matrix_temporary<MatA>::type temporary(B);
507 return divide_assign(A,temporary);
513 template<
class MatA,
class T,
class Device>
514 typename std::enable_if<std::is_convertible<T, typename MatA::value_type>::value,MatA&>::type
515 operator+=(matrix_expression<MatA, Device>& A, T t){
516 kernels::assign<typename device_traits<Device>:: template add<typename MatA::value_type> > (A, t);
523 template<
class MatA,
class T,
class Device>
524 typename std::enable_if<std::is_convertible<T, typename MatA::value_type>::value,MatA&>::type
525 operator-=(matrix_expression<MatA, Device>& A, T t){
526 kernels::assign<typename device_traits<Device>:: template subtract<typename MatA::value_type> > (A, t);
533 template<
class MatA,
class T,
class Device>
534 typename std::enable_if<std::is_convertible<T, typename MatA::value_type>::value,MatA&>::type
535 operator*=(matrix_expression<MatA, Device>& A, T t){
536 kernels::assign<typename device_traits<Device>:: template multiply<typename MatA::value_type> > (A, t);
543 template<
class MatA,
class T,
class Device>
544 typename std::enable_if<std::is_convertible<T, typename MatA::value_type>::value,MatA&>::type
545 operator/=(matrix_expression<MatA, Device>& A, T t){
546 kernels::assign<typename device_traits<Device>:: template divide<typename MatA::value_type> > (A, t);
556 template<
class T,
class U>
557 temporary_proxy<T> operator+=(temporary_proxy<T> x, U
const& arg){
558 static_cast<T&
>(x) += arg;
561 template<
class T,
class U>
562 temporary_proxy<T> operator-=(temporary_proxy<T> x, U
const& arg){
563 static_cast<T&
>(x) -= arg;
566 template<
class T,
class U>
567 temporary_proxy<T> operator*=(temporary_proxy<T> x, U
const& arg){
568 static_cast<T&
>(x) *= arg;
571 template<
class T,
class U>
572 temporary_proxy<T> operator/=(temporary_proxy<T> x, U
const& arg){
573 static_cast<T&
>(x) /= arg;
585 typedef typename C::closure_type closure_type;
586 typedef typename C::value_type value_type;
588 noalias_proxy(C &lval): m_lval(lval) {}
590 noalias_proxy(
const noalias_proxy &p):m_lval(p.m_lval) {}
593 closure_type &operator= (
const E &e) {
594 return assign(m_lval, e);
598 closure_type &operator+= (
const E &e) {
599 return plus_assign(m_lval, e);
603 closure_type &operator-= (
const E &e) {
604 return plus_assign(m_lval, e,
typename C::value_type(-1));
608 closure_type &operator*= (
const E &e) {
609 return multiply_assign(m_lval, e);
613 closure_type &operator/= (
const E &e) {
614 return divide_assign(m_lval, e);
618 closure_type &operator+= (value_type t) {
623 closure_type &operator-= (value_type t) {
628 closure_type &operator*= (value_type t) {
633 closure_type &operator/= (value_type t) {
643 template <
class C,
class Device>
644 noalias_proxy<C> noalias(matrix_expression<C, Device>& lvalue) {
645 return noalias_proxy<C> (lvalue());
647 template <
class C,
class Device>
648 noalias_proxy<C> noalias(vector_expression<C, Device>& lvalue) {
649 return noalias_proxy<C> (lvalue());
652 template <
class C,
class Device>
653 noalias_proxy<C> noalias(vector_set_expression<C>& lvalue) {
654 return noalias_proxy<C> (lvalue());
657 noalias_proxy<C> noalias(temporary_proxy<C> lvalue) {
658 return noalias_proxy<C> (
static_cast<C&
>(lvalue));