by Nikolai Golovchenko debugged by Daniel Schouten [daniels at XS4ALL.NL]
Well, let's calculate y=2^x! x is Q6.10 notation (always negative with implicit sign). Output y has Q0.16 notation (always less then 1). Therefore x should not be zero (2^0 = 1).
y is in the range from 0.9993 (x = -1/1024) to 5e-20 (x = -64 + 1/1024). Okay....
y=2^x y=2^-(32*x.15+16*x.14+...1*x.10 + 0.5*x.9+0.25*x.8+...) \========================/ \===================/ x_int x_frac x_int = 0:1:63 x_frac = 0:1/1024:(1-1/1024) y=2^-(x_int+x_frac) y=2^(-x_int) * 2^(-x_frac) y= (2^(-x_frac)) >> x_int =========================
So we first find 2^-x_frac using a table and then shift the result right x_int times.
First we should convert the fraction part through a table to a new fraction part. 2^(-0..-1) = 0.5..1
; y = 2^x2 ;Input: x2hi:x2lo ;Output: yhi:ylo ;Form table index from 4 higher bits of x2 fraction part rlf x2lo, f rlf x2ho, w movwf index rlf x2lo, w rlf index, f ;here middle 6 bits of x2lo contain multiplier for linear ;interpolation, and index has 4 lower bits of table pointer rlf index, w ;multiply index by 2 for 16 bit ;entries addressing andlw 0x1E ;and clear lsb and higher bits movwf index ;Read first point to temphi:templo call exp2_table ;clear result and subtract the first point from it clrf yhi clrf ylo movf templo, w subwf ylo, f movf temphi, w skpc incfsz temphi, w subwf yhi, f ;Read next point to temphi:templo incf index, f incf index, f call exp2_table ;find difference with previous point to temphi:templo movf ylo, w addwf templo, f movf yhi, w skpnc incfsz yhi, w addwf temphi, f ;multiply the difference by the next 6 fraction bits in ;x2lo and divide by 64. Then subtract it from the current ;result in yhi:ylo movlw 6 movwf index ;use index as a loop counter rrf x2lo, f ;align the 6 bits to the lsb clrf temp ;we will use another temp ;for mul purposes rrf yhi, f ;rotate y right 2 times rrf ylo, f ;to make easy multiplication. rrf temp, f ;lower bits will go to temp rrf yhi, f rrf ylo, f rrf temp, f exp2loop rrf x2lo, f ;get next multiplier bit bnc exp2loopnext ;skip subtraction if carry is clear movf templo, w subwf temp, f movf temphi, w skpc incfsz temphi, w subwf ylo, f skpc decf yhi, f exp2loopnext rrf yhi, f rrf ylo, f rrf temp, f decfsz index, f goto exp2loop ;shift the result 8 bits left movf ylo, w movwf yhi movf temp, w movwf ylo ;Now we will shift y right the number of times ;equal to the integer part of x2 clrc ;align integer bits rrf x2hi, f ;to lsb clrc rrf x2hi, f test x2hi skpnz return ;done exp2loop2 clrc rrf y2hi, f rrf y2lo, f decfsz x2hi, f goto exp2loop2 return ;done
Now we need to calculate the table...
1-2.^(0:-1/16:-1)
ans =
Columns 1 through 4 0 0.04239671930143 0.08299595679533 0.12187391981335 Columns 5 through 8 0.15910358474629 0.19475483402537 0.22889458729603 0.26158692703025 Columns 9 through 12 0.29289321881345 0.32287222653155 0.35158022267450 0.37907109396326 Columns 13 through 16 0.40539644249864 0.43060568262165 0.45474613366737 0.47786310878629 Column 17 0.50000000000000
Multiplied by 65536 and rounded
round(65536*(1-2.^(0:-1/16:-1)))
ans =
Columns 1 through 6 0 2779 5439 7987 10427 12763 Columns 7 through 12 15001 17143 19195 21160 23041 24843 Columns 13 through 17 26568 28220 29802 31317 32768 »
So, the table would be:
exp2_table movf index, w call exp2tableStart movwf templo incf index, w call exp2tableStart movwf temphi return exp2tableStart addwf PCL, f DT 0 & 0xFF, 0 >> 8, 2779 & 0xFF, 2779 >> 8 DT 5439 & 0xFF, 5439 >> 8, 7987 & 0xFF, 7987 >> 8 DT 10427 & 0xFF, 10427 >> 8, 12763 & 0xFF, 12763 >> 8 DT 15001 & 0xFF, 15001 >> 8, 17143 & 0xFF, 17143 >> 8 DT 19195 & 0xFF, 19195 >> 8, 21160 & 0xFF, 21160 >> 8 DT 23041 & 0xFF, 23041 >> 8, 24843 & 0xFF, 24843 >> 8 DT 26568 & 0xFF, 26568 >> 8, 28220 & 0xFF, 28220 >> 8 DT 29802 & 0xFF, 29802 >> 8, 31317 & 0xFF, 31317 >> 8 DT 32768 & 0xFF, 32768 >> 8 IF (($ - 1) >> 8) - ((exp2tableStart + 1) >> 8) != 0 error 'exp2 table crossed 8-bit boundary' ENDIF
And the cleaned up version is below... Yeah, this one was harder and not really the reverse of log!
Don't forget to check x and y for zero in x^y.
#include <p16f84.inc> cblock 0x20 xhi, xlo templo, temphi, temp index x2hi, x2lo endc #define tval 65300 movlw tval & 0xFF movwf xlo movlw tval >> 8 movwf xhi call log2 nop call exp2 nop ;************************************************ ; EXP2 routine for fixed point unsigned ; 16 bit values in 6.10 notation (implicit minus) ; ; Input: x2hi:x2lo unsigned Q6.10 (implicit minus) ; Output: xhi:xlo unsigned Q0.16 ; Temporary: index, templo, temphi, temp ; ; Maximum error: 0.025% (for x2 < 1) ; ; Size: 121 words ; Time: min 2+8+18*2+10+16+10*6-1+6+2=139 ; max 2+8+18*2+10+16+17*6-1+6+1+14+6*16-1+2=291 ; ; Note: Zero input is illegal! Will result in ; zero output. (2^0 = 1, but x is always less ; than 1) ; ; 30 Sep 2000 by Nikolai Golovchenko ; 02 Oct 2000 debugged by Daniel Schouten [daniels at XS4ALL.NL] ;************************************************ exp2 ;Form table index from 4 higher bits of x2 fraction part rlf x2lo, f rlf x2hi, w movwf index rlf x2lo, w rlf index, f ;here middle 6 bits of x2lo contain multiplier for linear ;interpolation, and index has 4 lower bits of table pointer rlf index, w ;multiply index by 2 for 16 bit ;entries addressing andlw 0x1E ;and clear lsb and higher bits movwf index ;Read first point to temphi:templo call exp2_table ;clear result and subtract the first point from it clrf xhi clrf xlo movf templo, w subwf xlo, f movf temphi, w skpc incfsz temphi, w subwf xhi, f ;Read next point to temphi:templo incf index, f incf index, f call exp2_table ;find difference with previous point to temphi:templo movf xlo, w addwf templo, f movf xhi, w skpnc incfsz xhi, w addwf temphi, f ;multiply the difference by the next 6 fraction bits in ;x2lo and divide by 64. Then subtract it from the current ;result in xhi:xlo movlw 6 movwf index ;use index as a loop counter rrf x2lo, f ;align the 6 bits to the lsb clrf temp ;we will use another temp ;for mul purposes rrf xhi, f ;rotate x right 2 times rrf xlo, f ;to make easy multiplication. rrf temp, f ;lower bits will go to temp rrf xhi, f rrf xlo, f rrf temp, f exp2loop rrf x2lo, f ;get next multiplier bit bnc exp2loopnext ;skip subtraction if carry is clear movf templo, w subwf temp, f movf temphi, w skpc incfsz temphi, w subwf xlo, f skpc decf xhi, f exp2loopnext rrf xhi, f rrf xlo, f rrf temp, f decfsz index, f goto exp2loop ;shift the result 8 bits left movf xlo, w movwf xhi movf temp, w movwf xlo ;Now we will shift x right the number of times ;equal to the integer part of x2 clrc ;align integer bits rrf x2hi, f ;to lsb clrc rrf x2hi, f tstf x2hi skpnz return ;done movlw 17 ;limit shifts number to 16 maximum subwf x2hi, w movlw 16 skpnc movwf x2hi ;if fractional part is zero than set carry, else ;clear carry movf xlo, w iorwf xhi, w setc skpz clrc ;limit number of si ;perform shifts exp2loop2 rrf xhi, f rrf xlo, f clrc decfsz x2hi, f goto exp2loop2 return ;done exp2_table movf index, w call exp2tableStart movwf templo incf index, w call exp2tableStart movwf temphi return exp2tableStart addwf PCL, f DT 0 & 0xFF, 0 >> 8, 2779 & 0xFF, 2779 >> 8 DT 5439 & 0xFF, 5439 >> 8, 7987 & 0xFF, 7987 >> 8 DT 10427 & 0xFF, 10427 >> 8, 12763 & 0xFF, 12763 >> 8 DT 15001 & 0xFF, 15001 >> 8, 17143 & 0xFF, 17143 >> 8 DT 19195 & 0xFF, 19195 >> 8, 21160 & 0xFF, 21160 >> 8 DT 23041 & 0xFF, 23041 >> 8, 24843 & 0xFF, 24843 >> 8 DT 26568 & 0xFF, 26568 >> 8, 28220 & 0xFF, 28220 >> 8 DT 29802 & 0xFF, 29802 >> 8, 31317 & 0xFF, 31317 >> 8 DT 32768 & 0xFF, 32768 >> 8 IF (($ - 1) >> 8) - ((exp2tableStart + 1) >> 8) != 0 error 'exp2 table crossed 8-bit boundary' ENDIF ;************************************************
file: /Techref/microchip/math/power/2x-16b-ng.htm, 10KB, , updated: 2000/10/3 13:06, local time: 2024/12/25 19:41,
18.216.161.178:LOG IN
|
©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://techref.massmind.org/techref/microchip/math/power/2x-16b-ng.htm"> PIC Microcontoller Math Method 2 ^ X 16 Bit 0.16 notation</A> |
Did you find what you needed? |
Welcome to massmind.org! |
Welcome to techref.massmind.org! |
.