Melissa wrote:Floating point multiplication and addition are generally almost as fast as integer math,
4-5 times slower, according to my tests.
Your tests are wrong.
Code: Select all
; Turn off debugger
#Tries = 10000000
time = ElapsedMilliseconds()
For U = 0 To #Tries
!repeat 100
a = b * c
!end repeat
Next
MessageRequester("", Str(ElapsedMilliseconds()-time))
time = ElapsedMilliseconds()
For U = 0 To #Tries
!repeat 100
f.f = g.f * h.f
!end repeat
Next
MessageRequester("", Str(ElapsedMilliseconds()-time))
however, the conversion from floating point to integer is very expensive, so it seems to me like you're just slowing your code down.
Of course, of course... Well, now just read my sample again: f->i conversion would happen there anyways (floats could not be properly stored in integer variable), I just want to manually force it's happening before addition of 1 (for changing 'fadd' into 'inc').
When I say it won't go faster due to float to integer conversion, I mean it. One of the reasons FP to integer is expensive is that
you cannot move data from the fpu to the cpu. It must go through memory. So you have to store the float to memory (in a temp location), load it from memory onto the cpu, do an inc, and move it back to memory yet again. Moreover, the temp location has to be allocated somewhere.
Instead of two memory accesses you have four. Instead of two register accesses (for add and store) you now have 6, for alloc temp, store, load (and dealloc temp), inc and store. How is that going to be faster??
Also, I don't understand what you really want. Look at this: "{a / b}.f". Here you want the division (the INSIDE of the {}) to be done on the fpu. While here "{a.f * c}.i + 1" you want the addition (the OUTSIDE of the {}) to be done as integer math. You don't clearly define whether the {} should change the type of the expression inside before calculation is done or after.
Let's assume for a moment you declared your variable a as float. The generated code would look like this:
Code: Select all
FLD dword [v_a]
FIDIV dword [v_b]
FIMUL dword [v_c]
FADD dword [F1] ; + 1 ; 1 memory access, 1 register access
FISTP dword [v_d] ; 1 memory access, 1 register access
If a was an integer and you had forced float division, the first FLD would say FILD.
Now assume that we convert the fadd to an inc. It would look like this:
Code: Select all
!FLD dword [v_a]
!FIDIV dword [v_b]
!FIMUL dword [v_c]
!push eax ; 2 register access (eax+esp), 1 memory access ([esp])
!fistp dword [esp] ; 1 register access (st0), 1 memory access ([esp])
!pop eax ; 2 register access (eax+esp), 1 memory access ([esp])
!inc eax ; 1 register access
!mov dword [v_d], eax ; 1 memory access
In practice, the codes have almost the same speed, however, the first one (with fadd) is
slightly faster.