Somone's SO question: "Is there an existing library for dynamically-determineddimensional array in c

  • Thread starter Alf P. Steinbach
  • Start date
A

Alf P. Steinbach

This question was closed as off-topic on Stack Overflow.
The OP was anonymous.

http://stackoverflow.com/questions/...dynamically-determined-dimensional-array-in-c
I am looking for a good existing library for dynamically-determined dimensional
array in c++. Blitz++ and other similars provide array with fixed dimensionality,
like the following

int m = 2, n = 3; p = 4;
blitz::Array<double, 3> a(m, n, p); // A 3D array

What I am looking for is

int d = 3;
Array<double> a(d, m, n, p); // An array of 3D

where the array's dimensionality d and size of all the dimensions (here m, n, p)
are all determined dynamically.



I don't know of any such library, and I wouldn't advice using such a
class since it incurs some overhead and opens the door for bugs, but
here is a working sketch of how you can do it yourself:


Code:
#include <assert.h>             // assert
#include <vector>               // std::vector
#include <initializer_list>     // std::initializer_list
#include <stddef.h>             // ptrdiff_t
#include <iterator>             // std::begin, std::end

namespace my{
using std::vector;
using std::initializer_list;

typedef ptrdiff_t Size;
typedef Size Index;

template< class Item >
auto item( Index const i, initializer_list<Item> const& items )
-> Item const
{ return *(items.begin() + i); }

// Needs to be more elaborate for general implementation.
template< class Container >
auto size( Container const& c )
-> Size
{ return end( c ) - begin( c ); }

typedef double Item;
class Array
{
private:
vector<Size>    extents_;
vector<Item>    items_;

auto n_items() const
-> Size
{
Size result = 1;
for( auto const n : extents_ ) { result *= n; }
return result;
}

auto index_for( initializer_list<int> const& indices ) const
-> Index
{
assert( indices.size() == extents_.size() );
Size sub_array_size = 1;
Index result = 0;
for( Index i = 0;  i < size( indices ); ++i )
{
result += item( i, indices )*sub_array_size;
sub_array_size *= extents_[i];
}
return result;
}

public:
auto n_dimensions() const
-> int
{ return extents_.size(); }

auto extent( Index const i ) const
-> Size
{ return extents_[i]; }

template< class... Int >
auto operator()( Int const... indices )
-> double&
{ return items_[ index_for({indices...}) ]; }

template< class... Int >
auto operator()( Int const... indices ) const
-> double const&
{ return items_[ index_for({indices...}) ]; }

template< class... Int >
Array( Int const... extents )
: extents_( { extents... } )
{ items_.resize( n_items() ); }
};
}  // namespace my

#include <iostream>
#include <iomanip>
using namespace std;

auto main() -> int
{
my::Array a( 3, 3, 3 );
cout << a.n_dimensions() << " dimensions" << endl;

a( 1, 2, 1) = 3.14;
a( 2, 2, 1) = 3.15;
for( int z = 0;  z < 3;  ++z )
{
for( int y = 0;  y < 3;  ++y )
{
for( int x = 0;  x < 3;  ++x )
{
cout << setw( 5 ) << a( x, y, z );
}
cout << endl;
}
cout << endl;
}

cout << a( 1, 2, 1) << endl;
}


Cheers & hth.,

- Alf
 
L

Larry Evans

This question was closed as off-topic on Stack Overflow.
The OP was anonymous.

http://stackoverflow.com/questions/...dynamically-determined-dimensional-array-in-c

I am looking for a good existing library for dynamically-determined
dimensional
array in c++. Blitz++ and other similars provide array with fixed
dimensionality,
like the following

int m = 2, n = 3; p = 4;
blitz::Array<double, 3> a(m, n, p); // A 3D array

What I am looking for is

int d = 3;
Array<double> a(d, m, n, p); // An array of 3D

where the array's dimensionality d and size of all the dimensions
(here m, n, p)
are all determined dynamically.



I don't know of any such library, and I wouldn't advice using such a
class since it incurs some overhead and opens the door for bugs, but
here is a working sketch of how you can do it yourself:


Code:
#include <assert.h>             // assert
#include <vector>               // std::vector
#include <initializer_list>     // std::initializer_list
#include <stddef.h>             // ptrdiff_t
#include <iterator>             // std::begin, std::end

namespace my{
using std::vector;
using std::initializer_list;

typedef ptrdiff_t Size;
typedef Size Index;

template< class Item >
auto item( Index const i, initializer_list<Item> const& items )
-> Item const
{ return *(items.begin() + i); }

// Needs to be more elaborate for general implementation.
template< class Container >
auto size( Container const& c )
-> Size
{ return end( c ) - begin( c ); }

typedef double Item;
class Array
{
private:
vector<Size>    extents_;
vector<Item>    items_;

auto n_items() const
-> Size
{
Size result = 1;
for( auto const n : extents_ ) { result *= n; }
return result;
}

auto index_for( initializer_list<int> const& indices ) const
-> Index
{
assert( indices.size() == extents_.size() );
Size sub_array_size = 1;
Index result = 0;
for( Index i = 0;  i < size( indices ); ++i )
{
result += item( i, indices )*sub_array_size;
sub_array_size *= extents_[i];
}
return result;
}

public:
auto n_dimensions() const
-> int
{ return extents_.size(); }

auto extent( Index const i ) const
-> Size
{ return extents_[i]; }

template< class... Int >
auto operator()( Int const... indices )
-> double&
{ return items_[ index_for({indices...}) ]; }

template< class... Int >
auto operator()( Int const... indices ) const
-> double const&
{ return items_[ index_for({indices...}) ]; }

template< class... Int >
Array( Int const... extents )
: extents_( { extents... } )
{ items_.resize( n_items() ); }
};
}  // namespace my

#include <iostream>
#include <iomanip>
using namespace std;

auto main() -> int
{
my::Array a( 3, 3, 3 );
cout << a.n_dimensions() << " dimensions" << endl;

a( 1, 2, 1) = 3.14;
a( 2, 2, 1) = 3.15;
for( int z = 0;  z < 3;  ++z )
{
for( int y = 0;  y < 3;  ++y )
{
for( int x = 0;  x < 3;  ++x )
{
cout << setw( 5 ) << a( x, y, z );
}
cout << endl;
}
cout << endl;
}

cout << a( 1, 2, 1) << endl;
}


Cheers & hth.,

- Alf

Hi Alf,

The following code:

http://svn.boost.org/svn/boost/sandbox/variadic_templates/sandbox/array_dyn/array_dyn.hpp

has comments that appear to satisfy that need.

-regards,
Larry
 
Joined
Jun 12, 2020
Messages
29
Reaction score
2
To create a dynamically determined dimensional array in C++, you can use the following approach. The code below demonstrates how to allocate and manage a 3D array of floats, where the dimensions are specified at runtime.
C:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// Fonction pour allouer un tableau 3D de floats
float*** make_3d_array(int nx, int ny, int nz) {
    float*** arr = (float ***) malloc(nx * sizeof(float**));
    if (arr == NULL) {
        fprintf(stderr, "Erreur d'allocation de mémoire pour le tableau 3D\n");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < nx; i++) {
        arr[i] = (float **) malloc(ny * sizeof(float*));
        if (arr[i] == NULL) {
            fprintf(stderr, "Erreur d'allocation de mémoire pour le tableau 2D\n");
            exit(EXIT_FAILURE);
        }

        arr[i][0] = (float *) malloc(ny * nz * sizeof(float)); // Allocation d'un bloc pour chaque ligne
        if (arr[i][0] == NULL) {
            fprintf(stderr, "Erreur d'allocation de mémoire pour les éléments du tableau\n");
            exit(EXIT_FAILURE);
        }

        // Initialisation des pointeurs de ligne
        for (int j = 1; j < ny; j++) {
            arr[i][j] = arr[i][0] + j * nz; // Pointer vers le bon emplacement
        }
    }

    return arr;
}

// Fonction pour libérer la mémoire allouée pour le tableau 3D
void free_3d_array(float*** arr, int nx, int ny) {
    for (int i = 0; i < nx; i++) {
        free(arr[i][0]); // Libération du bloc de mémoire pour les éléments
        free(arr[i]); // Libération de chaque tableau 2D
    }
    free(arr); // Libération du tableau 3D
}

int main() {
    int N1 = 10, N2 = 20, N3 = 5;

    // Allocation du tableau 3D
    float ***ran = make_3d_array(N1, N2, N3);

    // Initialisation du générateur de nombres aléatoires
    srand(time(NULL));

    // Remplissage du tableau avec des nombres aléatoires
    for (int i = 0; i < N1; i++) {
        for (int j = 0; j < N2; j++) {
            for (int k = 0; k < N3; k++) {
                ran[i][j][k] = ((float)rand() / (float)(RAND_MAX));
            }
        }
    }

    // Affichage des valeurs
    for (int i = 0; i < N1; i++) {
        for (int j = 0; j < N2; j++) {
            for (int k = 0; k < N3; k++) {
                printf("A[%d][%d][%d] = %f \n", i, j, k, ran[i][j][k]);
            }
        }
    }

    // Libération de la mémoire
    free_3d_array(ran, N1, N2);

    return 0;
}
This code defines a function make_3d_array to allocate a 3D array of floats based on the dimensions provided at runtime. It also includes a function free_3d_array to properly deallocate the memory once it is no longer needed. The main function demonstrates how to use these functions to create a 3D array, fill it with random values, and print those values to the console.
 

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

Forum statistics

Threads
474,278
Messages
2,571,180
Members
48,780
Latest member
altimist-patrick

Latest Threads

Top