Add Scalar to Vector

Issue #109 duplicate
Nils Deppe created an issue

Hi Klaus,

I am trying to add a scalar (double) to every element of a DenseVector by writing 1 + the_vector, which fails to find an appropriate operator+. Is this currently not implemented and if not would it be possible to add? The same for subtraction would be nice as well. Thanks!

Best,

Nils

Comments (3)

  1. Klaus Iglberger

    Hi Nils!

    Thanks for the proposal. You are correct, Blaze does not support the addition and subtraction of vector and/or matrices with scalar values. However, we also don't plan to support it for three reasons: First, mathematically it is not well defined. Second, it is not intuitively clear what such an operation would do (especially if the vector or matrix is sparse). And third, Blaze already provides all the features to enable you to add these operations yourself with just a few lines of code (building on the forEach() function; see the wiki for more details). The following code snippets provide you with the implementation of the scalar addition and scalar subtraction for dense vectors (including the according compound assignment operators and proper vectorization):

    template< typename ST >
    struct AddScalar
    {
     public:
       explicit inline AddScalar( ST scalar )
          : scalar_( scalar )
       {}
    
       template< typename T >
       BLAZE_ALWAYS_INLINE decltype(auto) operator()( const T& a ) const
       {
          return a + scalar_;
       }
    
       template< typename T >
       static constexpr bool simdEnabled() { return blaze::HasSIMDAdd<T,ST>::value; }
    
       template< typename T >
       BLAZE_ALWAYS_INLINE decltype(auto) load( const T& a ) const
       {
          BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
          return a + set( scalar_ );
       }
    
     private:
       ST scalar_;
    };
    
    template< typename VT, bool TF, typename Scalar
            , typename = blaze::EnableIf_< blaze::IsNumeric<Scalar> > >
    decltype(auto) operator+( const blaze::DenseVector<VT,TF>& vec, Scalar scalar )
    {
       return forEach( ~vec, AddScalar<Scalar>( scalar ) );
    }
    
    template< typename Scalar, typename VT, bool TF
            , typename = blaze::EnableIf_< blaze::IsNumeric<Scalar> > >
    decltype(auto) operator+( Scalar scalar, const blaze::DenseVector<VT,TF>& vec )
    {
       return forEach( ~vec, AddScalar<Scalar>( scalar ) );
    }
    
    template< typename VT, bool TF, typename Scalar
            , typename = blaze::EnableIf_< blaze::IsNumeric<Scalar> > >
    VT& operator+=( blaze::DenseVector<VT,TF>& vec, Scalar scalar )
    {
       (~vec) = (~vec) + scalar;
       return ~vec;
    }
    
    template< typename ST >
    struct SubScalar
    {
     public:
       explicit inline SubScalar( ST scalar )
          : scalar_( scalar )
       {}
    
       template< typename T >
       BLAZE_ALWAYS_INLINE decltype(auto) operator()( const T& a ) const
       {
          return a - scalar_;
       }
    
       template< typename T >
       static constexpr bool simdEnabled() { return blaze::HasSIMDSub<T,ST>::value; }
    
       template< typename T >
       BLAZE_ALWAYS_INLINE decltype(auto) load( const T& a ) const
       {
          BLAZE_CONSTRAINT_MUST_BE_SIMD_PACK( T );
          return a - set( scalar_ );
       }
    
     private:
       ST scalar_;
    };
    
    template< typename VT, bool TF, typename Scalar
            , typename = blaze::EnableIf_< blaze::IsNumeric<Scalar> > >
    decltype(auto) operator-( const blaze::DenseVector<VT,TF>& vec, Scalar scalar )
    {
       return forEach( ~vec, SubScalar<Scalar>( scalar ) );
    }
    
    template< typename VT, bool TF, typename Scalar
            , typename = blaze::EnableIf_< blaze::IsNumeric<Scalar> > >
    VT& operator-=( blaze::DenseVector<VT,TF>& vec, Scalar scalar )
    {
       (~vec) = (~vec) - scalar;
       return ~vec;
    }
    

    We hope that fits your needs. Thanks again for the proposal,

    Best regards,

    Klaus!

  2. Nils Deppe reporter

    Hey Klaus!

    This is exactly what I was looking for and your reasons for not including it by default I completely agree with :) Thanks for the super quick solution! :+1: (with this we now have Blaze in our code for the expression templates :) )

    Cheers,

    Nils!

  3. Log in to comment