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());