-1

Problem: I have overloaded operators * and *= with the same solution, though using operator *= doesn't seem to change the contents of the Matrix, maybe I am declaring the operator overload method incorrectly.

At the same time, operator * works properly and actually multiplies Matrix, I have checked it beforehand.

Output:

3 4 -5 
8 0 7 
8 9 -4 

8 7 7 
-6 0 6 
2 2 9 

3 4 -5 
8 0 7 
8 9 -4 

Here is the code itself:

struct WrappedMatrix{
        int n;
        int ** Matrix;
    };

    struct WrappedVector{
        int n;
        int * Vector;
    };

    WrappedVector linearizedMatrix(WrappedMatrix matrix){
        WrappedVector vector;
        vector.n = matrix.n * matrix.n;
        vector.Vector = new int[vector.n];
        for(int i = 0; i < matrix.n; i++){
            for(int j = 0; j < matrix.n; j++){
                 int k = j + (int) (i*sqrt(vector.n));
                 vector.Vector[k] = matrix.Matrix[i][j];
            }
        }
        return vector;
    }

    WrappedMatrix normalMatrix(WrappedVector vector){
        WrappedMatrix matrix;
        matrix.n = sqrt(vector.n);
        matrix.Matrix = new int * [matrix.n];
        for(int i = 0; i < matrix.n; i++){
            matrix.Matrix[i] = new int[matrix.n];
            for(int j = 0; j < matrix.n; j++){
                int k = j + (int) (i*sqrt(vector.n));
                matrix.Matrix[i][j] = vector.Vector[k];
            }
        }
        return matrix;
    }

    WrappedVector operator*(const WrappedVector& vector1, const WrappedVector& vector2) {
        if(vector1.n != vector2.n) {
            cout << "Матриці різних розмірів!" << endl;
            return vector1;
        }
        WrappedMatrix matrix1 = normalMatrix(vector1);
        WrappedMatrix matrix2 = normalMatrix(vector2);
        WrappedMatrix result;
        result.n = matrix1.n;
        result.Matrix = new int * [result.n];
        for(int i = 0; i < result.n; i++){
            result.Matrix[i] = new int[result.n];
        }
        for(int i = 0; i < result.n; i++){
            for(int j = 0; j < result.n; j++){
                for(int k = 0; k < result.n; k++){
                    int p1 = matrix1.Matrix[i][k];
                    int p2 = matrix2.Matrix[k][j];
                    result.Matrix[i][j] += p1 * p2;
                }
            }
        }
        WrappedVector resultV = linearizedMatrix(result);
        return resultV;
    }

    //?
    WrappedVector operator*=(const WrappedVector& vector1, const WrappedVector& vector2) {
        if(vector1.n != vector2.n) {
            cout << "Матриці різних розмірів!" << endl;
            return vector1;
        }
        WrappedMatrix matrix1 = normalMatrix(vector1);
        WrappedMatrix matrix2 = normalMatrix(vector2);
        WrappedMatrix result;
        result.n = matrix1.n;
        result.Matrix = new int * [result.n];
        for(int i = 0; i < result.n; i++){
            result.Matrix[i] = new int[result.n];
        }
        for(int i = 0; i < result.n; i++){
            for(int j = 0; j < result.n; j++){
                for(int k = 0; k < result.n; k++){
                    int p1 = matrix1.Matrix[i][k];
                    int p2 = matrix2.Matrix[k][j];
                    result.Matrix[i][j] += p1 * p2;
                }
            }
        }
        WrappedVector resultV = linearizedMatrix(result);
        return resultV;
    }


    int main() {

        WrappedMatrix matrix;
        matrix.n = 3;
        matrix.Matrix = new int * [matrix.n];
        matrix.Matrix[0] = new int[matrix.n];
        matrix.Matrix[1] = new int[matrix.n];
        matrix.Matrix[2] = new int[matrix.n];
        matrix.Matrix[0][0] = 3;
         matrix.Matrix[0][1] = 4;
         matrix.Matrix[0][2] = -5;
        matrix.Matrix[1][0] = 8;
         matrix.Matrix[1][1] = 0;
         matrix.Matrix[1][2] = 7;
         matrix.Matrix[2][0] = 8;
         matrix.Matrix[2][1] = 9;
         matrix.Matrix[2][2] = -4;
        WrappedVector vector = linearizedMatrix(matrix);

        cout << vector << endl;

        WrappedMatrix matrix1;
        matrix1.n = 3;
        matrix1.Matrix = new int * [matrix1.n];
        matrix1.Matrix[0] = new int[matrix1.n];
        matrix1.Matrix[1] = new int[matrix1.n];
        matrix1.Matrix[2] = new int[matrix1.n];
        matrix1.Matrix[0][0] = 8;
        matrix1.Matrix[0][1] = 7;
        matrix1.Matrix[0][2] = 7;
        matrix1.Matrix[1][0] = -6;
        matrix1.Matrix[1][1] = 0;
        matrix1.Matrix[1][2] = 6;
        matrix1.Matrix[2][0] = 2;
        matrix1.Matrix[2][1] = 2;
        matrix1.Matrix[2][2] = 9;
        WrappedVector vector1 = linearizedMatrix(matrix1);

        cout << vector1 << endl;

        vector *= vector1;

        cout << vector;


        return 0;
    }

Thank you in advance!

  • 1
    You are returning `WrappedMatrix` by value. To return anything by value requires that value to have correct copy semantics. Your `WrappedMatrix` does not have correct copy semantics since it violates the [Rule of 3](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). Either implement those missing functions that you see at the link, or save yourself trouble by using `std::vector` and `std::vector>` instead `int *` and `int **`. – PaulMcKenzie Dec 07 '18 at 00:29
  • Also, the same for `WrappedVector`. The easiest thing for you to do is just use the `vector` I mentioned. That takes care of all of the pointer issues (but other issues may be present). – PaulMcKenzie Dec 07 '18 at 00:31
  • Note: storing arrays of arrays can be a performance killer. For small matrices it's not uncommon to find the program spending more time chasing pointers and loading cache than crunching numbers. Consider using a single 1 Dimensional array or vector and performing the 2D <-> 1D mapping yourself with `row * number_columns + column`. [Example with `std::vector`](https://stackoverflow.com/a/2076668/4581301) – user4581301 Dec 07 '18 at 00:35
  • Ask yourself a simple question: since you're passing a `const` reference to your `*=` overload, how exactly do you expect to modify the `const` object you're passing? You can't (and the exceptions are not relevant here). `*=` does not work the way you think it works. – Sam Varshavchik Dec 07 '18 at 01:20
  • @SamVarshavchik Actually, changing the data pointed to by `int ** Matrix` will be possible (only the outer pointer can't be modified without const-casting). – chtz Dec 07 '18 at 01:24
  • Also, `operator*` can be implemented by just calling `operator *=`, instead of duplicating code. – PaulMcKenzie Dec 07 '18 at 01:25

1 Answers1

0

This isn't an answer technically, I just revamped the code thus far, I'll add onto it later tonight if I have time. I just managed to put something together this morning, figured you might as well have a look so it doesn't just lay around doing nothing:

#include <iostream>
#include <vector>
#include <cstdarg>

class matrix{
    public:
        matrix(){};
        matrix(std::initializer_list<std::vector<int>> vectors):x(vectors){}
        ~matrix(){};

        const int& size(){ return this->x.size(); } //# of vectors
        //ALT: ex. print: 3x3, 4x5, 7x3
        //void size(){ std::cout<<"Dim: "<<this->x.size<<"x"<<this->x.front().size()<<std::endl;
        void add(const std::vector<int>& arr){ this->x.push_back(arr); }
        const std::vector<std::vector<int>>& extract(){ return this->x; } //Returns entire matrix
        const std::vector<int>& getVector(const int& row){ return this->x.at(row); } //Returns specific vector from matrix

        matrix operator*(const matrix& m){ //More params
            //Stuff here
        }
        matrix operator*=(const matrix& m){ //More params
            //Stuff here
        }

    private:
        std::vector<std::vector<int>> x;
};

//Can break the center out to make one for vectors too
std::ostream& operator<<(std::ostream& os, matrix& m){
    for (auto& it:m.extract()){
        for (auto& jt:it){
            os<<jt<<" ";
        }
        os<<std::endl;
    }
    os<<std::endl;
    return os;
}


int main(){
    matrix m({{2,5,8,11,14},
              {3,6,9,12,15},
              {4,7,10,13,16}});
    std::cout<<m;

    return 0;
}

This is, from what I gather, what the comments were about. Much easier to use in my opinion, though it may be something other than what you need if you are demanded to make structs and access vectors in some particular way.

Also, I didn't figure out what mathematical result you had in mind there, so I didn't put anything into the operators, I might add some crossproduct or dotproduct example later on, if that's what you were doing.

Jack Of Blades
  • 495
  • 7
  • 16