33#ifndef REMORA_ASSIGNMENT_HPP
34#define REMORA_ASSIGNMENT_HPP
38#include "detail/traits.hpp"
39#include "detail/proxy_optimizers_fwd.hpp"
53template<
class E,
class Device>
54typename std::conditional<
57 typename E::evaluation_category
59 typename vector_temporary<E>::type,
62eval_block(vector_expression<E, Device>
const& e){
70template<
class E,
class Device>
71typename std::conditional<
74 typename E::evaluation_category
76 typename matrix_temporary<E>::type,
79eval_block(matrix_expression<E, Device>
const& e){
89template<
class E,
class Device>
90typename std::conditional<
93 typename E::storage_type
95 typename vector_temporary<E>::type,
98eval_expression(vector_expression<E, Device>
const& e){
106template<
class E,
class Device>
107typename std::conditional<
110 typename E::storage_type
112 typename matrix_temporary<E>::type,
115eval_expression(matrix_expression<E, Device>
const& e){
124 template<
class VecX,
class VecV,
class Device>
126 vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v,
129 kernels::assign(x, v);
131 template<
class VecX,
class VecV,
class Device>
133 vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v,
138 template<
class VecX,
class VecV,
class Device>
139 void plus_assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v,
142 typename device_traits<Device>:: template add<typename common_value_type<VecX,VecV>::type> f;
143 kernels::assign(x, v, f);
145 template<
class VecX,
class VecV,
class Device>
147 vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v,
150 v().plus_assign_to(x);
158template<
class VecX,
class VecV,
class Device>
159VecX& assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
160 REMORA_SIZE_CHECK(x().size() == v().size());
161 detail::assign(x,v,
typename VecV::evaluation_category());
169template<
class VecX,
class VecV,
class Device>
170VecX& plus_assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
171 REMORA_SIZE_CHECK(x().size() == v().size());
172 detail::plus_assign(x,v,
typename VecV::evaluation_category());
180template<
class VecX,
class VecV,
class Device>
181VecX& minus_assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
182 REMORA_SIZE_CHECK(x().size() == v().size());
184 typedef typename VecV::value_type value_type;
185 auto minusV = detail::vector_scalar_multiply_optimizer<VecV>::create(v(),value_type(-1));
186 detail::plus_assign(x,minusV,
typename VecV::evaluation_category());
194template<
class VecX,
class VecV,
class Device>
195VecX& multiply_assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
196 REMORA_SIZE_CHECK(x().size() == v().size());
197 auto&& veval = eval_block(v);
198 typedef typename device_traits<Device>:: template multiply<typename common_value_type<VecX,VecV>::type> F;
199 kernels::assign(x, veval, F());
207template<
class VecX,
class VecV,
class Device>
208VecX& divide_assign(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
209 REMORA_SIZE_CHECK(x().size() == v().size());
210 auto&& veval = eval_block(v);
211 typedef typename device_traits<Device>:: template divide<typename common_value_type<VecX,VecV>::type> F;
212 kernels::assign(x, veval, F());
221 template<
class MatA,
class MatB,
class Device>
223 matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B,
226 kernels::assign(A, B);
228 template<
class MatA,
class MatB,
class Device>
230 matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B,
235 template<
class MatA,
class MatB,
class Device>
237 matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B,
240 typename device_traits<Device>:: template add<typename common_value_type<MatA,MatB>::type> f;
241 kernels::assign(A,B,f);
243 template<
class MatA,
class MatB,
class Device>
245 matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B,
248 B().plus_assign_to(A);
256template<
class MatA,
class MatB,
class Device>
257MatA& assign(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
258 REMORA_SIZE_CHECK(A().size1() == B().size1());
259 REMORA_SIZE_CHECK(A().size2() == B().size2());
260 detail::assign(A,B,
typename MatB::evaluation_category());
268template<
class MatA,
class MatB,
class Device>
269MatA& plus_assign(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
270 REMORA_SIZE_CHECK(A().size1() == B().size1());
271 REMORA_SIZE_CHECK(A().size2() == B().size2());
272 detail::plus_assign(A,B,
typename MatB::evaluation_category());
280template<
class MatA,
class MatB,
class Device>
281MatA& minus_assign(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
282 REMORA_SIZE_CHECK(A().size1() == B().size1());
283 REMORA_SIZE_CHECK(A().size2() == B().size2());
284 typedef typename MatB::value_type value_type;
285 auto minusB = detail::matrix_scalar_multiply_optimizer<MatB>::create(B(),value_type(-1));
286 detail::plus_assign(A, minusB,
typename MatB::evaluation_category());
294template<
class MatA,
class MatB,
class Device>
295MatA& multiply_assign(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
296 REMORA_SIZE_CHECK(A().size1() == B().size1());
297 REMORA_SIZE_CHECK(A().size2() == B().size2());
298 auto&& Beval = eval_block(B);
299 typedef typename device_traits<Device>:: template multiply<typename common_value_type<MatA,MatB>::type> F;
300 kernels::assign(A, Beval, F());
308template<
class MatA,
class MatB,
class Device>
309MatA& divide_assign(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
310 REMORA_SIZE_CHECK(A().size1() == B().size1());
311 REMORA_SIZE_CHECK(A().size2() == B().size2());
312 auto&& Beval = eval_block(B);
313 typedef typename device_traits<Device>:: template divide<typename common_value_type<MatA,MatB>::type> F;
314 kernels::assign(A, Beval, F());
328template<
class VecX,
class VecV,
class Device>
329VecX& operator+=(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
330 REMORA_SIZE_CHECK(x().size() == v().size());
331 typename vector_temporary<VecX>::type temporary(v);
332 return plus_assign(x,temporary);
335template<
class VecX,
class VecV,
class Device>
336typename VecX::closure_type operator+=(vector_expression<VecX, Device>&& x, vector_expression<VecV, Device>
const& v){
337 REMORA_SIZE_CHECK(x().size() == v().size());
338 typename vector_temporary<VecX>::type temporary(v);
339 return plus_assign(x,temporary);
348template<
class VecX,
class VecV,
class Device>
349VecX& operator-=(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
350 REMORA_SIZE_CHECK(x().size() == v().size());
351 typename vector_temporary<VecX>::type temporary(v);
352 return minus_assign(x,temporary);
355template<
class VecX,
class VecV,
class Device>
356typename VecX::closure_type operator-=(vector_expression<VecX, Device>&& x, vector_expression<VecV, Device>
const& v){
357 REMORA_SIZE_CHECK(x().size() == v().size());
358 typename vector_temporary<VecX>::type temporary(v);
359 return minus_assign(x,temporary);
368template<
class VecX,
class VecV,
class Device>
369VecX& operator*=(vector_expression<VecX, Device>& x, vector_expression<VecV, Device>
const& v){
370 REMORA_SIZE_CHECK(x().size() == v().size());
371 typename vector_temporary<VecX>::type temporary(v);
372 return multiply_assign(x,temporary);
375template<
class VecX,
class VecV,
class Device>
376typename VecX::closure_type 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 multiply_assign(x,temporary);
388template<
class VecX,
class VecV,
class Device>
389VecX& 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 divide_assign(x,temporary);
395template<
class VecX,
class VecV,
class Device>
396typename VecX::closure_type operator/=(vector_expression<VecX, Device>&& x, vector_expression<VecV, Device>
const& v){
397 REMORA_SIZE_CHECK(x().size() == v().size());
398 typename vector_temporary<VecX>::type temporary(v);
399 divide_assign(x,temporary);
405template<
class VecX,
class T,
class Device>
406typename std::enable_if<std::is_convertible<T, typename VecX::value_type>::value,VecX&>::type
407operator+=(vector_expression<VecX, Device>& x, T t){
408 kernels::assign<typename device_traits<Device>:: template add<typename VecX::value_type> > (x, t);
412template<
class VecX,
class T,
class Device>
413typename std::enable_if<std::is_convertible<T, typename VecX::value_type>::value,
typename VecX::closure_type>::type
414operator+=(vector_expression<VecX, Device>&& x, T t){
415 kernels::assign<typename device_traits<Device>:: template add<typename VecX::value_type> > (x, t);
422template<
class VecX,
class T,
class Device>
423typename std::enable_if<std::is_convertible<T, typename VecX::value_type>::value,VecX&>::type
424operator-=(vector_expression<VecX, Device>& x, T t){
425 kernels::assign<typename device_traits<Device>:: template subtract<typename VecX::value_type> > (x, t);
429template<
class VecX,
class T,
class Device>
430typename std::enable_if<std::is_convertible<T, typename VecX::value_type>::value,
typename VecX::closure_type>::type
431operator-=(vector_expression<VecX, Device>&& x, T t){
432 kernels::assign<typename device_traits<Device>:: template subtract<typename VecX::value_type> > (x, t);
439template<
class VecX,
class T,
class Device>
440typename std::enable_if<std::is_convertible<T, typename VecX::value_type>::value,VecX&>::type
441operator*=(vector_expression<VecX, Device>& x, T t){
442 kernels::assign<typename device_traits<Device>:: template multiply<typename VecX::value_type> > (x, t);
446template<
class VecX,
class T,
class Device>
447typename std::enable_if<std::is_convertible<T, typename VecX::value_type>::value,
typename VecX::closure_type>::type
448operator*=(vector_expression<VecX, Device>&& x, T t){
449 kernels::assign<typename device_traits<Device>:: template multiply<typename VecX::value_type> > (x, t);
456template<
class VecX,
class T,
class Device>
457typename std::enable_if<std::is_convertible<T, typename VecX::value_type>::value,VecX&>::type
458operator/=(vector_expression<VecX, Device>& x, T t){
459 kernels::assign<typename device_traits<Device>:: template divide<typename VecX::value_type> > (x, t);
463template<
class VecX,
class T,
class Device>
464typename std::enable_if<std::is_convertible<T, typename VecX::value_type>::value,
typename VecX::closure_type>::type
465operator/=(vector_expression<VecX, Device>&& x, T t){
466 kernels::assign<typename device_traits<Device>:: template divide<typename VecX::value_type> > (x, t);
482template<
class MatA,
class MatB,
class Device>
483MatA& operator+=(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
484 REMORA_SIZE_CHECK(A().size1() == B().size1());
485 REMORA_SIZE_CHECK(A().size2() == B().size2());
486 typename matrix_temporary<MatA>::type temporary(B);
487 return plus_assign(A,temporary);
490template<
class MatA,
class MatB,
class Device>
491typename MatA::closure_type operator+=(matrix_expression<MatA, Device>&& A, matrix_expression<MatB, Device>
const& B){
492 REMORA_SIZE_CHECK(A().size1() == B().size1());
493 REMORA_SIZE_CHECK(A().size2() == B().size2());
494 typename matrix_temporary<MatA>::type temporary(B);
495 return plus_assign(A,temporary);
504template<
class MatA,
class MatB,
class Device>
505MatA& operator-=(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
506 REMORA_SIZE_CHECK(A().size1() == B().size1());
507 REMORA_SIZE_CHECK(A().size2() == B().size2());
508 typename matrix_temporary<MatA>::type temporary(B);
509 return minus_assign(A,temporary);
512template<
class MatA,
class MatB,
class Device>
513typename MatA::closure_type operator-=(matrix_expression<MatA, Device>&& A, matrix_expression<MatB, Device>
const& B){
514 REMORA_SIZE_CHECK(A().size1() == B().size1());
515 REMORA_SIZE_CHECK(A().size2() == B().size2());
516 typename matrix_temporary<MatA>::type temporary(B);
517 return minus_assign(A,temporary);
526template<
class MatA,
class MatB,
class Device>
527MatA& operator*=(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
528 REMORA_SIZE_CHECK(A().size1() == B().size1());
529 REMORA_SIZE_CHECK(A().size2() == B().size2());
530 typename matrix_temporary<MatA>::type temporary(B);
531 return multiply_assign(A,temporary);
534template<
class MatA,
class MatB,
class Device>
535typename MatA::closure_type operator*=(matrix_expression<MatA, Device>&& A, matrix_expression<MatB, Device>
const& B){
536 REMORA_SIZE_CHECK(A().size1() == B().size1());
537 REMORA_SIZE_CHECK(A().size2() == B().size2());
538 typename matrix_temporary<MatA>::type temporary(B);
539 return multiply_assign(A,temporary);
548template<
class MatA,
class MatB,
class Device>
549MatA& operator/=(matrix_expression<MatA, Device>& A, matrix_expression<MatB, Device>
const& B){
550 REMORA_SIZE_CHECK(A().size1() == B().size1());
551 REMORA_SIZE_CHECK(A().size2() == B().size2());
552 typename matrix_temporary<MatA>::type temporary(B);
553 return divide_assign(A,temporary);
556template<
class MatA,
class MatB,
class Device>
557typename MatA::closure_type operator/=(matrix_expression<MatA, Device>&& A, matrix_expression<MatB, Device>
const& B){
558 REMORA_SIZE_CHECK(A().size1() == B().size1());
559 REMORA_SIZE_CHECK(A().size2() == B().size2());
560 typename matrix_temporary<MatA>::type temporary(B);
561 return divide_assign(A,temporary);
567template<
class MatA,
class T,
class Device>
568typename std::enable_if<std::is_convertible<T, typename MatA::value_type>::value,MatA&>::type
569operator+=(matrix_expression<MatA, Device>& A, T t){
570 kernels::assign<typename device_traits<Device>:: template add<typename MatA::value_type> > (A, t);
574template<
class MatA,
class T,
class Device>
575typename std::enable_if<std::is_convertible<T, typename MatA::value_type>::value,
typename MatA::closure_type>::type
576operator+=(matrix_expression<MatA, Device>&& A, T t){
577 kernels::assign<typename device_traits<Device>:: template add<typename MatA::value_type> > (A, t);
584template<
class MatA,
class T,
class Device>
585typename std::enable_if<std::is_convertible<T, typename MatA::value_type>::value,MatA&>::type
586operator-=(matrix_expression<MatA, Device>& A, T t){
587 kernels::assign<typename device_traits<Device>:: template subtract<typename MatA::value_type> > (A, t);
591template<
class MatA,
class T,
class Device>
592typename std::enable_if<std::is_convertible<T, typename MatA::value_type>::value,
typename MatA::closure_type>::type
593operator-=(matrix_expression<MatA, Device>&& A, T t){
594 kernels::assign<typename device_traits<Device>:: template subtract<typename MatA::value_type> > (A, t);
601template<
class MatA,
class T,
class Device>
602typename std::enable_if<std::is_convertible<T, typename MatA::value_type>::value,MatA&>::type
603operator*=(matrix_expression<MatA, Device>& A, T t){
604 kernels::assign<typename device_traits<Device>:: template multiply<typename MatA::value_type> > (A, t);
608template<
class MatA,
class T,
class Device>
609typename std::enable_if<std::is_convertible<T, typename MatA::value_type>::value,
typename MatA::closure_type>::type
610operator*=(matrix_expression<MatA, Device>&& A, T t){
611 kernels::assign<typename device_traits<Device>:: template multiply<typename MatA::value_type> > (A, t);
618template<
class MatA,
class T,
class Device>
619typename std::enable_if<std::is_convertible<T, typename MatA::value_type>::value,MatA&>::type
620operator/=(matrix_expression<MatA, Device>& A, T t){
621 kernels::assign<typename device_traits<Device>:: template divide<typename MatA::value_type> > (A, t);
625template<
class MatA,
class T,
class Device>
626typename std::enable_if<std::is_convertible<T, typename MatA::value_type>::value,
typename MatA::closure_type>::type
627operator/=(matrix_expression<MatA, Device>&& A, T t){
628 kernels::assign<typename device_traits<Device>:: template divide<typename MatA::value_type> > (A, t);
637 typedef typename C::closure_type closure_type;
638 typedef typename C::value_type value_type;
640 noalias_proxy(C &lval): m_lval(lval) {}
642 noalias_proxy(
const noalias_proxy &p):m_lval(p.m_lval) {}
645 closure_type &operator= (
const E &e) {
646 return assign(m_lval, e);
650 closure_type &operator+= (
const E &e) {
651 return plus_assign(m_lval, e);
655 closure_type &operator-= (
const E &e) {
656 return minus_assign(m_lval, e);
660 closure_type &operator*= (
const E &e) {
661 return multiply_assign(m_lval, e);
665 closure_type &operator/= (
const E &e) {
666 return divide_assign(m_lval, e);
670 closure_type &operator+= (value_type t) {
675 closure_type &operator-= (value_type t) {
680 closure_type &operator*= (value_type t) {
685 closure_type &operator/= (value_type t) {
695template <
class C,
class Device>
696noalias_proxy<C> noalias(matrix_expression<C, Device>& lvalue) {
697 return noalias_proxy<C> (lvalue());
699template <
class C,
class Device>
700noalias_proxy<C> noalias(vector_expression<C, Device>& lvalue) {
701 return noalias_proxy<C> (lvalue());
703template <
class C,
class Device>
704noalias_proxy<C> noalias(vector_expression<C, Device>&& rvalue) {
705 return noalias_proxy<C>(rvalue());
707template <
class C,
class Device>
708noalias_proxy<C> noalias(matrix_expression<C, Device>&& lvalue) {
709 return noalias_proxy<C> (lvalue());
712template <
class C,
class Device>
713noalias_proxy<C> noalias(vector_set_expression<C, Device>& lvalue) {
714 return noalias_proxy<C> (lvalue());