通过将它们组合成一个整数来一次处理两个短裤

时间:2019-01-03 19:47:25

标签: c++ optimization bit-manipulation

我正在使用以下代码将两个有符号的16位整数映射到一个无符号的32位整数的高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);
}

我需要同时在mgeg部分上执行各种计算,然后再在函数末尾对这两个部分进行插值。

据我了解,只要没有溢出,添加两个uint32_t创建的to_score并提取int16_t来查找结果应该是安全的各个计算的结果:即如果我分别添加mgeg的值的结果。

我不确定mgeg是否为负,或者是否可以将该方法用于减法,乘法和/或除法。

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

2 个答案:

答案 0 :(得分:2)

从低半部分到高半部分的进位会有问题,但是可以通过额外的操作来避免,例如chessprogramming.org/SIMD_and_SWAR_Techniques

CREATE OR REPLACE FUNCTION cdate(rhs anyelement) RETURNS timestamp without time zone AS
$BODY$
DECLARE retval timestamp without time zone;
BEGIN
IF pg_typeof($1)=ANY ('{int2,int,int8,real,float8,numeric}'::regtype[]) THEN
    retval:=DATE_TRUNC('second',DATE('1899-12-30')+$1*INTERVAL '1 day');
ELSE
    IF pg_typeof($1)=ANY ('{timestamp,date}'::regtype[]) THEN
        retval:=$1::timestamp without time zone;
    END IF;
END IF;
RETURN retval;
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE STRICT;

在这种情况下为z = ((x &~H) + (y &~H)) ^ ((x ^ y) & H)

作为另一种选择,可以添加两次,但可以优化提取/重组:

H = 0x80008000

减法是加法的微小变化。

不幸的是,乘法关心的是绝对位的位置,因此必须将值移动(移位)到其名义位置才能起作用。 Actual 仍然可以使用SIMD,例如带有SSE2的// 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)

答案 1 :(得分:1)

C ++有符号整数是二进制补码,它正在用C ++ 20进行标准化,在实践中您可能已经假设了。

某些加法和减法会起作用,而不会引起以下任何一种情况:例如溢出,mg溢出,mg改变符号。

优化没有多大意义。

如果有更大的数组,则可以尝试使用正确的SIMD指令对操作进行矢量化,如果通过启用编译器优化或使用内在函数(_mm_adds_pi16可能是您需要的功能)可在您的平台上使用它们。

如果只有两个整数,则一一计算。