Ok, Here is the sceenario,

Im writting some floating point algorithms to be:

[ 1 / (2*Pie) ] * [ ln ( 8 / (Pie * (4A/B - 1)) ) ]

Some engineering crap.. not important what it means... There is only one macro im using fLn1() which does the ln function. I have tested this and verified it is working accurately..

I have coded the function as:
``````  mov DTEMP, 8      ; ln numerator
fild DTEMP
fld A             ; new stack start 4A..
mov DTEMP, 4
fimul DTEMP       ; A*4
fdiv B            ; A*4/B
fldpi
fmul              ; A*4/B*Pie
fldpi             ; New Start  load pie
fsub              ; A*4/B*Pie - Pie
fdiv              ; 8 / (A*4/B*Pie - Pie)

fstp TEMP1
fmov TEMP2, fLn1( TEMP1 )
fld TEMP2         ; ln ( 8 / (A*4/B*Pie - Pie) )

fldpi             ; New start - pie
mov DTEMP, 2
fimul DTEMP       ; Pie*2
div               ; [ln (8 / (A*4/B*Pie - Pie) ) ] / (2*Pie)
``````

I have even varified that the code is correct... my problem is even minimizing the use of add's and sub's i have precision only to 2 decmal places!!! Im using entirely QWORD for A and B and thier typical values are 400-660 ish. My test uses the case of 660 for A and 400 for B ( I have to allow for integers Real's..)..

Im very surprised that this will only give me correct results so poorly.. My 8\$ TexasInstrument calculator has more precision! So im sure im overlooking something..

So.. to any and all Guru's... How would i get the precison to become more like 6 decmal places??

BTW: the macro was designed from the AoA ln' example and proven to work accurately to all demal places. I have also read the chapter in the AoA and understand it, just it doesnt have any good example of the 'Theoretics' is warns about.

Thanx for your help... I would really like to understand this problem better!

NaN
:stupid:
Posted on 2001-07-25 21:11:25 by NaN
To better help.. here is the fLn1() Macro:

``````
; LN(x)- Computes the base e logarithm of x.
;
; X must be greater than zero.
;
; ln(x) = lg(x)/lg(e).
fLn1 MACRO Q1:REQ
fld Q1
fld1
fxch
fyl2x ;Compute 1*lg(x).
fdiv ;Compute lg(x)/lg(10).
fstp GLOBAL_TEMP
EXITM <GLOBAL_TEMP>
ENDM
``````

Thanx again...
NaN
Posted on 2001-07-25 21:32:21 by NaN
NaN,
What are you using to format your output ?
I tested your code before you posted the
macro ( so I commented out the line) and
used FloatToStr2 and saw 17 digits of precision.
Its getting late (or I'm getting old) so I will
look at it some more in the morning.

Good Luck,
anon
Posted on 2001-07-25 22:04:53 by anon
I've held back one detail... The actual "code" is at work...

I have re-written the problem in the above post....

Im using masm's float to string and string to float conversions..

At work i have debugged the loss of accuracy to be within the "ln" itself.. somewhere in (8 / (pie *(4A/B -1)))

Im not sure if i should be using the fscale opp code or not.. (i dont truely understand its use, and havent found good docs on it either..)

NaN
Posted on 2001-07-25 22:48:20 by NaN
I didn't test your code but I've knocked up the calculation myself and with FloatToStr2 I get many places precision.
Note the only real difference between this code and yours is that I intregrated your LnX MACRO into the code.
``````
finit
fld1				Prepare for Log Calculation

mov tdd,8
fild tdd
fldpi				; 8*Pie
mov tdd,4
fild tdd
fmul A				; 4*A
fdiv B				; 4*A/B

fld1
fsub				; (4*A/B)-1

fmul				; (8*Pie)[(4*A/B)-1]

fyl2x
fldl2e
fdiv				; Ln{(8*Pie)([4*A/B]-1)}

fldpi
fdiv				; Ln{(8*Pie)([4*A/B]-1)}/(2*Pie)

``````

PS This is a rather interesting equation, what is it for?
Posted on 2001-07-26 05:24:23 by Eóin
Did you try to transform the equation :

[ 1 / (2*Pie) ] * [ ln ( 8 / (Pie * (4A/B - 1)) ) ] =

((ln (8/Pie))/2*Pie) - (1/2Pie) * ln (4*A/B-1) = Cst1 - Cst2 * ln(4*A/B-1)

If you hardcode the constant, you only have to compute ln (4*A/B-1) and substract the constant value. This way there are less rounding errors.

For example :
``````
.DATA
cst1 REAL8 0.14876398039102426156989078301892
cst2 REAL8 0,15915494309189533576888376337251

.CODE
fld  a
fdiv b ; a/b
fld1

fsub ; 4*a/b - 1

fld1
fxch
fyl2x
fldl2e
fdiv  ; ln (4*a/b - 1)

fmul cst2 ; cst2 * ln (4*a/b - 1)

fld cst1
fsubr ; cst1 - cst2 * ln(4*a/b-1)
``````
Posted on 2001-07-26 06:47:55 by Dr. Manhattan
To everyone, Thank you for your help, I manageded to systematically solve the problem today.. Turn's out the Engineer's short note's were to blame.. not the floating point math! (To keep it ironic, i must have did the same mistake yesterday with my 8\$ calculator to put me off track.. :rolleyes: )

Anyways.. I had precision on every calculation to within the 9 digits my calculator has. This i can live with :)

Karim, Thank you as well, for your detailed responce. I did restructure the equation (as i have been told to do so in the AoA to preserve guard bits..). However, your recent post got me thinking about weather its better to ADD two of the same #'s together or multiply by 2.....

Im new to the floating point 'tricks' so im currious about why you chose to do this.. I guess since the same number has the same precision, then there will be no loss of any more precision (within the bounds of the register itself)?

Again, to everyone, thanx again! I was quite impressed on the speedy replies...

:alright:
NaN
Posted on 2001-07-26 21:56:33 by NaN
``````fld1
fxch
fyl2x
fldl2e
fdiv  ; ln (4*a/b - 1)

fmul cst2 ; cst2 * ln (4*a/b - 1)``````

can't be replaced with:
``````
fld cst2
fxch
fyl2x
fldl2e
fdiv``````

?
Posted on 2003-09-07 09:39:20 by inFinie
Wow.. this can out of the stone ages ;) .. over two years now!

Umm i guess it could, with out testing i dont see any reason why not...

:NaN:
Posted on 2003-09-07 21:39:00 by NaN
Since ln(2)=1/log2(e), you could also use the following sequence to compute the natural log of the value in st0:
``````[b]fldln2
fxch
fyl2x[/b]``````

However, your recent post got me thinking about weather its better to ADD two of the same #'s together or multiply by 2.....
It's always faster to double the stack top by adding it to itself than doing a multiplication or scaling it.
``````[b]fldpi