DevPinoy.org
A Filipino Developers Community

>>> First two to make 3 wins! <<<

Round-off!

rated by 0 users
This post has 12 Replies | 0 Followers

Top 10 Contributor
Posts 751
Points 10,140
modchip Posted: 05-18-2006 1:51 AM
I've experimented today on rounding values. I used this code to round off my numbers.

fld number1
fmul number2
frndint
fstp number3

The only problem I have now is I can't figure out how to round-off to the nearest N. I've read some texts, it tells something about control words and stuff...

Can anybody shed some light into this topic? Thanks in advance... :)

Regards,
m0ds

  • Filed under:
  • | Post Points: 20
Top 10 Contributor
Posts 498
Points 8,375

Yup, just set the bit 10 and bit 11 of the control word to zero, then FPU will round number to the nearest, or equidistance.

.data
cword dw 0

.code
   fstcw cword           ; Get FPU control word
   fwait
   mov   ax, cword       ; Store it to AX
   and   ax, 0fffff9ffh  ; Clear bit 10 and bit 11
   push  eax
   fldcw [sp]            ; Store modified control word

   ' do your rounding here.. 



Regards,

-chris
  

Chris Vega This posting is provided "AS IS" with no warranties, and confers no rights My Weblog|Visit MSDN Community
  • | Post Points: 20
Top 10 Contributor
Posts 751
Points 10,140
I'm having a problem when I compile my asm, this is the error: "must be index or base register" and this error occirs in this line; fldcw [sp]...

I've studied the SimplyFPU by Raymod Fil(Something), and as far as read, the code seems right, almost identical with ours...

So I was wondering, what could have I've done wrong... here's a part of the code;

            fstcw cword
            fwait
            mov ax, cword
            and   ax, 0fffff9ffh
            or ax, 0C00h
            push  eax
            fldcw [sp]            ; this line alwasy error

            fld float_buffer
            frndint
            fstp float_buffer

            ;restore some stuff
            fldcw cword
            pop eax

Can you please look at this code, I appreciate all the help. Thanks! Later!

Regrads,
m0ds

  • Filed under:
  • | Post Points: 20
Top 10 Contributor
Posts 498
Points 8,375

Sorry, that was my mistake. I'm using MASM version 8.0 which can handle 16-bit/32-bit register correction, while MASM version 6.14 (comes from MASM32v9) can't. In general, FLDCW instruction is expecting a DWORD pointer to a 16-bit data, so a more correct one is using ESP instead:

      fldcw [esp] ; ESP = 32-bit pointer to the stack

or try to reuse cword variable:

      fstcw cword 
      fwait
      mov   ax, cword
      and   ax, 0fffff9ffh
      or    ax, 0C00h
      mov   cword, ax       ; cword = changed control word
      fldcw [cword]         ; Update control word

Regards,

-chris

Chris Vega This posting is provided "AS IS" with no warranties, and confers no rights My Weblog|Visit MSDN Community
  • | Post Points: 20
Top 10 Contributor
Posts 751
Points 10,140
Hey, that was fast... :)

I'll test this out. Once again, Thanks a lot!

Regards
m0ds

  • Filed under:
  • | Post Points: 5
Top 10 Contributor
Posts 751
Points 10,140
I'm having a little problem again... Using the code we currently have, the result is always floored. Hmmmm... Is this what it should really do?

Input: 5.96
Output: 5

Input: 5.2
Output: 5

Anyways, I'll try to read more on Ramond's site. Later!

Regards,
m0ds

  • Filed under:
  • | Post Points: 35
Top 10 Contributor
Posts 498
Points 8,375
I'll look at this later Smile [:)]

Cheers,

-chris
Chris Vega This posting is provided "AS IS" with no warranties, and confers no rights My Weblog|Visit MSDN Community
  • | Post Points: 5
Top 10 Contributor
Posts 498
Points 8,375
modchip:
I'm having a little problem again... Using the code we currently have, the result is always floored. Hmmmm... Is this what it should really do?

Input: 5.96
Output: 5

Input: 5.2
Output: 5

Anyways, I'll try to read more on Ramond's site. Later!

Regards,
m0ds



How about keep the FPU control word intact, without modification, and try rounding off numbers. On my test, I got the nearest/equidistant result. Here's my code:

.data
   _fnum dq 5.96
   _buffer db 64 dup(0)

.code

   finit
   fld  _fnum
   frndint
   fstp _fnum
 
   invoke FloatToStr, _fnum, addr _buffer
   invoke MessageBox, hWnd, addr _buffer, 0, MB_OK


The result of the code above is 6. And if I changed _fnum to 5.2, then I am getting 5 as the result, which is the one I expected.

Regards,

-chris
Chris Vega This posting is provided "AS IS" with no warranties, and confers no rights My Weblog|Visit MSDN Community
  • | Post Points: 35
Top 10 Contributor
Posts 751
Points 10,140
Ok, I'll try that. Thanks for the reply. :) Later!

Regards,
m0ds

  • Filed under:
  • | Post Points: 5
Top 10 Contributor
Posts 751
Points 10,140
Yes, that works OK. But how do you round off to the nearest digit. Like if I had a number; 5.268456548, I could make it round like this; 5.27... Is that controlled with the RC filed of the control word? In the documentation it states that bit 10 and 11 will round the results in 4 ways;

00 = Round to nearest, or to even if equidistant (this is the initialized state)
01 = Round down (toward -infinity)
10 = Round up (toward +infinity)
11 = Truncate (toward 0)

What does this mean? Please help, I'm "lost". :(

Regards,
m0ds

  • Filed under:
  • | Post Points: 20
Top 10 Contributor
Posts 498
Points 8,375

00 - Means, it round floating point to nearest whole number. I'm not sure on how to make it equidistant, because I can't make it work that way, like 5.5 should remain 5.5 etc.
01 - The rounded number is floor value., 5.9=5
10 - The rounded number is ceiling value., 5.2=6
11 - Truncates based on precision

Well, this takes a lot of trial and error, I haven't done much about it, because I prefer using Streaming SIMD Extension (SSE/SSE2 or SSE3) instructions over FPU. In FPU, you have to play with IC (Infinity Control) and PC (Precision Control), together with RC (Rounding Control) to be able to make rounding work. The initial settings of these controls are mostly for basic arithmetic.

If you have much time, I suggest start learning Streaming SIMD Extension, since Windows Vista is now blocking any call to FPU: http://www.intel.com/support/processors/sb/cs-001650.htm

You can search the Intel website for more documents about SSE, or if you're an AMD user, try working with 3DNow, documents available in their respective sites.

I also recomend this sites:
http://www.cpuid.com/ (For MMX/3DNow/SSE/SSE2/SSE3 instruction sets)
http://www.sandpile.org/ (For general CPU layout and design)

Cheers,

-chris

Chris Vega This posting is provided "AS IS" with no warranties, and confers no rights My Weblog|Visit MSDN Community
  • | Post Points: 20
Top 10 Contributor
Posts 751
Points 10,140
Yikes! I was just beginning to have fun with it! Well anyway, maybe I'll take a look that SIMD thingy when time permits. In the meantime, I'll try to pursue on FPU since vista is still in beta (I think). Well, catch you later Chris. Thanks for the info.

Regards,
m0ds

  • | Post Points: 5
Top 10 Contributor
Posts 751
Points 10,140

Whew, after 1 year, 2 months and 13 days, I finally got the solution for this. BTW, the solution is in my blog. Check it out here: http://devpinoy.org/blogs/modchip/archive/2007/08/13/round-n-round-we-go.aspx

Thanks!

  • Filed under:
  • | Post Points: 5
Page 1 of 1 (13 items) | RSS

Copyright DevPinoy 2005-2008