본문 바로가기

Programming/NEON

[NEON] 비트와 시프트 연산

1. 비트 연산

1.1 NOT(~)연산

uint8x8_t r = vmvn_u8(uint8x8_t a)

벡터의 모든 레인에 NOT 연산을 실행

 

1.2 AND(&) 연산

uint8x8_t r = vand_u8(uint8x8_t a, uint8x8_t b)

두 벡터의 레인 사이에 AND(&)연산을 실행

 

1.3 OR(|) 연산

uint8x8_t r = vorr_u8(uint8x8_t a, uint8x8_t b)

두 벡터의 레인 사이에 OR(|) 연산을 실행

 

1.4 XOR(^) 연산

uint8x8_t r = veor_u8(uint8x8_t a, uint8x8_t b)

두 벡터의 레인 사이에 XOR(^) 연산을 실행

 

1.5 AND NOT(&~) 연산

uint8x8_t ar = vbic_u8(uint8x8_t a, uint8x8_t b)

벡터에 NOT 연산한 결과를 또 다른 벡터와 AND연산 (b 벡터에 NOT 연산후 AND연산)

 

1.6 OR NOT(|~) 연산

uint8x8_t r = vorn_u8(uint8x8_t a, uint8x8_t b)

벡터에 NOT(~) 연산한 결과를 또 다른 벡터와 OR(|) 연산 (b 벡터에 NOT 연산후 OR 연산)

 

1.7 비트 단위 선택 함수

int8x8_t r = vbsl_s8(uint8x8_t a, int8x8_t b, int8x8_t c)

두 벡터의 레인 bit를 조합하여 하나의 레인에 저장

벡터 a의 레인의 값이 1이면 b벡터의 비트 선택, 레인값이 0이면 c벡터의 비트 선택

 

1.8 부호 비트 변환 함수

int8x8_t r = vneg_s8(int8x8_t a)

벡터의 부호 변경(각 레인 마다 변경)

 

2. NEON 시프트 연산

2.1 NEON Shift 함수

int8x8_t r = vshl_s8(int8x8_t a, int8x8_t b)

벡터 a의 레인 값을 벡터 b의 레인 값 만큼 Shift 연산을 한다.(양수는 왼쪽으로 shift, 음수는 오른쪽으로 shift)

 

int8x8_t r = vqshl_s8(int8x8_t a, int8x8_t b) - 포화 shift 함수(오버플로우 방지)

 

※ 일반적으로 Shift 연산은 산술적 Shift 연산과 논리적 Shift 연산이 있다.

    NEON 에서는 논리적 Shift 연산을 지원하지 않는다. 그 이유는 예를들어 논리적 Shift 연산은 2의 n승으로

    나눈 효과가 있지만, 음수에서는 문제가 나타난다. 일반적으로 음의 정수는 2의 보수로 구현되는데,

    2의 보수의 최상위 부호는 1이 된다. 그래서 논리적 Shift 연산을 음수에 사용하면 2로 나눈 결과가 아닌

    양수로 바뀌게 된다.(논리적 Shift 연산은 최상위 비트가 부호에 상관없이 무조건 0이 채워지기 때문)

    따라서 NEON 에서는 논리적 Shift 연산을 지원하지 않는다.

 

2.2 오른쪽 Shift 함수

int8x8_t r = vshr_n_s8(int8x8_t a, __constrange(1, 8) int b)

벡터 a 를 b만큼 오른쪽으로 Shift 연산한다. 각 레인에 대해서 최상위 비트 값은 유지하고,

이후 1bit씩 Shift하므로 2의 n승으로 나눈 결과가 된다.

 

2.3 왼쪽 Shift 함수

int8x8_t r = vshl_n_s8(int8x8_t a, __constrange(0, 7) int b)

벡터 a를 b만큼 왼쪽으로 Shift 연산한다. 논리적 왼쪽 Shift 연산은 2의 n승으로 곱한 효과가 있다.

 

2.4 Shift 후 삽입 함수

오른쪽 Shift 후 삽입

uint8x8_t r = vsri_n_u8(uint8x8_t a, uint8x8_t b, __constrange(1, 8) int c)

벡터 레인을 Shift 하고, Shift 한 크기만큼 다른 벡터 레인의 bit로 채워 넣는다.

벡터 b를 c 만큼 오른쪽 shift 연산 한후, 빈 공간은 벡터 b의 bit로 채운다.

 

왼쪽 Shift 후 삽입

uint8x8_t r =vsli_n_u8(uint8x8_t a, uint8x8_t b, __constrange(0, 7) int c)

벡터 a를 2만큼 왼쪽 shift 연산 한 후, 빈 공간은 b의 bit로 채운다.

 

2.5 나눗셈 구현

NEON 에서는 나눗셈을 지원하지 않으므로 Shift 연산으로 대체해야 한다.

순수하게 Shift만을 사용하게 되면 2, 4, 6, 8, 16, 32, 64와 같이 2의 n승 단위의 나눗셈만 구현할 수 있다.

 

149/23과 같은 나눗셈을 구현하려면 일정한 값을 곱하고 나서 Shift 연산을 수행해야 한다.

먼저 레인이 오버플로가 발생하는지를 고려하여 Shift 연산을 수행할 크기를 정한다.

오버플로에 대한 우려가 없다면 Shift 단위가 클수록 오차가 줄고 정확하다. 나눗셈을 구현하는 과정은 다음과 같다.

  ① 오버플로가 발생하지 않는 범위의 Shift 단위를 정한다.

  ② Shift 단위를 제수로 나눈다. (6÷3=2에서 6을 말함 )

  ③ 구한 값을 피제수로 곱한다.

  ④ 피제수를 오른쪽 Shift 연산한다.


예) 256 Shift 단위로 다음 나눗셈을 구현하기

   149 / 9 = 16


직접 나눗셈을 할수 없으므로 Shift 연산을 수행할 단위 256을 9로 나눈다.

   256 / 9 = 16


28을 149에 곱하고 나서 256으로 나눈다.

   149 * 28 = 4172

 

4172를 8번 오른쪽 Shift 연산하면

   4172 / 256 = 16

결과값 16이 나온다.

'Programming > NEON' 카테고리의 다른 글

[NEON] 변환 연산  (0) 2016.09.23
[NEON] 비교 연산과 절대값  (0) 2016.09.23
[NEON] 레인 설정과 조회  (0) 2016.09.23
[NEON 산술 연산과 확장  (0) 2016.09.23
[NEON] 함수 정리 (로드 함수, 저장 함수)  (0) 2016.09.23