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 14:06, local time: 2025/10/23 22:49,
216.73.216.53,10-2-207-162:LOG IN
|
| ©2025 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://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! |
|
The Backwoods Guide to Computer Lingo |
.