2016-10-03 7 views
0

blackfin533에서 -1.31의 형식을 가진 fract32를 가진 코드 조각을 발견했습니다.두 고정 소수점 분수의 제곱근을 계산하는 것에 대해 설명합니다.

복소수 (re, img)의 진폭을 계산할 때 왜 프리 - 시프 팅이 필요한지 알 수 없습니다. 나는 1.31을 1.31의 소수 포맷으로 곱하고 싶다면 31 비트 오른쪽으로 이동해야한다는 것을 안다.

GO_coil_D [0], 을 .RE GO_coil_D와 [0]은 fract32 두 .im있다.

나는 다음과 같은 코드가 무엇을하고 있는지 얻을 수 없습니다

norm[0] = norm_fr1x32(GO_coil_D[0].re); 
norm[1] = norm_fr1x32(GO_coil_D[0].im); 
shift = (norm[0] < norm[1]) ? (norm[0] - 1) : (norm[1] - 1); 
vectorFundamentalStored.im = shl_fr1x32(GO_coil_D[0].im,shift);  
vectorFundamentalStored.re = shl_fr1x32(GO_coil_D[0].re,shift); 
vectorFundamentalStored.im = mult_fr1x32x32(vectorFundamentalStored.im, vectorFundamentalStored.im); 
vectorFundamentalStored.re = mult_fr1x32x32(vectorFundamentalStored.re, vectorFundamentalStored.re); 
amplitudeFundamentalStored = sqrt_fr16(round_fr1x32(add_fr1x32(vectorFundamentalStored.re,vectorFundamentalStored.im))) << 16; 
amplitudeFundamentalStored = shr_fr1x32(amplitudeFundamentalStored,shift); 

round_ fr1x32` (fract32의 F1) fract16 편견 라운딩을 사용 fract 16 비트 32 비트 fract를 반올림합니다.

norm_fr1x32 norm_fr1x32 (fract32) int 입력 변수를 정규화하는 데 필요한 왼쪽 시프트 수를 0x40000000 - 0x7fffffff 간격 또는 0x80000000 - 0xc0000000 간격으로 반환합니다. 즉, fract32 x; shl_fr1x32 (x, norm_fr1x32 (x)); 비트 '0'0x7fffffff에 0x40000000과, 또는의 범위 0x80000000에 소수부의 최상위 N 비트가 모든 경우가 0xC0000000

답변

1

1)의 범위의 값을 리턴하고이 '1 따른다 비트이면 n은 부동 소수점 이진 지수 값이 n과 같고 나머지 31- n 비트는 가수처럼 동작합니다. 숫자의 자릿수는 2 * n의 앞에 오는 '0'비트의 수를 두 배로 늘리고 가수의 크기를 31-2 * n 비트로 줄입니다. 이로 인해 제곱 연산 결과의 정확도가 떨어질 수 있습니다.

2) round_fr1x32은 1.31 분수를 1.15 분수로 변환하여 최대 16 비트의 정밀도를 잃습니다.

단계 1과 2를 사용하면 숫자의 정확도를 상당 부분 제거 할 수 있습니다. 숫자를 사전 스케일링하면 앞의 '0'비트 수는 가능한 한 많이 줄어들어 1 단계에서 정밀도가 떨어집니다. 실제로 두 숫자 중 하나가 제곱되고 추가되면 앞선 숫자 '0'비트 n은 0이 될 것이므로 해당 숫자를 제곱하면 다른 숫자에 추가되기 전에 최대 31 비트의 정밀도가 유지됩니다. (2 단계는 그 정밀도를 15 비트로 줄입니다.)

마지막으로 두 개의 1.31 분수 형식 번호를 곱한 결과가 잘못되었습니다. 결과는 62 비트가 아니라 31 비트만큼 오른쪽으로 이동해야합니다.

이의 실제 부분은 1,024분의 3이고 절대 값이 피타고라스에 의해 천이십사분의 오해야 있도록 허수 부분은, 소수의 1,024분의 4 인 가정 해 봅시다 :

예를했다.

사전 조정이 없으면 이진수는 re = 0.00000000112, im = 0.00000001002입니다. 사각형을 채우면 re² = 0.00000000000000001001², im² = 0.000000000000000100002가됩니다. 사각형을 추가하면 abs² = 0.000000000000000110012가됩니다. 15 소수 비트로 반올림하면 abs² = 0.0000000000000012가됩니다. 제곱근을 취하면 abs = 0.0000000101101012가됩니다. 이것은 정확한 결과 0과 다릅니다.00000001012 x 0.0000000000101012.

프리 스케일링시 두 분수가 모두 왼쪽으로 6 비트 씩 이동하므로 sre = 0.00112, sim = 0.01002가됩니다 (접두어 's'를 'scaled'로 사용했습니다). 그들을 squaring하면 sre² = 0.00001001₂, sim² = 0.00010000₂가됩니다. 사각형을 추가하면 sabs² = 0.000110012가됩니다. 15 소수 비트로 반올림해도 값이 변경되지 않습니다. 제곱근을 취하면 sabs = 0.010100002가됩니다. 이것을 1.31 형식으로 변환하고 6 비트 씩 오른쪽으로 이동하면 abs = 0.00000001012가됩니다 (십진수로 5/1024).

+1

실제 파트가 3/1024 (십진수)이고 허수 부분이 4/1024 인 경우 프리 스케일링이있는 경우와없는 경우의 작업 예제를 추가했습니다. 피타고라스 3-4-5 삼각형을 형성하기 때문에 절대 값 (진폭)은 5/1024 여야합니다. –

+0

실재를 그 자체와 가상으로 곱한 원래의 문제가 무엇인지 말해 주시겠습니까? 결과를 더한 다음 제곱근을 취해 오른쪽 31 비트를 이동 하시겠습니까? 그 접근법의 문제점은 무엇입니까? –

+1

1.31 형식 분수의 제곱근을 쉽게 계산할 수 있다면 실수 및 허수 릿 부분을 제곱 할 때 약간의 정밀도가 손실 될 수 있지만 그렇게하는 것은 그리 문제가되지 않습니다. –