3

I have a matrix of values (stored as an array of values) and a vector with the matrix dimensions( dims[d0, d1, d2]). I need to build a string like that: "matA(j, k, l) = x;" where j, k, l are the indices of the matrix and x the value of the element. I need to write this for each value of the matrix and for matrices with 2 to n dimensions.

I have a problem isolating the base case and replicating it in a useful way. I did a version in a switch case with a case for each dimension and a number of for cycles equal to the number of dimensions:

for (unsigned int k=1; k<=(dims[2]); k++)
{
for (unsigned int j=1; j<=(dims[1]); j++)
{
for (unsigned int i=1; i<=(dims[0]); i++)
{
strs << matName << "(" << i << "," << j << ","<< k << ")="<< tmp[t]<< "; ";
.... 

but is not what I wanted.. Any idea for a more general case with a variable number of dimensions?

3
  • 1
    You want to look at template metaprogramming Commented Dec 13, 2013 at 10:21
  • Is the data stored in a one-dimensional array? Commented Dec 13, 2013 at 10:34
  • @interjay yes, the data is stored in a one dimensional array. Commented Dec 13, 2013 at 10:39

2 Answers 2

1

You need a separate worker function to recursively generate the series of indices and main function which operates on it.

For example something like

void worker(stringstream& strs, int[] dims, int dims_size, int step) {
  if (step < dims_size) {
    ... // Add dims[step] to stringstream. Another if may be necessary for
    ... // whether include `,` or not
    worker(strs, dims, dims_size, step + 1);
  } else {
    ... // Add cell value to stringstream.
  }
}

string create_matrix_string(int[] dims, int dims_size, int* matrix) {
  ... // Create stringstream, etc.
  strs << ... // Add matrix name etc.
  worker(strs, dims, dims_size, 0);
  strs << ... // Add ending `;` etc.
}

The main problem here is the value, since the dimension is not known during compilation. You can avoid that by encoding matrix in single-dimensional table (well, that's what C++ is doing anyway for static multidimensional tables) and call it using manually computed index, eg. i + i * j (for two-dimensional table). You can do it, again, by passing an accumulated value recursively and using it in final step (which I omitted in example above). And you probably have to pass two of them (running sum of polynomial components, and the i * j * k * ... * x product for indices from steps done so far.

So, the code above is far from completion (and cleanliness), but I hope the idea is clear.

Sign up to request clarification or add additional context in comments.

Comments

1

You can solve this, by doing i, j and k in a container of the size of dim[] - sample:

#include <iostream>
#include <vector>

template< typename Itr >
bool increment( std::vector< int >& ijk, Itr idim, int start )
{
    for( auto i = begin(ijk); i != end(ijk); ++i, ++idim )
    {
        if( ++*i <= *idim )
            return true;
        *i = start;
    }
    return false;
}

int main()
{
    using namespace std;
    int dim[] = { 5, 7, 2, 3 };
    const int start = 1;
    vector< int > ijk( sizeof(dim)/sizeof(*dim), start );
    for( bool inc_done = true; inc_done
        ; inc_done = increment( ijk, begin(dim), start ) )
    {
        // .. here make what you want to make with ijk
        cout << "(";
        bool first = true;
        for( auto j = begin(ijk); j != end(ijk); ++j )
        {
            if( !first )
                cout << ",";
            else
                first = false;
            cout << *j;
        }
        cout << ")= tmp[t] " << endl;
    }
    return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.