A while ago I read a thread about faster memory allocation for matrices which uses new operator efficiently and not through loop. I can't find that thread now, but if someone remember how it is done please post code here.
Thank you
A while ago I read a thread about faster memory allocation for matrices which uses new operator efficiently and not through loop. I can't find that thread now, but if someone remember how it is done please post code here.
Thank you
- The returned memory is uninitialized.Code:template <typename T> inline T** alloc_matrix(size_t rows, size_t columns) { return (T**)new char[rows * columns * sizeof(T)]; }//alloc_matrix template <typename T> inline void free_matrix(T **m) { delete[] (char*)m; }//free_matrix int **matrix = alloc_matrix<int>(10, 10); ... free_matrix(matrix);
- If T is an object type, constructors and destructors are not called.
gg
There are quite a few ways of going about this. What implementation you use depends on how you intend to index the matrix. Here's one way:
Code:#include <iomanip> #include <iostream> template <typename T> class matrix { public: matrix ( int m, int n ) : rows ( m ), cols ( n ) { data = new T[rows * cols]; } ~matrix() { delete [] data; } T& operator() ( int i, int j ) { return data[cols * i + j]; } private: int rows, cols; T *data; }; int main() { matrix<int> m ( 2, 5 ); for ( int i = 0; i < 2; i++ ) { for ( int j = 0; j < 5; j++ ) m ( i, j ) = ( i + 1 ) * ( j + 1 ); } for ( int i = 0; i < 2; i++ ) { for ( int j = 0; j < 5; j++ ) std::cout<< std::left << std::setw ( 3 ) << m ( i, j ); std::cout<<std::endl; } }
My best code is written with the delete key.
>> - If T is an object type, constructors and destructors are not called.
Let me fix that....
Which makes it near identical to Prelude's code, just not as OOCode:template <typename T> inline T** alloc_matrix(size_t rows, size_t columns) { return (T**)new T[rows * columns]; }//alloc_matrix template <typename T> inline void free_matrix(T **m) { delete[] (T*)m; }//free_matrix
gg
Just to be tedious and pedantic, while you allocate the correct number of T's you then store the location of the first T in a pointer to a pointer. This aint even vaguely correct and why innocent looking c-style casts should be shunned for reinterpret_cast. Prelude's method, where you just break down and do the math to index in two dimentions is the way to go. What I think the OP was asking for, but is somewhat of a waste is something likeOriginally Posted by Codeplug
Now m[y][x] type syntax will work as expected, and it's clear that what we really have is just a lookup table for multiplication m[y] = base + y*colCode:template <class T> T ** new_p2p_arr(int col, int row) { T **rowtbl = new T*[row]; rowtbl[0] = new T[row*col]; for(int i=1;i<row;i++) { rowtbl[i] = rowtbl[0] + i*col; } return rowtbl; }
There's no gain in using reinterpret_cast over a C cast in this situation.
However, my original thoughts of using [][] to achieve an offset into the allocated array is indeed incorrect. [][] will perform two dereferences which doesn't work on a T array.
I was totaly thinking [][] was identical to "data[cols * i + j]" - don't ask me why.
Can I blame it on the beer? Sure I can.
(Let me go check my other posts....)
gg
If you never use the c-style casts then to do something like this you would need to use reinterpret_cast, rather than static_cast. So I guess I should say always use static_cast and if the compiler complains it probably has a point.Originally Posted by Codeplug
Yeah it's confusing as all get out. int *p and int a[3] act the same, p=a makes sense p[x] == a[x] works, so why don't int **p and int a[3][3] act the same. Really would be nice to have typedef's that could represent say int[30] then you could clealy say pointer to first of an unknown number of consecutive int[30]'s. Ah well, beer, now there's a good idea.I was totaly thinking [][] was identical to "data[cols * i + j]" - don't ask me why.
Can I blame it on the beer? Sure I can.
(Let me go check my other posts....)
gg
Confunded T** with T[][]... Beer for sureOriginally Posted by Codeplug
Yes that would be very nice.Originally Posted by grib
MSDN C Language Reference: Interpreting More Complex DeclaratorsCode:#include <cstdio> #include <cstdlib> using namespace std; int main(void) { typedef int INT_ARRAY_30[30]; INT_ARRAY_30* foo; /* Declare a pointer to an array 30 of ints. */ int (*bar)[30]; /* Equivalent to foo without the use of typedef synonym. */ foo = new INT_ARRAY_30[20]; /* C++ style allocation */ bar = (int (*)[30]) malloc(20 * sizeof(*bar)); /* C style allocation with ugly cast. */ for (int x = 0;x < 20;x++) { for (int y = 0;y < 30;y++) { foo[x][y] = y * x; bar[x][y] = y + x; printf("foo/bar[%d][%d] = %d, %d \n", x, y, foo[x][y], bar[x][y]); } } delete [] foo; free(bar); getchar(); return 0; }
Well I'm glad because of this discussion, but I've found what I searched for and that is Sang-drax's code:
I found Prelude's code very useful for what I'm doing right now!Code://Allocate the actual data int* rawData = new int[rows*cols]; //Allocate pointers to the data int** data = new int*[rows]; //Point the pointers into the data for (int i=0; i < rows; ++i){ data[i] = &rawData[cols*i];
Anyway I have one more question:
Maybe some of you work with MATLAB.
In MATLAB if you want to declare 2d array (matrix) say 3x3 you simply type this:
A=[1 2 3;4 5 6;7 8 9];
and that's it you have 3x3 matrix.
Is this possible using string processing or what?
I don't have that much knowledge to write program that will doing the same thing.
I wonder how memory is allocated here. Maybe whole line is placet to some buffer first and then counted for elementes...?
If someone knows a little about this please explain!
Thanks
>Is this possible using string processing or what?
Are you asking how MATLAB does it or how can you get similar functionality? I would imagine that MATLAB does something similar to the allocation loop:
>I wonder how memory is allocated here.Code:// Pseudo-implementation with s == 1 2 3;4 5 6;7 8 9]; int span; int ndim = count_sep ( s, span ); int **mat = new int*[ndim]; for ( int i = 0; i < ndim; i++ ) { mat[i] = new int[span]; s = fill_span ( s, mat[i], span ); }
It really depends on how the thing is implemented internally. MATLAB could use a matrix buffer for all matrices and then allocate "just enough" memory after parsing the string, it could build a list of vectors, it could build a vector of vectors dynamically, it could use a static vector of vectors, we just don't know unless you can see the source. But as with everything, there are naive methods and there are methods that optimize for space or time or both.
My best code is written with the delete key.
If you do this, then I imagine freeing the matrix would be different as well:Code://Allocate the actual data int* rawData = new int[rows*cols]; //Allocate pointers to the data int** data = new int*[rows]; //Point the pointers into the data for (int i=0; i < rows; ++i){ data[i] = &rawData[cols*i];
Rather simpler I say, if it works.Code:delete[] rawData; or delete[] data[0];
**EDIT**
[edit2: snip]Oops, I thought MATLAB was a library [/edit2]
Last edited by Hunter2; 11-15-2004 at 05:58 PM.
Just Google It. √
(\ /)
( . .)
c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.
I think that both is needed:Originally Posted by Hunter2
The line delete [] data[0] look suspicious to me, I'm not sure that it will work the job.Code:delete [] data; delete [] rawData;
>>delete [] data;
Oops yeah, forgot you have to delete the pointer array too
>>The line delete [] data[0] look suspicious to me
I agree, looks fishy, but data[0] does point to the first element of the array you've allocated.
Just Google It. √
(\ /)
( . .)
c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.