Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过将两个短路合并成一个整数,同时对它们进行运算_C++_Optimization_Bit Manipulation - Fatal编程技术网

C++ 通过将两个短路合并成一个整数,同时对它们进行运算

C++ 通过将两个短路合并成一个整数,同时对它们进行运算,c++,optimization,bit-manipulation,C++,Optimization,Bit Manipulation,我使用以下代码将两个有符号16位整数映射到无符号32位整数的上16位和下16位 inline uint32_t to_score(int16_t mg, int16_t eg) { return ((1u * mg) << 16 | (eg & 0xFFFF)); } inline int16_t extract_mg(uint32_t score) { return int16_t(score >> 16); } inline int16_t

我使用以下代码将两个有符号16位整数映射到无符号32位整数的上16位和下16位

inline uint32_t to_score(int16_t mg, int16_t eg) {
    return ((1u * mg) << 16 | (eg & 0xFFFF));
}

inline int16_t extract_mg(uint32_t score) {
    return int16_t(score >> 16);
}

inline int16_t extract_eg(uint32_t score) {
    return int16_t(score & 0xFFFF);
}
inlineuint32-to-score(int16-t-mg,int16-t-eg){
返回((1u*mg)>16);
}
内联int16提取(uint32分数){
返回int16(分数和0xFFFF);
}
我需要同时对
mg
eg
两部分执行各种计算,然后在函数末尾插入这两部分

据我所知,只要没有溢出,应该可以安全地将创建的两个
uint32_t
s添加到到分数中,然后提取
int16_t
s以找到单独计算的结果:即,如果我分别添加
mg
eg
的值,则会得到结果

如果
mg
eg
为负值,我不确定这个假设是否成立,或者这个方法是否可以用于减法、乘法和/或除法


我希望哪些操作能够正常运行?有没有其他方法可以表示两个可以快速加/减/乘的整数?

C++有符号整数是两个整数的补码,它正在C++20中标准化,实际上您可能已经假设了这一点

有些情况下,加减法是可行的,这些情况不会导致以下任何一种情况:例如溢出,mg溢出,mg改变符号

这种优化没有多大意义

如果有更大的数组,您可以尝试使用适当的SIMD指令对操作进行矢量化,如果您的平台可以通过启用编译器优化或使用内部函数来实现这些操作(_mm_adds_pi16可能是您需要的)


如果只有两个整数,只需逐个计算。

从低半部进位到高半部进位会有问题,但可以通过额外的操作来避免,如中所述

其中,在这种情况下,
H=0x80008000

作为另一种选择,可以通过两种添加方式完成,但需要优化提取/重组:

// low half addition, leaving upper half corrupted but it will be ignored
l = x + y
// high half addition, adding 0 to the bottom so no carry
h = x + (y & 0xFFFF0000)
// recombine
z = (l & 0xFFFF) | (h & 0xFFFF0000)
减法是加法的一个小变化


不幸的是,乘法关心的是绝对位的位置,所以值必须移动(移位)到它们的概念位置才能工作。尽管如此,仍然可以使用实际的SIMD,例如SSE2的
\u mm\u mullo\u epi16

例如&0xFFFF
,这似乎有些奇怪。它应该具有适当的长度,但它是有符号的,而不是要求无符号的。可以使用uint16\u t而不是int16\u t吗?我很确定int16_t不符合您希望以何种方式进行这些操作的“安全”条件。假设您关心可移植性。你可能会对亨利·s·沃伦的《黑客的喜悦》一书感兴趣,这本书涵盖了许多有趣的比特旋转技术。顺便说一下,这些伪并行计算风格有时被称为SWAR(寄存器内的SIMD),SWAR看起来很有趣,但我想它最终会比单独计算值慢。很高兴知道这个选项,只需减去假溢出:s=x+y;返回s-((x^y^s)和0x10000)
// low half addition, leaving upper half corrupted but it will be ignored
l = x + y
// high half addition, adding 0 to the bottom so no carry
h = x + (y & 0xFFFF0000)
// recombine
z = (l & 0xFFFF) | (h & 0xFFFF0000)