反转(小)排列

Invert a (small) permutation

我正在使用 OpenCL 的随机播放功能对 float3 向量进行排序,如下所示(忽略实际 4d 向量的最后一个分量):

uint4 mask = (uint4)(0,1,2,3);
mask.xyz = res.x < res.y ? (res.x >= res.z ? mask.yxz : mask.yzx) : (res.y >= res.z ? mask.xyz : mask.xzy);
float4 abcd = shuffle(res,mask);

然后我操作vector的每个分量abcd,想反转排序排列,如下:

uint4 inv_mask = ... // ???
res = shuffle(abcd,inv_mask); // Inverse the sorting permutation

如何有效地计算逆掩码?

你是说 uint4 invmask = (uint4)(3,3,3,3) - mask;

对于掩码 (0,3,1,2) 这给你 (3-0, 3-3, 3-1, 3-2) = (3,0,2,1)

可能性非常有限:

  1. x >= y >= z => mask.xyz = (0,1,2), inv_mask = (0,1,2)
  2. x >= z >= y => mask.xyz = (0,2,1), inv_mask = (0,2,1)
  3. y >= x >= z => mask.xyz = (1,0,2), inv_mask = (1,0,2)
  4. y >= z >= x => mask.xyz = (1,2,0), inv_mask = (2,0,1)
  5. z >= x >= y => mask.xyz = (2,0,1), inv_mask = (1,2,0)
  6. z >= y >= x => mask.xyz = (2,1,0), inv_mask = (2,1,0)

请注意,六个可能的排列中只有两个包含不止一个交换,因此其余 4 个排列自行反转。

计算出 mask 后,您可以使用以下代码获得 inv_mask:

inv_mask.xyz = mask.xyz == (int3)(1,2,0) ? (int3)(2,0,1) : (mask.xyz == (int3)(2,0,1) ? (int3)(1,2,0) : mask.xyz);