给定一个由小整数组成的N维向量,有没有一种简单的方法将其与一个大整数一对一地映射?
比如说,我们有一个3维向量空间。我们能否使用一个整数(int48)y来表示向量X=[(int16)x1,(int16)x2,(int16)x3]?显然答案是“可以”。但问题是:“如何以最快的方式进行这个操作,并且它的反操作是什么?”
这个新的一维空间会拥有一些非常特殊和有用的属性吗?
;]
- Xavier Ho为了更具体地说明,如果您有一个由8位数字组成的三维向量,就像这样:
uint8_t vector[3] = { 1, 2, 3 };
uint32_t all = (vector[0] << 16) | (vector[1] << 8) | vector[2];
printf("the vector was packed into %06x", (unsigned int) all);
the vector was packed into 010203
uint8_t v2[3];
v2[0] = (all >> 16) & 0xff;
v2[1] = (all >> 8) & 0xff;
v2[2] = all & 0xff;
1 2 5 | draw along the edge of the square this way
4 3 6 v
8 7
1
开始计数,并且只考虑正数值;对于整数,你可以绕着原点螺旋前进。为了扩展 Rex Kerr的通用形式,在C语言中,您可以这样打包数字:
X = e[n];
X *= MAX_E[n-1] + 1;
X += e[n-1];
/* ... */
X *= MAX_E[0] + 1;
X += e[0];
然后使用以下代码进行解压:
e[0] = X % (MAX_E[0] + 1);
X /= (MAX_E[0] + 1);
e[1] = X % (MAX_E[1] + 1);
X /= (MAX_E[1] + 1);
/* ... */
e[n] = X;
(其中MAX_E[n]
是e[n]
可能具有的最大值)。请注意,这些最大值很可能是常数,并且对于每个e
可能相同,这将使事情变得简单一些。
其他答案中给出的移位/掩码实现是这个问题的一般化,适用于MAX_E + 1
值为2的幂的情况(因此可以使用移位进行乘法和除法,使用按位或进行加法,使用按位与进行模数运算)。
我在没有时间检查细节的情况下编写这篇文章,但我怀疑最好的方法是使用模算术来表示您的长整数,使用k个互质的不同整数。然后可以使用中国剩余定理重构原始整数。很抱歉这有点草率,但希望能有所帮助。
#include <stdint.h> // for uint8_t
long x;
uint8_t * p = &x;
或者
union X {
long L;
uint8_t A[sizeof(long)/sizeof(uint8_t)];
};
如果您不关心字节序,则可以使用该方法。根据我的经验,编译器使用联合会生成更好的代码,因为它不会像快速设置“您获取了此地址,因此我必须将其保留在RAM中”的规则一样。如果您尝试使用编译器无法优化的内容索引数组,则会触发这些规则。
如果您关心字节序,则需要进行掩码和移位操作。
有一些完全不可移植的方法可以使用打包联合和直接访问内存来使其真正快速。你真的需要这种速度是可疑的。使用移位和掩码的方法对于大多数目的来说应该已经足够快了。如果不行,考虑使用专门的处理器,如GPU,其中向量支持得到了优化(并行)。
这种天真的存储方式除了我能预见到的可以同时对三个坐标执行一些计算(加、减、逻辑位运算)以外,没有任何有用的属性,只要你只使用正整数并且在加法和减法中不会溢出。
你最好确信你不会溢出(或者不会因为减法而变成负数),否则向量将变成垃圾。
=]
- Xavier Ho