初始化未知维度数组 [英] Initializing An Array of Unknown Dimensionality

查看:118
本文介绍了初始化未知维度数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很惊讶,我找不到这个问题。

I was surprised that I couldn't find this question existing. I've tried to generalize it (with some nice untested code) to something everyone can benefit from.

假设我有一个多维的

Suppose I have a multidimensional Point:

template <int dims> class Point { public: double data[dims]; };

现在我创建了一个多维数组:

Now I create a multidimensional array of them:

 template <int dims> void foobar(int count0, ...) {
    //Using variadic function.  Could also use variadic templates in C++ (arguably better)
    int counts[dims], total_count=count0; counts[0]=count0;
    va_list args; va_start(args,count0);
    for (int i=1;i<dims;++i) {
        int count = va_arg(args,int);
        counts[i] = count;
        total_count *= count;
    }
    va_end(args);

    Point<dims>* array = new Point<dims>[total_count];

    //...
}

请参阅数组是一个未知维度的多维数组,以1D数组表示。

As you can see, array is a multidimensional array of unknown dimensionality, represented in a 1D array.

我的问题:如何清洁地将这个数组初始化到多维网格点?

这里是我想要的1,2和3维的示例行为。显然,我不想为每一个可能的维度写我想使用!目标是概括

Here's the example behavior I want in 1, 2, and 3 dimensions. Obviously, I don't want to write this for every possible dimensionality I might want to use! The goal is to generalize this.

//Example: dim==1
for (int x=0; x<counts[0]; ++x) {
    Point<1>& point = array[x];
    point.data[0] = (x+0.5) / (double)counts[0];
}

//Example: dim==2
for (int y=0; y<counts[1]; ++y) {
    for (int x=0; x<counts[0]; ++x) {
        Point<2>& point = array[y*counts[0]+x];
        point.data[0] = (x+0.5) / (double)counts[0];
        point.data[1] = (y+0.5) / (double)counts[1];
    }
}

//Example: dim==3
for (int z=0; z<counts[2]; ++z) {
    for (int y=0; y<counts[1]; ++y) {
        for (int x=0; x<counts[0]; ++x) {
            Point<3>& point = array[(z*counts[1]+y)*counts[0]+x];
            point.data[0] = (x+0.5) / (double)counts[0];
            point.data[1] = (y+0.5) / (double)counts[1];
            point.data[2] = (z+0.5) / (double)counts[2];
        }
    }
}

注意:我想出了一些讨厌的方法,并且他们不愉快和缓慢。特别是,我想避免递归,如果可能,因为这将被调用高维小型数据集很频繁。
注意:在C中有明显的并行,所以C或C ++都很好。 C ++ 11首选。

Note: I've come up with a few nasty ways, and they're inelegant and slow. Especially, I want to avoid recursion, if possible, since this will be called on high-dimensional smallish datasets quite frequently. Note: There are obvious parallels in C, so either C or C++ is fine. C++11 preferred.

推荐答案

X,Y,Z 到扁平数组(F),我们有以下等式:

Going from X,Y,Z to the flattened array (F) we have the following equation

F=(Z*DimY+y)*DimX+X

F=Z*DimY*DimX+Y*DimX+X

X = F % DimX
Y = F % DimX*DimY/DimX
Z = F % DimX*DimY*DimZ/DimX*DimY



< 3,Y = 1,X = 2将在 3 * 3 * 5 + 1 * 5 + 2 = 45 + 5 + 2 = 52

in a 7 x 3 x 5 array, Z=3, Y=1, X=2 would be at 3*3*5 + 1*5 + 2= 45+5+2=52

X = `52` % 5 = 2
Y = `52` % (5 * 3) / 5 = 7 / 5 = 1
Z = `52` % (7 * 5 * 3)/15 = 52/15 = 3



数组,Z = 4,Y = 2,X = 3将在 4 * 3 * 5 + 2 * 5 + 3 = 60 + 10 + 3 = 73

in a 7 x 3 x 5 array, Z=4, Y=2, X=3 would be at 4*3*5 + 2*5 + 3= 60+10+3=73

X = `73` % 5 = 3
Y = `73` % (5 * 3) / 5 = 13 / 5 = 2
Z = `73` % (7 * 5 * 3)/15 = 73/15 = 4

数组中的累积乘积, mult {1,X,X * Y,X * Y * Z,...} 和数组中的所有点, val

If we keep the cumulative products in an array, mult { 1, X, X*Y, X*Y*Z, ...} and all points in an array, val

指向平面数组:

F=sum(mult[i]*val[i]);

平面数组到点:

i[0]=F%mult[1]/mult[0];
i[1]=F%mult[2]/mult[1];
...

然后我们可以遍历F从索引到平面数组所有点:X,Y,...如上所述,并在通用循环中进行初始化:

We can then iterate over F (the flat array) , reverse engineer from the index into the flat array all points: X,Y,... as above and do the initialization you want in a generic loop:

给定 mult as mult [0] = 1; mult [d + 1] = mult [d] * count [d];

for (int i = 0; i < total_count; ++i) {
    for (int d=0; d < dims; ++d) {
      int dim=(i%mult[d+1])/mult[d];
      point.data[d] = (dim+0.5) / (double)counts[d];
  }
}

这篇关于初始化未知维度数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆