Reputation: 1844
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
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
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 double
s, 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