给定一系列整数,将数组从中间分割成两个短数组的最有效方法是什么?

时间:2011-09-26 02:21:16

标签: c++ c arrays algorithm

令我印象深刻的是必须有一个聪明的方法来做到这一点。这不适用于家庭作业,工作或任何事情。我只是用一种有数据交错的文件格式来徘徊。

所以,在通用的C / C ++中,(或其他)给出一些数组

int x[] = ...

有一种巧妙的方法将它分成两个短阵列

short sa1[], sa2[]

使得int数组在中间分割

x[i] = 1111111111111111 1111111111111111
             sa1[i]         sa2[i]

编辑:对不起,如果没有说得好。对于int数组的每个第i个元素,最左边的16位成为一个数组的第i个元素,最右边的16位成为第二个数组的第i个元素。

所以给出

x[i] = 0001111111111111 1111111100011111

然后

sa1[i] = 0001111111111111
sa2[i] = 1111111100011111

我正在寻找不明显的答案,这些答案不会遍历每个元素,并且会移动并屏蔽每个元素。这很简单:)

3 个答案:

答案 0 :(得分:5)

有很多方法可以做到这一点:

假设:

  1. short是16位。
  2. int是32位。
  3. 方法1 :(一个简单的循环)

    for (int i = 0; i < size; i++){
        int tmp = x[i];
        sa1[i] = (tmp      ) & 0xffff;
        sa2[i] = (tmp >> 16) & 0xffff;
    }
    

    方法2:SSE2

    for (int i = 0; i < size / 8; i++){
        __m128i a0 = ((__m128i*)x)[2*i + 0];
        __m128i a1 = ((__m128i*)x)[2*i + 1];
    
        a0 = _mm_shufflelo_epi16(a0,216);
        a1 = _mm_shufflelo_epi16(a1,216);
        a0 = _mm_shufflehi_epi16(a0,216);
        a1 = _mm_shufflehi_epi16(a1,216);
        a0 = _mm_shuffle_epi32(a0,216);
        a1 = _mm_shuffle_epi32(a1,216);
    
        ((__m128i*)sa1)[i] = _mm_unpacklo_epi64(a0,a1);
        ((__m128i*)sa2)[i] = _mm_unpackhi_epi64(a0,a1);
    }
    

    如果循环进一步展开,最后一个示例非常快。如果这可以击败所有字节操作库,我不会感到惊讶。

    但是,它有以下限制:

    1. 数据必须对齐到16个字节。
    2. 迭代次数必须可以被8整除。
    3. 需要SSE2。
    4. 前两个可以通过清理代码解决。这很麻烦,但如果你真的想要表现,那可能是值得的。

      编辑:

      是的,这违反了严格别名,但如果不这样做,几乎不可能使用SSE内在函数。

答案 1 :(得分:3)

int在您的平台上只有两个short,您可以reinterpret_castint数组short转换为int数组,然后取偶数/奇数元素。

但是请注意,shortshort的大小无法保证(intint之外的大小不能超过short)。例如,short可能等于int,或者可能超过2 {{1}} s。即使{{1}}的绝对大小也不能得到保证(典型大小为4和8字节)。

对于真正可移植的解决方案,您可能最好将您要解释的文件的确切格式映射到bit fields

答案 2 :(得分:0)

你需要知道x的长度,但你可以做类似的事情:

#include <stdio.h>

int main(int argc, char * argv[])
{
    int x[] = {1, 2, 3, 4, 5, 6};
    int xlen = 6;

    short * a = &x[0];
    short * b = &x[xlen/2];

    printf("%d\n%d\n", a[0], b[0]);
}

a指向原始int数组的开头,并允许您以short增量进行索引。与b相同,但它从原始int数组的中间开始。

我会称之为聪明,但是你会收到gcc关于不兼容指针类型的警告。这是我在嵌入式环境中可能会做的事情,但我会确保它在不太受控制的环境中不会引起任何安全问题。