# Multi dimensional arrays in Objective-C



## Viro (Mar 23, 2005)

Simple question for those familiar with Objective-C. What are my options for using multi-dimensional arrays in Objective-C?


----------



## lurk (Mar 24, 2005)

Identical to C and Java.  How is that for a non answer?  Really it depends on what you mean by "array" do you mean a bunch of things in consecutive memory location a la C, or do you mean an instance of NSArray?


----------



## Viro (Mar 24, 2005)

That'll teach me to post a 12:30 am .

I meant multidimensional arrays of primitives, particularly doubles. In C, you can do it with a large array and simulate it with various offsets. Problem is, you need to code lots. 

I was hoping for a simpler solution in Objective-C, sorta like NSArray, except NSArray seems to deal with objects while I'm interested in primitives. You might be able to wrap primitives in objects but performance suffers and I don't want that. Is there something like NSArray for primitives? Or do I have to write one myself?


----------



## cfleck (Mar 24, 2005)

Actually in c you can make an array of pointers to array and thus have 2 dimensional arrays.  You needn't fiddle with offsets.


----------



## Lycander (Mar 24, 2005)

If you can squeeze STL in and use objective-C++


```
#include <vector>
using namespace std;

typedef vector <double> VDOUBLE;

int main()
{
   vector<VDOUBLE> vecvec;  // this is the 2D array

   VDOUBLE v1( ... );  // initialize it here or populate it with data later
   VDOUBLE v2( ... ); // same as above

   vecvec.push_back( v1 );  // add the array of doubles to the end
   vecvec.push_back( v2 );  // same as above

   // VDOUBLE is your new data type. Continue making new single dimension
   // arrays and add them to vecvec, the 2D array

   // Getting values out of the 2D array:
   for(int i=0; i<vecvec.size(); i++)
   {
      for(int j=0; j<vecvec[i].size(); j++)
      {
         cout << vecvec[i][j] << "\n";
      }
   }
   return 0;
}
```


----------



## Viro (Mar 24, 2005)

cfleck said:
			
		

> Actually in c you can make an array of pointers to array and thus have 2 dimensional arrays.  You needn't fiddle with offsets.



I've thought of that, but you lose some speed though, since the array is no longer contiguous and there is less of a chance that the whole array fits into cache .


----------



## cfleck (Mar 24, 2005)

May I ask what it is that you are doing that you are shooting for such cache use?


----------



## Viro (Mar 24, 2005)

I'm currently working with chaotic temporal neural networks, that have an internal state that's based on a modified Rossler system (for the chaos). It's pretty bleeding edge at the moment and I don't think there is any other research group working on it.

I'm doing a lot of numerical analysis of the neural nets I build and various other experiments to understand the models I'm working with. Most of them are written in MATLAB and this has been very slow. Currently, I'm in the process of re-implementing everything in C and thus far have seen a speed up in the region of 100x. I'm keen on having everything in the cache as far as possible since memory accesses are heavily penalized on most machines apart from those lovely Opterons that have an on die memory controller .

Objective-C comes in because I'd like to try new stuff . It's a great opportunity to learn the language and it's a chance to get familiar with Cocoa. Plus, if I make mistakes this new system, I've still got my old system written in MATLAB to validate it against so there's no worry that it'll impact my research too much. It also doesn't hurt that I'm on holiday at the moment and want something to do while my fiancee is away with her parents.

But this is all tangential to the topic at hand...


----------



## lurk (Mar 25, 2005)

In this case you have to do it the C way.  There is no support for anything related to primitives that is specific to Objective-C it all just relies on C for that.  So you just have to use the foo[1][4][3] style notation. You do not have to compute any offsets yourself though, the compiler should do it for you with the right declarations.


----------



## Aleran (Mar 27, 2005)

Damn, Neural Nets is the field I really want to get into, though I haven't even scratched the surface of the field as I've only read ch. 1 in a couple books on it I have and don't have the time to read more due to having my actual comp sci classes (I'll try to take a class on neural nets my senior year). 

Any way as per your question I would agree with Lurk, just define a C matrix as its easier than using an offset (not that its a big deal to use a offset, but its still easier)

double myMatrix[num_rows][num_cols];


----------



## Viro (Mar 28, 2005)

Problem with the C definitions given is that they're stack based. Works fine for most small arrays, but when you start using large arrays, you need them to be allocated from the heap. Hence, the need to malloc() or calloc() your arrays.

Anyhow, I'm currently using a 1D array, and simulating my own offsets. It's the way the GNU Scientific library does it, and it's the way most people in the field do it. Here is an example for anyone who might search the forums and wonder how to do the exact same thing .


```
/*Array2D.h*/
#ifndef __ARRAY_2D
#define __ARRAY_2D

typedef struct Array2D {
	double *data;
	int w, h;
}Array2D;

Array2D *a2d_create(int h, int w);
void a2d_destroy(Array2D *a);
double a2d_get(Array2D *a, int row, int col);
void a2d_set(Array2D *a, int row, int col, double d);
#endif

/*************Array2D.c*******************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

#include "array2d.h"


Array2D *a2d_create(int h, int w) {
	Array2D *a = (Array2D *)calloc(1, sizeof(*a));
	assert(a != NULL);
	
	a->w = w;
	a->h = h;
	a->data = (double *)calloc(w * h, sizeof(*a->data));
	assert(a->data != NULL);
	
	return a;
		
}

void a2d_destroy(Array2D *a) {

	if(a != NULL) {
		if(a->data != NULL)
			free(a->data);
		free(a);
	}
}

double a2d_get(Array2D *a, int y, int x) {
	assert(a != NULL);
	assert(x < a->w);
	assert(y < a->h);
	
	return *(a->data + x + y*a->w);
}

void a2d_set(Array2D *a, int y, int x, double d) {
	assert(a != NULL);
	assert(x < a->w);
	assert(y < a->h);
	
	*(a->data + x + y*a->w) = d;
}
```

Has a truck load of asserts sprinkled throughout the code. Doesn't affect runtime speed if you define NDEBUG. Not the most beautiful code in the world, but it works, and it's fast, and it's portable. Daddy like .


----------



## Viro (Apr 1, 2005)

For all my attempts at optimization in C, I've found that Java code runs just as fast. And it's a lot easier to work with, since arrays hold their own length, and bounds are checked. Given that Objective-C isn't faster than C, it makes me wonder if I should even bother with it.

Looks like I'll be sticking with Java for the rest of my code.


----------



## cfleck (Apr 1, 2005)

I'm curious.  How big are the arrays you are playing with?


----------



## Viro (Apr 1, 2005)

They range from 10,000 elements (in cache) to 10,000,000 elements (stresses memory subsystem). These are doubles.


----------



## Krevinek (Apr 5, 2005)

Well, you could always code a class or set of functions to do the offsets and the like for you. This way you can get contigous space (although the size of your elements is large enough that keeping them in cache is gonna be tough), and ease of use outside of the class. That is the way industry does it.


----------



## Viro (Apr 6, 2005)

That's exactly how I've done it. It is 6 posts up .


----------

