-2

I am writing a matrix manipulation class in C++ as a course project. I want the syntax to be as close to MATLAB as possible. I wish to implement a constructor for the matrix which allows me to do something like what is shown below:

Matrix X(3,3) = {1, 2, 3, 4, 5, 6, 7, 8, 9};
//     [1  2  3]
// X = [4  5  6]
//     [7  8  9]

I have tried using an initializer_list constructor but that only allows me to do:

Matrix X(3,3,{1, 2, 3, 4, 5, 6, 7, 8, 9});

Here's my code for this constructor:

Matrix::Matrix(size_t row, size_t col) : nrow(row), ncol(col), len(row*col) {
    mat = std::unique_ptr<double[]>(new double[len]);
}

void Matrix::operator= (std::initializer_list<double> list) {
    if (list.size() != len)
        throw std::length_error("Sizes of matrix and initializer list do not match");
    auto it = list.begin();
    for (int i = 0; it != list.end(); ++i, ++it)
        mat[i] = *it;
}

Matrix::Matrix(size_t row, size_t col, std::initializer_list<double> list) : Matrix::Matrix(row, col) {
    *this = list;
}

I need suggestions on how to implement the first one.

lakshayg
  • 2,053
  • 2
  • 20
  • 34
  • 2
    Why not use a `std::vector` instead of a `std::unique_ptr`? – NathanOliver May 20 '16 at 17:58
  • @NathanOliver I may be completely wrong but I think arrays are faster and lighter as compared to vectors. – lakshayg May 20 '16 at 18:00
  • A `std::vector` performance wise should be just as fast. You still have a memory allocation in both cases and afterwards access speed should be the same. – NathanOliver May 20 '16 at 18:03
  • @LakshayGarg Unfortunately, people here often downvote questions if what they are asking is impossible. – Dan May 20 '16 at 18:20
  • 1
    Just as a side note, opencv has a particular way to do this: `Mat m = (Mat_(3,3) << 0,-1,0,-1,5,-1,0,-1,0);` though its a bit more complicated to implement – kmdreko May 20 '16 at 18:41
  • Check out the Armadillo project for ideas. They also implemented a Matrix API (and more) that tried to emulate Matlab as much as possible. As mentioned OpenCV has also done similar things, there are quite a few matrix libraries out there. Given its for school you'll obviously want to write your own still, but you should look at how other people have solved that problem when formulating your own solution. – RyanP May 20 '16 at 18:55
  • @NathanOliver I did some timing by using std::vector and std::unique_pointer and I find that the time for constructing a matrix is smaller in case of std::unique_ptr. Also have a look here: http://stackoverflow.com/questions/16711697/is-there-any-use-for-unique-ptr-with-array PS: I tried timing a matrix of size 10000 x 10000 – lakshayg May 20 '16 at 19:05
  • @LakshayGarg I think you were using the wrong construction. I see no difference [here](http://coliru.stacked-crooked.com/a/d0894881503a5a8e) – NathanOliver May 20 '16 at 19:29
  • @NathanOliver Yes! you're right. I was using `resize` that is why it took more time. Thanks for the idea :) – lakshayg May 20 '16 at 19:33
  • @LakshayGarg No problem. – NathanOliver May 20 '16 at 19:38
  • @NathanOliver There's a catch. When you use `reserve`, you increase the vector capacity but its size is still 0. So you may get incorrect results if any of your methods use iterators without actually pushing anything into the vector. – lakshayg May 20 '16 at 20:36
  • @LakshayGarg *I did some timing* -- Always mention what type of build you're timing. If you're timing an unoptimized or "debug" version, your results are meaningless. – PaulMcKenzie May 20 '16 at 20:39
  • @LakshayGarg Yes there is that but you have that same cost with what you are doing with the pointer. the usage may differ slightly but the performance should be the same. – NathanOliver May 20 '16 at 20:58

1 Answers1

2

Your problem is with the syntax.

Matrix X(3,3) = {1, 2, 3, 4, 5, 6, 7, 8, 9};

is not legal c++, since you are using both the direct initialization syntax and the aggregate initialization syntax in one declaration. This means what you want to do can't work. You can, however, do something like this:

Matrix X(3,3);
X = {1, 2, 3, 4, 5, 6, 7, 8, 9};

which I believe will work with your code.

Dan
  • 12,409
  • 3
  • 50
  • 87