Mr. Crow
Mr. Crow

Reputation: 21

Matrix multiplication in Objective-C

These are some code that I carried in my project to do matrix computing.
They are two class methods and one instance method that for create matrices and do the matrix multiplication operation.
The method for matrics multiplication doesn't work well, the result from it is wrong.

+ (NSMutableArray *)arrayOfWidth:(NSInteger)width andHeight:(NSInteger)height {
    return [[self alloc] initWithWidth:width andHeight:height];
}

- (id)initWithWidth:(NSInteger)width andHeight:(NSInteger)height {
    if((self = [self initWithCapacity:height])) {
        for(int i = 0; i < height; i++) {
            NSMutableArray *inner = [[NSMutableArray alloc] initWithCapacity:width];
            [self addObject:inner];
        }
    }
    return self;
}

+ (NSMutableArray *)matrixA:(NSMutableArray *)matrixA multiplyMatrixB:(NSMutableArray *)matrixB {
    int aRow = [matrixA count];
    int aColumn = [[matrixA objectAtIndex:0] count];
    int bRow = [matrixB count];
    int bColumn = [[matrixB objectAtIndex:0] count];
    NSMutableArray *newArray = [NSMutableArray arrayOfWidth:aRow andHeight:bColumn];

    for (int i = 0; i < aRow; i++) {
        for (int j = 0; j < bColumn; j++) {
            double sum = 0.0;
            for (int k = 0; k < aColumn; k++) {
                NSMutableArray *innerA = [matrixA objectAtIndex:i];
                double numA = [[innerA objectAtIndex:k] doubleValue];
                NSMutableArray * innerB = [matrixB objectAtIndex:k];
                double numB = [[innerB objectAtIndex:j] doubleValue];
                sum += numA * numB; 
            }
            NSNumber *result = [NSNumber numberWithDouble:sum];
            [[newArray objectAtIndex:i] insertObject:result atIndex:j];
        }
    }
    return newArray;
}

Is there something wrong with the code? And how can I fix it?


    //First, I create a array to hold the numbers
    NSNumber *num11 = [NSNumber numberWithDouble:-2.0];
    NSNumber *num12 = [NSNumber numberWithDouble:1.0];
    NSNumber *num13 = [NSNumber numberWithDouble:-1.0];
    NSNumber *num14 = [NSNumber numberWithDouble:2.0];
    NSNumber *num21 = [NSNumber numberWithDouble:-7.0];
    NSNumber *num22 = [NSNumber numberWithDouble:0.0];
    NSNumber *num23 = [NSNumber numberWithDouble:-1.0];
    NSNumber *num24 = [NSNumber numberWithDouble:-4.0];
    NSNumber *num31 = [NSNumber numberWithDouble:-2.0];
    NSNumber *num32 = [NSNumber numberWithDouble:-1.0];
    NSNumber *num33 = [NSNumber numberWithDouble:0.0];
    NSNumber *num34 = [NSNumber numberWithDouble:-2.0];
    NSNumber *num41 = [NSNumber numberWithDouble:-3.0];
    NSNumber *num42 = [NSNumber numberWithDouble:-2.0];
    NSNumber *num43 = [NSNumber numberWithDouble:0.0];
    NSNumber *num44 = [NSNumber numberWithDouble:-3.0];

    NSMutableArray *temp = [NSMutableArray arrayWithObjects:num11, num12, num13, num14, num21, num22, num23, num24, num31, num32, num33, num34, num41, num42, num43, num44, nil];

    //Second, I create the matrix and get the elements from that array 
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            double c = [[temp objectAtIndex:4*i+j] doubleValue];
            NSNumber *object = [NSNumber numberWithDouble:c];
            [[matrix objectAtIndex:i] insertObject:object atIndex:j];
        }
    }

    //Then, I do the multiplication for matrix and itself
    NSMutableArray *multiMatrix = [NSMutableArray matrixA:matrix multiplyMatrixB:matrix];

    //get all the elements from the multiMatrix
    double m11 = [[[multiMatrix objectAtIndex:0] objectAtIndex:0] doubleValue];
    double m12 = [[[multiMatrix objectAtIndex:0] objectAtIndex:1] doubleValue];
    double m13 = [[[multiMatrix objectAtIndex:0] objectAtIndex:2] doubleValue];
    double m14 = [[[multiMatrix objectAtIndex:0] objectAtIndex:3] doubleValue];

    double m21 = [[[multiMatrix objectAtIndex:1] objectAtIndex:0] doubleValue];
    double m22 = [[[multiMatrix objectAtIndex:1] objectAtIndex:1] doubleValue];
    double m23 = [[[multiMatrix objectAtIndex:1] objectAtIndex:2] doubleValue];
    double m24 = [[[multiMatrix objectAtIndex:1] objectAtIndex:3] doubleValue];

    double m31 = [[[multiMatrix objectAtIndex:2] objectAtIndex:0] doubleValue];
    double m32 = [[[multiMatrix objectAtIndex:2] objectAtIndex:1] doubleValue];
    double m33 = [[[multiMatrix objectAtIndex:2] objectAtIndex:2] doubleValue];
    double m34 = [[[multiMatrix objectAtIndex:2] objectAtIndex:3] doubleValue];

    double m41 = [[[multiMatrix objectAtIndex:3] objectAtIndex:0] doubleValue];
    double m42 = [[[multiMatrix objectAtIndex:3] objectAtIndex:1] doubleValue];
    double m43 = [[[multiMatrix objectAtIndex:3] objectAtIndex:2] doubleValue];
    double m44 = [[[multiMatrix objectAtIndex:3] objectAtIndex:3] doubleValue];

    //Or you can use the NSLog to check the result 
    NSString *lineOne = [NSString stringWithFormat:@"%f, %f, %f, %f", m11, m12, m13, m14];
    NSString *lineTwo= [NSString stringWithFormat:@"%f, %f, %f, %f", m21, m22, m23, m24];
    NSString *lineThree = [NSString stringWithFormat:@"%f, %f, %f, %f", m31, m32, m33, m34];
    NSString *lineFour = [NSString stringWithFormat:@"%f, %f, %f, %f", m41, m42, m43, m44];

@rooftop, that's all the code

Upvotes: 0

Views: 7473

Answers (3)

Tim Le
Tim Le

Reputation: 279

There are mainly two errors here:

  1. In the main program, you did not declare matrix. You know how to fix this problem.
  2. As you create the matrix, if you already initialize the matrix to zeros, insertingObject will make the matrix of size '4x8', and not '4x4'.

    [[matrix objectAtIndex:i] insertObject:object atIndex:j];
    
  3. In your matrix multiplication method, you also insertObject into an existing matrix, making its size '4x8' instead of '4x4'.

To fix this second problem, you need to replace method insertObject:atIndex, with replaceObjectAtIndex:withObject.

That should solve the problem.

Upvotes: 0

geowar
geowar

Reputation: 4447

If you're on iOS you might want to consider the matrix routines in GLKit

Upvotes: 6

El Developer
El Developer

Reputation: 3346

If you are familiar with MATLAB's vector operations (even if you are not), I would recommend you to check the Accelerate Framework, it is an optimized framework for digital signal processing.

Two great advantages:

  • They have that operation already implemented.
  • It's a more efficient way to do it, but apparently not for small matrixes, see the comments for further detail.

This is probably the function you are looking for:

vDSP_mmul: Performs an out-of-place multiplication of two matrices; single precision.

void vDSP_mmul (
   float *__vDSP_a,
   vDSP_Stride __vDSP_aStride,
   float *__vDSP_b,
   vDSP_Stride __vDSP_bStride,
   float *__vDSP_c,
   vDSP_Stride __vDSP_cStride,
   vDSP_Length __vDSP_M,
   vDSP_Length __vDSP_N,
   vDSP_Length __vDSP_P
);
Parameters
__vDSP_a
Input matrix A.
__vDSP_aStride
The stride within __vDSP_a. For example if stride is 2, every second element is used.
__vDSP_b
Input matrix B.
__vDSP_bStride
The stride within __vDSP_b. For example if stride is 2, every second element is used.
__vDSP_c
The result matrix.
__vDSP_M
The number of rows in matrix A.
__vDSP_N
The number of columns in matrix B.
__vDSP_P
The number of columns in matrix A and the number of rows in matrix B.
Discussion
This function multiplies an M-by-P matrix (A) by a P-by-N matrix (B) and stores the results in an M-by-N matrix (C).

This performs the following operation:

On the other side if writing the method yourself is a requirement, this post won't help you at all.

Upvotes: 2

Related Questions