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
Printable View
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;
}
}
>> - 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 OO :)Code: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
Thanks guys, always very reliable!
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 likeQuote:
Originally 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.Quote:
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.Quote:
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 sure ;) ;)Quote:
Originally Posted by Codeplug
Yes that would be very nice.Quote:
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.
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 :rolleyes:[/edit2]
I think that both is needed:Quote:
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 :rolleyes:
>>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.