simonthumper
simonthumper

Reputation: 1844

C++ Matrix in objective-c

I am trying to write a class to manipulate matrices in Objective-c, originally I was using NSArrays and NSNumbers, however this resulted in extremely slow code for what I'm doing (simulating a double pendulum) so I decided to try and re-write my arrays as c++ arrays, however I am getting problems which I have no idea how to solve.

Running this code gives me an error -[SMFiniteDifferenceHelper matrixHandler]: unrecognized selector sent to instance 0x100107cb0 even though my method is in the header file and implemented in the class. However if I leave only one of the array[][] values un-set the code runs fine...

BREAKS

self.matrixHandler = [[SMMatrixHandler alloc] init];

        double **array1 = (double **)malloc(3*2*sizeof(double)); // height
        for (int i = 0; i < 3; ++i)
            array1[i] = new double[2]; // width

        array1[0][0] = 1.0;
        array1[1][0] = 2.0;
        array1[0][1] = 1.0;
        array1[1][1] = 0.0;
        array1[0][2] = 4.0;
        array1[1][2] = 1.0;

        NSLog(@"array 1 : \n%@",[self.matrixHandler stringForMatrix:array1 ofSize:CGSizeMake(2, 3)]);

WORKS FINE

self.matrixHandler = [[SMMatrixHandler alloc] init];

        double **array1 = (double **)malloc(3*2*sizeof(double)); // height
        for (int i = 0; i < 3; ++i)
            array1[i] = new double[2]; // width

        array1[0][0] = 1.0;
        array1[1][0] = 2.0;
        array1[0][1] = 1.0;
        array1[1][1] = 0.0;
        // array1[0][2] = 4.0;
        array1[1][2] = 1.0;

        NSLog(@"array 1 : \n%@",[self.matrixHandler stringForMatrix:array1 ofSize:CGSizeMake(2, 3)]);

The method stringForArray looks like this:

- (NSString *)stringForMatrix:(double **)m ofSize:(CGSize)s {

    NSString *string = @"";

    for (int i = 0; i < s.height; i++) {

        for (int j = 0; j < s.width; j++) {

            string = [string stringByAppendingFormat:@"%f ",m[j][i]];

        }

        string = [string stringByAppendingString:@"\n"];

    }

    return string;

}

Upvotes: 2

Views: 629

Answers (2)

Grimm The Opiner
Grimm The Opiner

Reputation: 1806

Trouble is you have allocated an array of 6 doubles, but treat it as an array of arrays of doubles. Even if you had allocated it right, the lines

  array1[0][2] = 4.0;
  array1[1][2] = 1.0;

are wrong as index 2 is the third entry, and you're looking at a 3 item array of 2 item arrays.

Your code should look like this:

double** array1 = new double*[3];

for (int i = 0; i < 3; ++i)
{
    array1[i] = new double[2];
}

array1[0][0] = 1.0;
array1[0][1] = 2.0;
array1[1][0] = 1.0;
array1[1][1] = 0.0;
array1[2][0] = 4.0;
array1[2][1] = 1.0;

Or even better, like this:

vector< vector<double> > vec(3, vector<double>(2));

vec[0][0] = 1.0;
vec[0][1] = 2.0;
vec[1][0] = 1.0;
vec[1][1] = 0.0;
vec[2][0] = 4.0;
vec[2][1] = 1.0;

EDIT: An advanatge with vectors is they throw if you go out of bounds. A bare array as in the first example would exhibit undefined behaviour.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726559

Your size computations are incorrect, in the sense that they do not match your usage. This code

double **array1 = (double **)malloc(3*2*sizeof(double)); // height

allocates space for six doubles, but it is used as a storage for three pointers to double.

Since you are writing C++ code, not C code, you have an option of using std::vector containers - a preferred choice for situations like that. It frees you from the need to manage memory manually, and gives you execution speeds that match these of raw arrays.

Add #include <vector> at the top, then change the declaration as follows:

std::vector<std::vector<double> > array1(3, std::vector<double>(2, 0.0));

The code that uses the array remains the same.

Upvotes: 1

Related Questions