我有一个以小端序排列的交错有符号 24 位整数(复数)数组,我想将其转换为浮点数或双精度数的复杂数组。通过交错,我的意思是:
R1 R2 R3 I1 I2 I3 R4 R5 R6 I4 I5 I6 . . .
其中每个项目是一个 8 位字节,每三个一起是一个 24 位整数,其中 R = 实数,I = 虚数。
在 C# 中执行此操作的最有效方法是什么?代码必须运行很多次,所以我试图尽可能地挤出最后一个循环。我希望有比蛮力转换或强制转换更有效的方法。
如果有帮助的话,我不介意在这种情况下使用不安全的代码。
这是基线的蛮力方法,注释掉了对的第二个数字,暂时忽略了符号处理,以简化 IDL:
class Program
{
const int Size = 10000000;
static void Main(string[] args)
{
//
// Array of little-endian 24-bit complex ints
// (least significant byte first)
//
byte[] buf = new byte[3 * 2 * Size];
float[] real = new float[Size];
//float[] imag = new float[Size];
//
// The brute-force way
//
int j = 0;
Stopwatch timer = new Stopwatch();
timer.Start();
for (int i = 0; i < Size; i++)
{
real[i] = (float)(buf[j] | (buf[j + 1] << 8) | (buf[j + 2] << 16));
j += 3;
// imag[i] = (float)(buf[j] | (buf[j + 1] << 8) | (buf[j + 2] << 16));
j += 3;
}
timer.Stop();
Console.WriteLine("result = " +
(float)(timer.ElapsedMilliseconds * 1000.0f / Size) +
" microseconds per complex number");
Console.ReadLine();
}
}
和相关的 IDL:
IL_0024: ldc.i4.0
IL_0025: stloc.s i
IL_0027: br.s IL_0050
IL_0029: ldloc.1
IL_002a: ldloc.s i
IL_002c: ldloc.0
IL_002d: ldloc.2
IL_002e: ldelem.u1
IL_002f: ldloc.0
IL_0030: ldloc.2
IL_0031: ldc.i4.1
IL_0032: add
IL_0033: ldelem.u1
IL_0034: ldc.i4.8
IL_0035: shl
IL_0036: or
IL_0037: ldloc.0
IL_0038: ldloc.2
IL_0039: ldc.i4.2
IL_003a: add
IL_003b: ldelem.u1
IL_003c: ldc.i4.s 16
IL_003e: shl
IL_003f: or
IL_0040: conv.r4
IL_0041: stelem.r4
IL_0042: ldloc.2
IL_0043: ldc.i4.3
IL_0044: add
IL_0045: stloc.2
IL_0046: ldloc.2
IL_0047: ldc.i4.3
IL_0048: add
IL_0049: stloc.2
IL_004a: ldloc.s i
IL_004c: ldc.i4.1
IL_004d: add
IL_004e: stloc.s i
IL_0050: ldloc.s i
IL_0052: ldc.i4 0x989680
IL_0057: blt.s IL_0029