2012-01-26 5 views
6

비트 확장/복제를 수행하는 효율적인 (빠른) 알고리즘이 있습니까?비트 확장/복제 알고리즘?

1101 0101 => 11111100 01110001 11000111 

제안되었다 무력 방법은 룩업 테이블을 생성하는 것이다

예를 들어, (3)에 의한 8 비트 값을 각 비트 (24 비트 값을 생성)를 확장. 나중에 확장 값을 가변 할 필요가 있습니다. 즉, 위의 예에서 우리는 3으로 확장하고 있지만 다른 값으로 확장해야 할 수도 있습니다. 가능하다면 피해야 할 다중 조회 테이블이 필요합니다.

+6

8 비트 값만 처리하는 경우 조회 테이블이 거의 확실하게 최상의 옵션이 될 것입니다. 그것은 아주 작은 공간을 사용합니다. 유스 케이스와 공통적 인 작업에 대해 자세히 설명해 줄 수 있습니까? – templatetypedef

+0

입력은 일정한 직렬 비트 스트림입니다. 현재의 요구 사항에서, 각 데이터 청크는 한 번에 8 바이트 씩 도착하며, 그 다음에는 3으로 확장 된 각 비트가 다른 비트 스트림으로 전송되어야합니다. 192bits에서 64bits. 미래의 요구 사항은 각각의 확장 된 8 비트 값 앞에 "헤더"비트를 추가하는 것과 물론 바이트 경계에 패딩하는 것입니다. LUT는 빠르지 만이 작업을 얼마나 자주 실행해야하는지에 따라 잠재적으로 성능이 향상 될 수 있습니다. – jivany

+1

많은 아키텍처에는 이러한 종류의 계산 속도를 크게 높일 수있는 지침이 있습니다. 이러한 지침을 활용하여 플랫폼 간 호환성을 무서워하지 않으면 거의 확실한 승리를 거둘 수 있습니다. 알고리즘을 "사소한"알고리즘으로 최적화하면 낮은 수준의 최적화로 전환하는 것이 중요합니다. – Kaganar

답변

6

산술 계산이 메모리 액세스보다 빠르면 조회 테이블보다 더 빨리 처리 할 수 ​​있습니다. 이것은 계산이 벡터화 (PPC AltiVec 또는 Intel SSE)되거나 프로그램의 다른 부분이 모든 비트의 캐시 메모리를 사용해야하는 경우에 가능할 수 있습니다.

은 팽창 계수 = 3 만 7 지침이 필요한 경우 :

out = (in | in << 8) & 0x0F00F; 
out = (out | out << 4) & 0x0C30C3; 
out = (out | out << 2) & 0x249249; 
out *= 7; 

다른 확장 요인> = 3 :

unsigned mask = 0x0FF; 
unsigned out = in; 
for (scale = 4; scale != 0; scale /= 2) 
{ 
    shift = scale * (N - 1); 
    mask &= ~(mask << scale); 
    mask |= mask << (scale * N); 
    out = out * ((1 << shift) + 1) & mask; 
} 
out *= (1 << N) - 1; 

out = (((in * 0x101 & 0x0F00F) * 0x11 & 0x0C30C3) * 5 & 0x249249) * 7; 

또는 다른 대안, 10 개 지침

또는 다른 대안 인 확장 요소> = 2 :

unsigned mask = 0x0FF; 
unsigned out = in; 
for (scale = 4; scale != 0; scale /= 2) 
{ 
    shift = scale * (N - 1); 
    mask &= ~(mask << scale); 
    mask |= mask << (scale * N); 
    out = (out | out << shift) & mask; 
} 
out *= (1 << N) - 1; 

shiftmask 값을 비트 스트림 처리 전에 계산하는 것이 더 좋습니다.

+0

환상적인 응답.제 동료와 저는이 일에 손을 대고 화이트 보드를 사용하면서 브레인 스토밍을하면서이 방법을 사용했습니다. 그러나 이것은 우리의 방법보다 훨씬 효율적입니다. 나머지 코드를 구현하고 요금을 확인한 후에 일부 테스트를 실행해야합니다. – jivany

+0

누구나 뒤에있는 수학에 대한 링크가 있습니까? 나는 주변을 둘러 보았지만 어떻게 작동하는지에 대한 설명없이 마술을 발견했다. 나는 마법의 숫자에 어떤 패턴이 있다는 것을 알지만 다른 모든 것은 나를 벗어나고있다. –

+0

nvm, 알아 냈습니다. 바이너리를 쓰고 패턴을 찾는다. 그래도 주제에 대한 링크는 크게 감사하겠습니다. https://gist.github.com/corytodd/056ed01228f59fee9a13d00fc25b9a62 –

1

한 번에 하나의 입력 비트를 사용할 수 있습니다. 물론 룩업 테이블보다 느릴 수 있지만 테이블을위한 충분한 공간이없는 초소형 8 비트 마이크로 컨트롤러와 같은 작업을 수행하는 경우 ROM 풋 프린트를 최소화해야합니다.