初始化未知维度数组 [英] Initializing An Array of Unknown Dimensionality
问题描述
我很惊讶,我找不到这个问题。
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屋!