Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiplying an object with a constant from left side

I have a Matrix class and it has overloaded * operators for scalar and matrix multiplications.

template <class T> class Matrix
{
    public:
        // ...
        Matrix operator*(T scalar) const;
        // ...
}

// ...

template <class T>
Matrix<T> Matrix<T>::operator*(T RightScalar) const
{
    Matrix<T> ResultMatrix(m_unRowSize, m_unColSize);
    for (uint64_t i=0; i<m_unRowSize; i++)
    {
        for (uint64_t j=0; j<m_unColSize; j++)
        {
            ResultMatrix(i, j) = TheMatrix[m_unColSize * i + j] * RightScalar;
        }
    }
    return ResultMatrix;
}

// ...

I can multiply a matrix object with a scalar from right side without any problem:

Matrix<double> X(3, 3, /* ... */);  // Define a 3x3 matrix and initialize its contents
Matrix<double> Y;                   // Define an output matrix
Y = X * 10.0;                       // Do the linear operation

But, how do I multiply it from left side same way?

Matrix<double> X(3, 3, /* ... */);
Matrix<double> Y;
Y = 10.0 * X;

In arithmetic, it is a common notation to write constants on the left side when doing multiplication. I would like to obey this rule to make my code more readable.

Is it possible to implement this in C++?
If it is possible, how do I modify the class method in my code?

like image 832
hkBattousai Avatar asked Jan 23 '13 14:01

hkBattousai


People also ask

What are the rules for multiplying a matrix and a scalar?

This property states that if a matrix is multiplied by two scalars, you can multiply the scalars together first, and then multiply by the matrix. Or you can multiply the matrix by one scalar, and then the resulting matrix by the other.

How do you prove scalar multiplication?

Proof: Let A = [aij] and B = [bij] are two m × n matrices. Therefore, k(A + B) = kA + kB (proved). Therefore, (k + c)A = kA + cA (proved).

How do you multiply something in Javascript?

The multiplication operator ( * ) multiplies numbers.

Is scalar multiplication linear?

In mathematics, scalar multiplication is one of the basic operations defining a vector space in linear algebra (or more generally, a module in abstract algebra).


2 Answers

You'll need a non-member function for that:

template <typename T>
Matrix<T> operator*(T scalar, Matrix<T> const & matrix) {
    return matrix * scalar;
}

Non-member operator overloads allow you to specify any type on either side, while member overloads always get the object on the left-hand side.

like image 71
Mike Seymour Avatar answered Sep 27 '22 20:09

Mike Seymour


Member functions are matched by their left-hand-side argument which is the this-pointer. Since native types can't have member functions, you have to add right-multiplication with user-defined types through non-member functions (and also for other types you don't have write-access to).

template<typename T>
Matrix<T> operator*(T const& scalar, Matrix<T> rhs)
{
    // scalar multiplication is commutative: s M = M s
    return rhs *= scalar; // calls rhs.operator*=(scalar);
}

NOTE: I wrote the above non-member operator* implemented in terms of a member operator*=. It is recommended to write all multiplications as non-member functions, and use a member operator*= to implement these multiplications with a lhs Matrix element.

This will a) keep the class interface minimal, and b) prevent hidden conversions. E.g. you could have a Matrix class that is implicitly convertible to scalar if the dimensions are 1x1, and these conversions could silently happen if you don't provide a separate overload that is a direct match.

template<typename T>
Matrix<T> operator*(Matrix<T> lhs, T const& scalar)
{
    return lhs *= scalar; // calls lhs.operator*=(scalar);
}

template<typename T>
Matrix<T> operator*(Matrix<T> lhs, Matrix<T> const& rhs)
{
    return lhs *= rhs; // calls lhs.operator*=(rhs);
}

Notice on how the lhs Matrix is a copy and not a reference. This allows the compiler to make optimizations such as copy elision / move semantics. Also note that the return type of these operators is Matrix<T> and not const Matrix<T> which was recommended in some old C++ books, but which prevents move semantics in C++11.

// class member 
template<typename T>
Matrix<T>& Matrix<T>::operator*=(Matrix<T> const& rhs)
{
    // your implementation
    return *this;
}

// class member 
template<typename T>
Matrix<T>& Matrix<T>::operator*=(T const& scalar)
{
    // your implementation
    return *this;
}
like image 33
TemplateRex Avatar answered Sep 27 '22 20:09

TemplateRex