Dynamically Multidimensional Arrays

T

tvashtar

Hi sorry if this isn't the best place to be asking this,
I need to create a vector-like container which is arbitrarily
multi-dimensional, the number of dimensions has to be determined at run
time. Is there a preexisting library to do this (I've tried MultiArray
in Boost but templating seems to require compile time dimension
setting) or will it come down to implementing one myself?
Thanks in advance,
Niall Glynn
 
V

Victor Bazarov

Hi sorry if this isn't the best place to be asking this,
I need to create a vector-like container which is arbitrarily
multi-dimensional, the number of dimensions has to be determined at
run time. Is there a preexisting library to do this (I've tried
MultiArray in Boost but templating seems to require compile time
dimension setting) or will it come down to implementing one myself?

Have you tried googling for it?

Some time ago "Nikki Locke" used to publish a link to "Available C++
Library FAQ" here, try searching the archives for it, there can be
some useful libraries there.

If I were to roll my own, I think it shouldn't be that hard. The
sizes of individual dimensions should be kept in a vector. The total
size would be the product of all vector elements. Allocate the data
storage based on this size and then overload the operator function
call to extract elements of sub-arrays.

template<class T>
class ArrayWithDynamicDimensions {
T *data;
vector<size_t> sizes;
public:
ArrayWithDynamicDimensions(size_t ...); // c-tor
T& operator()(size_t ...); // extractor
const T& operator()(size_t ...) const; // extractor
};

V
 
N

Noah Roberts

Victor said:
template<class T>
class ArrayWithDynamicDimensions {
T *data;

I would use a vector for this as well. No reason why it needs to be a
raw pointer and using a vector follows the RAII idiom.
 
B

benben

Victor said:
Have you tried googling for it?

Some time ago "Nikki Locke" used to publish a link to "Available C++
Library FAQ" here, try searching the archives for it, there can be
some useful libraries there.

If I were to roll my own, I think it shouldn't be that hard. The
sizes of individual dimensions should be kept in a vector. The total
size would be the product of all vector elements. Allocate the data
storage based on this size and then overload the operator function
call to extract elements of sub-arrays.

template<class T>
class ArrayWithDynamicDimensions {
T *data;
vector<size_t> sizes;
public:
ArrayWithDynamicDimensions(size_t ...); // c-tor
T& operator()(size_t ...); // extractor
const T& operator()(size_t ...) const; // extractor
};

V

Use of variadic constructor and extractor doesn't sound like a good idea
to me. After all, if OP can write a call to one of these variadic
functions he will have a pretty good idea about the number of dimensions
(which is to be determined by run time according to the OP.)

Just a thought.

Regards,
Ben
 
K

Kai-Uwe Bux

Hi sorry if this isn't the best place to be asking this,
I need to create a vector-like container which is arbitrarily
multi-dimensional, the number of dimensions has to be determined at run
time. Is there a preexisting library to do this (I've tried MultiArray
in Boost but templating seems to require compile time dimension
setting) or will it come down to implementing one myself?

What about something like this?


#include <cassert>
#include <numeric>
#include <functional>
#include <cstddef>
#include <vector>

template < typename T >
struct dyn_array {

typedef std::size_t size_type;
typedef T value_type;
typedef std::vector<size_type> subscript_type;

typedef T & reference;
typedef T const & const_reference;
typedef T * pointer;
typedef T const * const_pointer;

private:

subscript_type the_bounds;
pointer the_data;

template < typename Iter >
static
size_type product ( Iter from, Iter to ) {
return ( std::accumulate( from, to, 1,
std::multiplies<size_type>() ) );
}

size_type index ( subscript_type const & subscript ) {
assert( this->dimensions() == subscript.size() );
size_type result = 0;
for ( size_type i = 0; i < this->dimensions(); ++i ) {
assert( subscript < the_bounds );
result *= the_bounds;
result += subscript;
}
assert( result < this->size() );
return ( result );
}

public:

dyn_array ( subscript_type const & bounds )
: the_bounds ( bounds )
, the_data ( new T [ product( bounds.begin(), bounds.end() ) ] )
{}

~dyn_array ( void ) {
delete [] the_data;
}

reference
operator[] ( subscript_type const & subscript ) {
return ( the_data[ index( subscript ) ] );
}

const_reference
operator[] ( subscript_type const & subscript ) const {
return ( the_data[ index( subscript ) ] );
}

size_type dimensions ( void ) const {
return ( the_bounds.size() );
}

size_type size ( void ) const {
return ( product( the_bounds.begin(), the_bounds.end() ) );
}

};

#include <iostream>
#include <kubux/sequenceio>

int main ( void ) {
dyn_array<int>::subscript_type bounds;
bounds.push_back( 5 );
bounds.push_back( 12 );
dyn_array<int> M ( bounds );
dyn_array<int>::subscript_type subscript ( 2, 0 );
for ( subscript[0] = 0; subscript[0] < bounds[0]; ++ subscript[0] ) {
for ( subscript[1] = 0; subscript[1] < bounds[1]; ++ subscript[1] ) {
M[ subscript ] = 0;
}
}
}



Now, if you need to do linear algebra on those beasts, I would have a look
into the available linear algebra an numerics libraries, like Blitz++ or
MTL. They should provide some way of viewing an array as a tensor of sorts.


Best

Kai-Uwe Bux
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,678
Members
48,796
Latest member
Greg L.

Latest Threads

Top