PICMicrocontollerMathMethod

2 ^ X 16 Bit 0.16 notation

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
andlw 0x1E      ;and clear lsb and higher bits
movwf index
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
incf index, f
incf index, f
call exp2_table
;find difference with previous point to temphi:templo
movf ylo, w
movf yhi, w
skpnc
incfsz yhi, w
;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
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
andlw 0x1E      ;and clear lsb and higher bits
movwf index
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
incf index, f
incf index, f
call exp2_table
;find difference with previous point to temphi:templo
movf xlo, w
movf xhi, w
skpnc
incfsz xhi, w
;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
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: 2024/7/23 23:11, TOP NEW HELP FIND:  44.192.44.30: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?Please DO link to this page! Digg it! / MAKE! PIC Microcontoller Math Method 2 ^ X 16 Bit 0.16 notation

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.

Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
 Did you find what you needed? "No. I'm looking for: " "No. Take me to the search page." "No. Take me to the top so I can drill down by catagory" "No. I'm willing to pay for help, please refer me to a qualified consultant"

 PICList 2024 contributors: o List host: MIT, Site host massmind.org, Top posters @none found - Page Editors: James Newton, David Cary, and YOU! * Roman Black of Black Robotics donates from sales of Linistep stepper controller kits. * Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters. * Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated! * Contributors: Richard Seriani, Sr.

.