0

我有一个 3 元素枚举,它定义了三个上下文之一,例如红色、绿色或蓝色。此枚举用于具有数百万次迭代的循环中,例如像素很多。这些字段当前是一个int默认值。给定 R,G,B,R,G,B... 的所需生产顺序,我目前已采取措施检查该值当前是否为 B,从而将其分配给 R,否则增加该值。

private enum CHANNEL_CONTEXT {RED, GREEN, BLUE} //here is a sample enum

//here is a sample loop with the relevant construct
CHANNEL_CONTEXT current = CHANNEL_CONTEXT.RED;
while(condition)
{
    use current;
    //...
    if(current == CHANNEL_CONTEXT.BLUE)
        current = CHANNEL_CONTEXT.RED
    else
        current+=1;

}

有没有办法用单个操作包装一个 3 字段枚举,这样就不需要分支来确定是否该包装了。我知道模数(%)符合要求,但我的动机是基于性能的,而且我最多只能通过如此昂贵的操作来收支平衡(测试得到证实,但并非详尽无遗)。

为了正确看待我的议程,如果我有 256 个相关字段,我可以创建一个基于字节的枚举,并在不受惩罚和预期溢出的情况下递增。唉,我只有三个,我想不出一种方法来操作任何积分原语,以循环产生三个值的方式,使用轻量级 ALU 操作,(+,-,&,^,|,<<.. ETC)。我也无法想出一种无需临时使用此类操作即可交换位的方法,但是有一种很少实用但可行的方法。

有人可以指导我分配3个整数枚举值的方法,以便它们可以定期遍历,不需要分支,也不需要使用基于除法的运算符(如模数)?

4

1 回答 1

2

虽然听起来您不太可能击败x = (x + 1) % 3您,但您可以尝试使用映射表:

var map = new[]{1,2,0};
x = map[x];

您可能需要将其包装起来unsafe以删除对数组访问的边界检查。


如果您真的设置位操作而不考虑代码的可读性 - 您感兴趣的数字转换表足够小,可以为每个位手动构建然后组合。

真值表:

Source     Result
Bit2 Bit1  Bit2 Bit1
0    0     0    1
0    1     1    0
1    0     0    0
1    1     x    x 

如您所见,我们感兴趣的值仅产生 2 个非零位,因此结果表达式将非常简单 - 一种情况1用于较低位,另一种情况用于较高位(假设值永远不会超出范围 0-2(如果这是唯一的转换,这是安全的)。

var b1 = (x & 1) >> 0; // extract lower bit  0
var b2 = (x & 2) >> 1; // extract higher bit 1
// only care of cases when pair of bits results in 1 
var resultBit1 =  1 & (~b1 & ~b2); // 00 -> x1, other cases is 0
var resultBit2 = (1 & (b1 & ~b2)) << 1;               // 01 -> 1x, other cases is 0
x = resultBit1 | resultBit2;

或者将所有内容内联到一个不可读的行中:

x = 1 & ~(x | x >> 1) | 2 & (x & 1 & ~x >> 1) << 1;
于 2019-06-21T05:24:01.920 回答