I did this before, it was somehow like this:
FILD j
FLD1
FADD iVarn
FYL2X
F2XM1
FLD1
FADD ; (i+1)^j
But now it does not work propertly.
Where am i wrong?
This is the code I use.
' Create the control WORD TO truncate when rounding.
' Only needs to be done once, not eveytime you do the calculation
!fstcw MaskedCW&
!OR MaskedCW&, &b110000000000
!fstcw SaveCW& ;save a copy of the initial control word so it can be put back
..
..
' calculate a# ^ b#
!fld b# ;push the 2 operands onto the FP stack
!fld a#
!fyl2x ;Compute x*lg(y)
!fldcw MaskedCW& ;Modify the control WORD TO truncate when rounding
!fld st(0) ;Duplicate top of stack
!frndint ;Compute INTEGER portion.
!fsubr st(0), st(1) ;Compute fractional part.
!f2xm1 ;Compute 2**FRAC(x)-1.
!fld1
!fadd ;Compute 2**FRAC(x).
!fscale ;Compute 2**INT(x) * 2**FRAC(x).
!fldcw SaveCW& ;Restore rounding mode.
!fstp x# ;pop the answer off the FP stack
!fstp st(0) ;clean up the stack (there's 1 value left on it)
akalenuk,
I had adapted Ray's theory to use in a FASM macro:
Quotemacro powerFloat x,y,result ; x^y = 2^(log2(x) * y))
{
finit
fld y ; st0=y
fld x ; st0=x, st1=y
fyl2x ; st0=log2(x)*y
; now get the antilog2 of the logarithm in st1
fst st1 ; st0=st1=log2(x)*y
frndint ; st0=int, st1=log2(x)*y. - keep only the integer in st0
fsub st1,st0 ; st0=int, st1=fraction. - keeps only the fraction in st1
fxch st1 ; st0=fraction, st1=int. - get the mantissa on top
f2xm1 ; st0=2^st0-1, st1=int. - 2^(mantissa)-1
fld1 ; st0=1, st1=2^st0-1, st2=int
faddp ; st0=2^st0, st1=int
fscale ; st0=x^y, st1=int. scale it with the integer
fwait
fstp result
}
I actually had not got around to testing this properly. Perhpas you could test it for me after translating to MASM if need be :bg
Chris
I've copied this straight out of my Expression Evaluator code (the integer code simply used a loop, which is much more efficient for small integer powers):
fld QWORD PTR [esp]
fld QWORD PTR [esp+8]
fyl2x
fld st
frndint
fsub st(1),st
fxch st(1)
f2xm1
add esp, 8
fld1
fadd
fscale
fstp st(1)
fstp QWORD PTR [esp]
Note that I take the parameters directly off the stack and put one back on the stack, hence the add esp, 8 in the middle of it. The fld's and fstp's can be modified.
Cheers,
Zooba :U
Quote from: dioxin on July 12, 2006, 11:45:28 PM
!frndint ;Compute INTEGER portion.
!fsubr st(0), st(1) ;Compute fractional part.
I simply don't understand why it is importrant to split a number to integer and fractional part. Looking at the code i see it is a thing that shoud be done, but why?
Quote from: ChrisLeslie on July 13, 2006, 12:28:47 AM
faddp ; st0=2^st0, st1=int
Here's "fadd", not "faddp". The rest is perfect! Works fine.
I still don't get this splitting issue. Looks like that is why my own code is wrong.
akalenuk,
it's a hardware restricion. The F2XM1 opcode only works on values between +1 and -1 so you need to split the integer part off, do the 2^x on the fractional part and then adjust the result by shifting left or right by the integer part (that's what SCALE does)
Paul.
Quote from: dioxin on July 13, 2006, 05:15:11 PM
it's a hardware restricion. The F2XM1 opcode only works on values between +1 and -1 so you need to split the integer part off, do the 2^x on the fractional part and then adjust the result by shifting left or right by the integer part (that's what SCALE does)
Right! Previously i used my piece of code in economical calculation, where that powered value always been between 0 and 1. No wonder,i didn't see any bugs. Now i'm working with arbitrary numbers, so that code is no good anymore.
That's why i love assembly. Everything is so logical, when you got there :bg
akalenuk
QuoteHere's "fadd", not "faddp". The rest is perfect! Works fine.
There appears to be little quirk with MASM assembler where FADD without operands can also be used as FADDP ST(1),ST(0). The posted FASM code with FADDP, no operands, works fine in FASM.
Chris