The MASM Forum

Miscellaneous => Miscellaneous Projects => Topic started by: RuiLoureiro on April 30, 2013, 04:07:27 AM

Title: Converting real8 to string
Post by: RuiLoureiro on April 30, 2013, 04:07:27 AM
Hi
    Here we have the ASM procedures

            ConvertFloat8DS and ConvertFloat8DSD

   to convert a real8 (qword) to a string,

    the second to specify the number of decimal places
    we want. These converters doesnt use BCD. It gets
    the qword integer and converts it to a string.

    All is in the file ConverterDQ.inc and
   
    we can test using TestCnvDQ12_DS.asm.

    All these files are in ConverterDQ folder.

EDIT: i replaced ConverterDQ by Converter8

    Here we have the new ASM procedures

        ConvertFloat8DR and ConvertFloat8DRD
        ConvertReal8DR  and ConvertReal8DRD

    and the last

        ConvertFloat8DS and ConvertFloat8DSD
        ConvertReal8DS  and ConvertReal8DSD

    . Float version use length behind the address
    . Real     "    doesnt use

    . Real version only: we may specify string address = 0
      The proc returns the address in EDX

        invoke  ConvertReal8DRD, addr _qword, 0, 14
        print   edx, 13,10

    To use it

        include     PowerTable.inc
        include     Convert8DR.inc
        include     Convert8DRD.inc
        include     Convert8DS.inc
        include     Convert8DSD.inc
       
        uncomment ;$DECIMALPLACES_REAL8  equ 15
       
   
    Test yourself:

            TestCycles8_10D.asm
            TestCycles8_15D.asm
            TestTime8_10D.asm
            TestTime8_15D.asm
           
            TestFloat8DR_10D.asm
            TestReal8DR_10D.asm           
            ...

    All these files are in Converter8 folder.

EDIT: the old Converter8 had a bug


EDITuse the last Converter8 because the first has a bug in the procedures
           ConvertReal8DR, ...Real8DRD, ..., Real8DS and ...Real8DSD.
           It sets the length if ERROR.
Title: Re: Converting real8 to string
Post by: dedndave on April 30, 2013, 08:21:04 AM
looking good, Rui   :t
Title: Re: Converting real8 to string
Post by: Gunther on April 30, 2013, 10:25:08 PM
Well done. :t

Gunther
Title: Re: Converting real8 to string
Post by: TouEnMasm on April 30, 2013, 10:36:06 PM

I try a question,is it better than the FloatToBCD (fptoa.asm) ?
Or perhaps better than the fcvt for the crt ?
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 01, 2013, 02:40:28 AM
Quote from: ToutEnMasm on April 30, 2013, 10:36:06 PM

I try a question,is it better than the FloatToBCD (fptoa.asm) ?
Or perhaps better than the fcvt for the crt ?
I think it is better but i will try to show all the numbers i have.
               now i improved it again, please wait  :t

For now i have this:
(CNV1 convert EDX:EAX using div, CNV2 uses magic numbers)

with CNV1

502  cycles, ConvertFloat8DSD, direct, fxam, fyl2x, ebp - 15 digits
554  cycles, ConvertFloat8DYD, direct, examine, fxtract, esp - 15 digits
563  cycles, ConvertFloat8DRD, direct, examine, fxtract, ebp - 15 digits
576  cycles, ConvertFloat8DXD, direct, fxam, fxtract, esp - 15 digits
683  cycles, ConvertFloat8DFD, direct, examine, fyl2x, ebp - 15 digits
754  cycles, ConvertFloat8BX, BCD, fxam, fxtract, ebp - 15 digits
757  cycles, ConvertFloat8BY, BCD, examine, fxtract, esp - 15 digits
763  cycles, ConvertFloat8BF, BCD, fxam, fxtract, esp - 15 digits
772  cycles, ConvertFloat8CT, BCD-CT, fxam, fxtract, esp - 15 digits
889  cycles, ConvertFloat8CTD, BCD-CT, fxam, fxtract, esp - 15 digits
989  cycles, ConvertFloat8BFD, BCD, fxam, fxtract, esp - 15 digits
992  cycles, ConvertFloat8BYD, BCD, examine, fxtract, esp - 15 digits
1000  cycles, ConvertFloat8DX, direct, fxam, fxtract, esp - 15 digits
1002  cycles, ConvertFloat8DY, direct, examine, fxtract, esp - 15 digits
1010  cycles, ConvertFloat8DR, direct, examine, fxtract, ebp - 15 digits
1028  cycles, ConvertFloat8BXD, BCD, fxam, fxtract, ebp - 15 digits
1056  cycles, ConvertFloat8ZX, BCD - old - 15 digits
1068  cycles, ConvertFloat8Z, BCD -old - 15 digits
1124  cycles, ConvertFloat8DS, direct, fxam, fyl2x, ebp - 15 digits
1153  cycles, ConvertFloat8DF, direct, examine, fyl2x, ebp - 15 digits
2728  cycles, ConvertFloat8DWD, direct,Save FPU, fxam, fxtract, esp -15 digits
2921  cycles, ConvertFloat8, BCD, Save FPU -old - 15 digits
3027  cycles, ConvertFloat8BWD, BCD, Save FPU, fxam, fxtract, ebp - 15 digits
3126  cycles, ConvertFloat8BW, BCD, Save FPU, fxam, fxtract, ebp - 15 digits
3885  cycles, ConvertFloat8DW, direct,Save FPU, fxam, fxtract, esp -15 digits
********** END **********

with CNV2

371  cycles, ConvertFloat8DXD, direct, fxam, fxtract, esp - 15 digits
373  cycles, ConvertFloat8DYD, direct, examine, fxtract, esp - 15 digits
509  cycles, ConvertFloat8DSD, direct, fxam, fyl2x, ebp - 15 digits
540  cycles, ConvertFloat8DX, direct, fxam, fxtract, esp - 15 digits
543  cycles, ConvertFloat8DR, direct, examine, fxtract, ebp - 15 digits
549  cycles, ConvertFloat8DY, direct, examine, fxtract, esp - 15 digits
564  cycles, ConvertFloat8DRD, direct, examine, fxtract, ebp - 15 digits
673  cycles, ConvertFloat8DS, direct, fxam, fyl2x, ebp - 15 digits
680  cycles, ConvertFloat8DF, direct, examine, fyl2x, ebp - 15 digits
685  cycles, ConvertFloat8DFD, direct, examine, fyl2x, ebp - 15 digits
756  cycles, ConvertFloat8BX, BCD, fxam, fxtract, ebp - 15 digits
763  cycles, ConvertFloat8BY, BCD, examine, fxtract, esp - 15 digits
764  cycles, ConvertFloat8BYD, BCD, examine, fxtract, esp - 15 digits
767  cycles, ConvertFloat8BF, BCD, fxam, fxtract, esp - 15 digits
781  cycles, ConvertFloat8CT, BCD-CT, fxam, fxtract, esp - 15 digits
794  cycles, ConvertFloat8CTD, BCD-CT, fxam, fxtract, esp - 15 digits
811  cycles, ConvertFloat8BFD, BCD, fxam, fxtract, esp - 15 digits
1008  cycles, ConvertFloat8BXD, BCD, fxam, fxtract, ebp - 15 digits
1053  cycles, ConvertFloat8ZX, BCD - old - 15 digits
1064  cycles, ConvertFloat8Z, BCD -old - 15 digits
2710  cycles, ConvertFloat8DWD, direct,Save FPU, fxam, fxtract, esp -15 digits
2930  cycles, ConvertFloat8, BCD, Save FPU -old - 15 digits
3023  cycles, ConvertFloat8BWD, BCD, Save FPU, fxam, fxtract, ebp - 15 digits
3532  cycles, ConvertFloat8BW, BCD, Save FPU, fxam, fxtract, ebp - 15 digits
3572  cycles, ConvertFloat8DW, direct,Save FPU, fxam, fxtract, esp -15 digits
********** END **********
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

with CNV1

326  cycles, ConvertFloat8DXD, direct, fxam, fxtract, esp - 18 digits
327  cycles, ConvertFloat8DYD, direct, examine, fxtract, esp - 18 digits
331  cycles, ConvertFloat8DRD, direct, examine, fxtract, ebp - 18 digits
461  cycles, ConvertFloat8DSD, direct, fxam, fyl2x, ebp - 18 digits
472  cycles, ConvertFloat8DFD, direct, examine, fyl2x, ebp - 18 digits
695  cycles, ConvertFloat8CTD, BCD-CT, fxam, fxtract, esp - 18 digits
702  cycles, ConvertFloat8BY, BCD, examine, fxtract, esp - 18 digits
703  cycles, ConvertFloat8BFD, BCD, fxam, fxtract, esp - 18 digits
705  cycles, ConvertFloat8BYD, BCD, examine, fxtract, esp - 18 digits
711  cycles, ConvertFloat8BXD, BCD, fxam, fxtract, ebp - 18 digits
714  cycles, ConvertFloat8BF, BCD, fxam, fxtract, esp - 18 digits
714  cycles, ConvertFloat8BX, BCD, fxam, fxtract, ebp - 18 digits
724  cycles, ConvertFloat8CT, BCD-CT, fxam, fxtract, esp - 18 digits
1155  cycles, ConvertFloat8ZX, BCD - old - 18 digits
1161  cycles, ConvertFloat8Z, BCD -old - 18 digits
1310  cycles, ConvertFloat8DR, direct, examine, fxtract, ebp - 18 digits
1318  cycles, ConvertFloat8DY, direct, examine, fxtract, esp - 18 digits
1334  cycles, ConvertFloat8DX, direct, fxam, fxtract, esp - 18 digits
1429  cycles, ConvertFloat8DS, direct, fxam, fyl2x, ebp - 18 digits
1434  cycles, ConvertFloat8DF, direct, examine, fyl2x, ebp - 18 digits
2585  cycles, ConvertFloat8DWD, direct,Save FPU, fxam, fxtract, esp -18 digits
2913  cycles, ConvertFloat8BWD, BCD, Save FPU, fxam, fxtract, ebp - 18 digits
3034  cycles, ConvertFloat8, BCD, Save FPU -old - 18 digits
3041  cycles, ConvertFloat8BW, BCD, Save FPU, fxam, fxtract, ebp - 18 digits
3713  cycles, ConvertFloat8DW, direct,Save FPU, fxam, fxtract, esp -18 digits
********** END **********
; ----------------------------------------------------------------------------------------------
With CNV2

325  cycles, ConvertFloat8DYD, direct, examine, fxtract, esp - 18 digits
327  cycles, ConvertFloat8DXD, direct, fxam, fxtract, esp - 18 digits
336  cycles, ConvertFloat8DRD, direct, examine, fxtract, ebp - 18 digits
452  cycles, ConvertFloat8DFD, direct, examine, fyl2x, ebp - 18 digits
454  cycles, ConvertFloat8DSD, direct, fxam, fyl2x, ebp - 18 digits
559  cycles, ConvertFloat8DX, direct, fxam, fxtract, esp - 18 digits
559  cycles, ConvertFloat8DY, direct, examine, fxtract, esp - 18 digits
615  cycles, ConvertFloat8DR, direct, examine, fxtract, ebp - 18 digits
680  cycles, ConvertFloat8DS, direct, fxam, fyl2x, ebp - 18 digits
693  cycles, ConvertFloat8CTD, BCD-CT, fxam, fxtract, esp - 18 digits
701  cycles, ConvertFloat8BFD, BCD, fxam, fxtract, esp - 18 digits
702  cycles, ConvertFloat8BY, BCD, examine, fxtract, esp - 18 digits
703  cycles, ConvertFloat8BF, BCD, fxam, fxtract, esp - 18 digits
709  cycles, ConvertFloat8BYD, BCD, examine, fxtract, esp - 18 digits
712  cycles, ConvertFloat8BXD, BCD, fxam, fxtract, ebp - 18 digits
715  cycles, ConvertFloat8DF, direct, examine, fyl2x, ebp - 18 digits
719  cycles, ConvertFloat8BX, BCD, fxam, fxtract, ebp - 18 digits
726  cycles, ConvertFloat8CT, BCD-CT, fxam, fxtract, esp - 18 digits
1151  cycles, ConvertFloat8ZX, BCD - old - 18 digits
1163  cycles, ConvertFloat8Z, BCD -old - 18 digits
2580  cycles, ConvertFloat8DWD, direct,Save FPU, fxam, fxtract, esp -18 digits
2916  cycles, ConvertFloat8BWD, BCD, Save FPU, fxam, fxtract, ebp - 18 digits
2980  cycles, ConvertFloat8DW, direct,Save FPU, fxam, fxtract, esp -18 digits
3020  cycles, ConvertFloat8, BCD, Save FPU -old - 18 digits
3039  cycles, ConvertFloat8BW, BCD, Save FPU, fxam, fxtract, ebp - 18 digits
********** END **********
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 01, 2013, 03:00:52 AM
 :biggrin:
Here are some numbers. Any question, please... ?

note 1: if Convert... ends with 3 letters (e.g. ...DFD), the last is D=decimal places we want
note 2: the number used : _Real8_2  dq -12345678.56781234
note 3: i am using the macros from MichaelW for timing

Quote
3.14159265358979312 <--  by ConvertFloat8D?
3.14159265358979312
3.14159265358979312
3.14159265358979312
3.14159265358979312
3.14159265358979312
3.141593                            <--------- from fptoa
*** STOP - Converting PI ***
1168 cycles, ConvertFloat8ZX, _Real8_2

3015 cycles, ConvertFloat8, _Real8_2

1161 cycles, ConvertFloat8Z, _Real8_2

682 cycles, ConvertFloat8DF, _Real8_2

607 cycles, ConvertFloat8DR, _Real8_2

716 cycles, ConvertFloat8BX, _Real8_2

706 cycles, ConvertFloat8BF, _Real8_2

702 cycles, ConvertFloat8BY, _Real8_2

561 cycles, ConvertFloat8DY, _Real8_2

560 cycles, ConvertFloat8DX, _Real8_2

783 cycles, ConvertFloat8CT, _Real8_2

683 cycles, ConvertFloat8DS, _Real8_2

3059 cycles, ConvertFloat8BW, _Real8_2

2983 cycles, ConvertFloat8DW, _Real8_2

454 cycles, ConvertFloat8DFD, _Real8_2

333 cycles, ConvertFloat8DRD, _Real8_2

707 cycles, ConvertFloat8BXD, _Real8_2

702 cycles, ConvertFloat8BFD, _Real8_2

704 cycles, ConvertFloat8BYD, _Real8_2

329 cycles, ConvertFloat8DYD, _Real8_2

325 cycles, ConvertFloat8DXD, _Real8_2

706 cycles, ConvertFloat8CTD, _Real8_2

498 cycles, ConvertFloat8DSD, _Real8_2

2924 cycles, ConvertFloat8BWD, _Real8_2

2591 cycles, ConvertFloat8DWD, _Real8_2

2216 cycles, TimFloatToStr, _Real8_2

*** Press any key to get the time table ***

***** Time table *****

325  cycles, ConvertFloat8DXD, direct, fxam, fxtract, esp - 18 digits
329  cycles, ConvertFloat8DYD, direct, examine, fxtract, esp - 18 digits
333  cycles, ConvertFloat8DRD, direct, examine, fxtract, ebp - 18 digits
454  cycles, ConvertFloat8DFD, direct, examine, fyl2x, ebp - 18 digits
498  cycles, ConvertFloat8DSD, direct, fxam, fyl2x, ebp - 18 digits
560  cycles, ConvertFloat8DX, direct, fxam, fxtract, esp - 18 digits
561  cycles, ConvertFloat8DY, direct, examine, fxtract, esp - 18 digits
607  cycles, ConvertFloat8DR, direct, examine, fxtract, ebp - 18 digits
682  cycles, ConvertFloat8DF, direct, examine, fyl2x, ebp - 18 digits
683  cycles, ConvertFloat8DS, direct, fxam, fyl2x, ebp - 18 digits
702  cycles, ConvertFloat8BFD, BCD, fxam, fxtract, esp - 18 digits
702  cycles, ConvertFloat8BY, BCD, examine, fxtract, esp - 18 digits
704  cycles, ConvertFloat8BYD, BCD, examine, fxtract, esp - 18 digits
706  cycles, ConvertFloat8CTD, BCD-CT, fxam, fxtract, esp - 18 digits
706  cycles, ConvertFloat8BF, BCD, fxam, fxtract, esp - 18 digits
707  cycles, ConvertFloat8BXD, BCD, fxam, fxtract, ebp - 18 digits
716  cycles, ConvertFloat8BX, BCD, fxam, fxtract, ebp - 18 digits
783  cycles, ConvertFloat8CT, BCD-CT, fxam, fxtract, esp - 18 digits
1161  cycles, ConvertFloat8Z, BCD -my old one- 18 digits
1168  cycles, ConvertFloat8ZX, BCD - old - 18 digits
2216  cycles, TimFloatToStr or fptoa, -18 digits
2591  cycles, ConvertFloat8DWD, direct,Save FPU, fxam, fxtract, esp -18 digits
2924  cycles, ConvertFloat8BWD, BCD, Save FPU, fxam, fxtract, ebp - 18 digits
2983  cycles, ConvertFloat8DW, direct,Save FPU, fxam, fxtract, esp -18 digits
3015  cycles, ConvertFloat8, BCD, Save FPU -old - 18 digits
3059  cycles, ConvertFloat8BW, BCD, Save FPU, fxam, fxtract, ebp - 18 digits
********** END **********
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 01, 2013, 03:08:30 AM
Quote from: ToutEnMasm on April 30, 2013, 10:36:06 PM

I try a question,...
Or perhaps better than the fcvt for the crt ?
i never used it if anyone tell me how do to
               or what to do i tested it. Please, tell me what i should do.
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 01, 2013, 03:14:58 AM
Quote from: Gunther on April 30, 2013, 10:25:08 PM
Well done. :t

Gunther
Hi Gunther  :t
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 01, 2013, 03:16:06 AM
Quote from: dedndave on April 30, 2013, 08:21:04 AM
looking good, Rui   :t
Hey, Dave, are you well ? I hope so much  :t
Title: Re: Converting real8 to string
Post by: TouEnMasm on May 01, 2013, 03:53:50 AM
Quote
ConvertFloat8DS                              3.141592653589793
sprintf_s                                           3.1415926535897931

Your function write outside the buffer,at the beginning (3,4 bytes)
and show 1 digit less than sprintf_s
Title: Re: Converting real8 to string
Post by: jj2007 on May 01, 2013, 04:56:57 AM
Which means that Rui's version is better because the last digit, 1, is wrong.
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 01, 2013, 05:06:42 AM
Quote from: ToutEnMasm on May 01, 2013, 03:53:50 AM
Quote
ConvertFloat8DS                              3.141592653589793
sprintf_s                                           3.1415926535897931

Your function write outside the buffer,at the beginning (3,4 bytes)
and show 1 digit less than sprintf_s
Why it writes outside the buffer ?
The buffer MUST BE LIKE THIS:
                                                                 dd ?        <- to get the length
                                                   _buffer   db 30 dup (?)

                       dont forget this dd before the address
About PI
                if you specify 16 decimal places => 17 digits

               it gives 3.1415926535897931
               ;*** STOP - ConvertFloat8DS  PI- 17 digits ***

If you use the converter from real10 i posted we get
                            ;3.14159265358979324
                            ;*** STOP - Converting PI ***

So the last 1 is error as Jochen said. This is why i use only 15 decimal places, 16 digits in real8.

note: after conversion, if we do, for instance, mov ecx, [_buffer-4] we get
          how long is the string, we get the length. Note that the buffer is also
          null terminated.
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 01, 2013, 05:21:52 AM
Quote from: jj2007 on May 01, 2013, 04:56:57 AM
Which means that Rui's version is better because the last digit, 1, is wrong.
Very well, Jochen  :t  :eusa_clap:
Title: Re: Converting real8 to string
Post by: dedndave on May 01, 2013, 08:24:31 AM
QuoteHey, Dave, are you well ?

feeling better today, Rui - thank you for asking
i will be back to normal in a couple days or so   :P

ConvertFloat8DS                              3.141592653589793
sprintf_s                                    3.1415926535897931


this is one of the finer points where Jochen and i disagree
the last digit does not to be correct to be considered "usable"

if we look at a few more digits of Pi...
3.1415926535897932385
you can see that 3.1415926535897931 is closer to the actual value of Pi than 3.141592653589793
so, even though the digit is incorrect, it is usable
in fact, any value from 3.1415926535897931 to 3.1415926535897934 is closer than 3.141592653589793

to understand the logic in this.....
it is a 1 vs 2 digit because we happen to be converting to base 10
if we were converting to some other base, it may actually be a correct digit
should we disregard extra information, simply because we chose base 10 ?
the fact that we are converting to base 10 should be somewhat inconsequential
of course, we have to end the string someplace, so the base does make a difference

in truth, we shouldn't look at real Pi, we should look at the numbers that may be represented with extra precision   :P
400921FB_54442D17: +3.1415926535897926719
400921FB_54442D18: +3.141592653589793116
400921FB_54442D19: +3.1415926535897935601

...31 is as close as we can get with real8
Title: Re: Converting real8 to string
Post by: TouEnMasm on May 01, 2013, 02:59:09 PM
Quote
The buffer MUST BE LIKE THIS:
                                                                 dd ?        <- to get the length
                                                   _buffer   db 30 dup (?)

I suggest you modify the prototype of your function using a structure.
for example:
    STRFLOAT STRUCT
           long DWORD ?
           strf  BYTE MAX_PATH dup (?)
    STRFLOAT ENDS   

It's the first time i see something working like that:
12 00 00 00 20 33 2e 31-34 31 35 39 32 36 35 33  .... 3.141592653
0040430e  35 38 39 37 39 33 00 00-00 00 00 00 00 00 00 00  589793..........

The address passed to the function must be STRFLOAT.strf and not STRFLOAT
Not very usable







Title: Re: Converting real8 to string
Post by: jj2007 on May 01, 2013, 06:25:33 PM
Quote from: dedndave on May 01, 2013, 08:24:31 AM
this is one of the finer points where Jochen and i disagree
the last digit does not to be correct to be considered "usable"

When I made my engineer, teachers told us to cut off at the last correct digit. I doubt that has changed... ;)
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 01, 2013, 07:30:50 PM
Hi ToutEnMasm

Quote
The address passed to the function must be STRFLOAT.strf and not STRFLOAT
Not very usable
Sorry, but it is very usable for all.
       
        You have the complete code, so you can remove the length HERE:
Quote
            @@:     EXPONENTREAL_8W
                           
        _finish:    mov      eax, edi               
                       mov      edi, pRcl
                       sub      eax, edi

        _exit0:     ;mov      dword ptr [edi-4], eax    ; <--- HERE
                    mov      byte ptr [edi+eax], 0

So you have the solution to use it as you want

Quote
It's the first time i see something working like that:
12 00 00 00 20 33 2e 31-34 31 35 39 32 36 35 33
conclusion: it's the first time you look at my code.
         my library is full of this and i dont use things
         like this: STRFLOAT STRUCT (e.g. structures).
         I use EQU to do all my structures and i define
         data byte by byte in the data section. Well i
         use only my own library and not more.

To give you another example, a table of 20 pointers is this

                 dd 20         ; if we define this for unknown number of pointers
                 dd 0          ; <- no pointers in the table
_TblPtrX    dd 20 dup (?)

When i want to use it, i do something like this:

                mov     ecx, [_TblPtrX-4]
                jmp     _start
    _loop:
                mov     ebx, [_TblPtrX+ecx*4]   ; <-- ebx=pointer
                ;
                ; do something
                ;
    _start: sub     ecx, 1
                jns     short _loop
               
(note: the procs in my library follow this logic)

i think a macro may be used to define the buffer:

.data
             dd ?
label  X dup (?)

Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 01, 2013, 07:48:15 PM
Quote from: jj2007 on May 01, 2013, 06:25:33 PM
Quote from: dedndave on May 01, 2013, 08:24:31 AM
this is one of the finer points where Jochen and i disagree
the last digit does not to be correct to be considered "usable"

When I made my engineer, teachers told us to cut off at the last correct digit. I doubt that has changed... ;)
Yes Jochen, if we have operands with x significant digits and
               we do some set of operations, after that we lost significant digits
               at the end and there is no solution to that. They are lost.
               But in this case, the procedure that rounds it to 1 makes a little error
               and we should know this and cut it. I dont see another solution.
               If we use 2x significant digits, at the end, probably we have x
               significant digits correct, depends on the operations, but x we should
               have (probably they wasnt rounded).
Title: Re: Converting real8 to string
Post by: dedndave on May 01, 2013, 08:58:40 PM
during a series of operations, you should retain as much precision as possible
while it's true that round-off errors accumulate, you are only making things worse if you continually throw away digits
when the final result is met, then you can round to some precision that is meaningful

in the real world, 6 or 7 digits is more than enough for most applications
the difference between 1.000001 and 1.000002 feet is very, very small and difficult to measure

there are cases where several more digits are useful
in electronics, i find these cases often in quantifying time or frequency, for example
Title: Re: Converting real8 to string
Post by: jj2007 on May 01, 2013, 08:59:32 PM
As Dave rightly writes, it's a "finer point". For an engineer, 1.2347 implies "the number is in the range 1.234650 to 1.23474999". From a viewpoint of numbers theory, and that's Dave's strong point, "usability" has a completely different meaning, so I consider his view legitimate but, of course, we agree to disagree :icon_mrgreen:
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 01, 2013, 09:25:04 PM
Quote
you are only making things worse if you continually throw away digits
generaly, any calculator uses the same number of digits for all
          operations, it doest use 10 digits for one operation and 8 for the
          next

Quote
you can round to some precision that is meaningful
yes, meanningful is the question

Quote
For an engineer, 1.2347 implies "the number is in the range 1.234650 to 1.23474999"
Or for an error limit of 0.0001 that 1.2347 could be X, for instance,
          with 5 decimal places
         
                                 1.23465 < X < 1.23475

Well, the problem of that PI is only a problem of showing it in real8 because
FPU uses it and works in real10 and the value is the same.
Title: Re: Converting real8 to string
Post by: dedndave on May 02, 2013, 01:17:45 AM
something important to understand is that the value of Pi is known to many digits
the FPU gives you the REAL4, REAL8, or REAL10 value that it is capable of representing that is closest to Pi

when you evaluate that real number, don't expect to get digits that all match the value of Pi
the task of the routine is to evaluate the floating point value, as it is represented in the current format
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 02, 2013, 02:26:37 AM
About what we show with real8 format
-------------------------------------------------

    1. All numbers inside FPU are in real10 format.
       We cannot load or operate in real4 or real8.
       If we do that, first the real4 or real8 is
       converted to real10 inside FPU. If we move
        it to memory, there is a conversion to real4
        or real8 format.
       As far as i know.

     EDIT: we may use real4 or real8 mode but it is useless.

    2. When some procedure converts a real8 to
       string and show it, what we see may be
       the result of that procedure and not
       the number itself inside FPU. Dont
       forget that we need to do some operations
         to get the number
and the string.

       For instance, the real8 uses 52 bits+1
       implied. So we should have only 16 digits.
       Now see what happen when a procedure try
       17 digits:

Quote
000_00000_00000001 = 4.940656458412465 e-324
000_FFFFF_FFFFFFFF = 2.2250738585072009e-308
7FF_00000_00000000 =+INFINITY
FFF_00000_00000000 =-INFINITY
7FE_FFFFF_FFFFFFFF = 1.7976931348623157e+308
001_00000_00000000 = 2.2250738585072014e-308
0
1.0
2.0
3.0
4.0
5.0
6.0
7.0
8.0
9.0
0.1
0.2
0.2999999999999999
0.4
0.5
0.6
0.7
0.8
0.9
*** STOP - ConvertFloat8DF  end test digits ***
-1.1000000000000001
-11.1
-111.09999999999999
-1111.0999999999999
-11111.1
-111111.10000000001
-1111111.1000000001
-11111111.1
-111111111.09999999
-1111111111.0999999
-11111111111.1
-111111111111.10001
-1111111111111.1001
-11111111111111.1
-111111111111111.09
-1111111111111111.1
-1.1111111111111112e+16
-1.1111111111111111e+17
-2.2000000000000002
-22.199999999999999
-222.19999999999999
-2222.1999999999998
-22222.200000000001
-222222.20000000001
-2222222.2000000002
-22222222.199999999
-222222222.19999999
-2222222222.1999998
-22222222222.200001
-222222222222.20001
-2222222222222.2002
-22222222222222.199
-222222222222222.19
-2222222222222222.2
-2.2222222222222224e+16
-2.2222222222222222e+17
-3.3
-33.3
-333.3
-3333.3
-33333.3
-333333.3
-3333333.3
-33333333.3
-333333333.3
-3333333333.3
-33333333333.3
-333333333333.3
-3333333333333.3
-33333333333333.3
-333333333333333.3
-3333333333333334
-3.333333333333333e+16
-3.333333333333333e+17
*** STOP - ConvertFloat8DF ***

now, the same procedure using 16 digits
and all seems to be perfect

Quote
000_00000_00000001 = 4.94065645841247 e-324
000_FFFFF_FFFFFFFF = 2.225073858507201e-308
7FF_00000_00000000 =+INFINITY
FFF_00000_00000000 =-INFINITY
7FE_FFFFF_FFFFFFFF = 1.797693134862316e+308
001_00000_00000000 = 2.225073858507201e-308
0
1.0
2.0
3.0
4.0
5.0
6.0
7.0
8.0
9.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
*** STOP - ConvertFloat8DF  end test digits ***
-1.1
-11.1
-111.1
-1111.1
-11111.1
-111111.1
-1111111.1
-11111111.1
-111111111.1
-1111111111.1
-11111111111.1
-111111111111.1
-1111111111111.1
-11111111111111.1
-111111111111111.1
-1.111111111111111e+15
-1.111111111111111e+16
-1.111111111111111e+17
-2.2
-22.2
-222.2
-2222.2
-22222.2
-222222.2
-2222222.2
-22222222.2
-222222222.2
-2222222222.2
-22222222222.2
-222222222222.2
-2222222222222.2
-22222222222222.2
-222222222222222.2
-2.222222222222222e+15
-2.222222222222223e+16
-2.222222222222222e+17
-3.3
-33.3
-333.3
-3333.3
-33333.3
-333333.3
-3333333.3
-33333333.3
-333333333.3
-3333333333.3
-33333333333.3
-333333333333.3
-3333333333333.3
-33333333333333.3
-333333333333333
-3.33333333333333e+15
-3.33333333333333e+16
-3.33333333333333e+17
*** STOP - ConvertFloat8DF ***
Title: Re: Converting real8 to string
Post by: qWord on May 02, 2013, 02:39:02 AM
Quote from: RuiLoureiro on May 02, 2013, 02:26:37 AMWe cannot load or operate in real4 or real8.
yes, of course we can do that.

Quote from: RuiLoureiro on May 02, 2013, 02:26:37 AM
       If we do that, first the real4 or real8 is
       converted to real10 inside FPU.
which means to zero extend the fraction bits.
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 02, 2013, 02:48:43 AM
Quote from: qWord on May 02, 2013, 02:39:02 AM
Quote from: RuiLoureiro on May 02, 2013, 02:26:37 AMWe cannot load or operate in real4 or real8.
yes, of course we can do that.
What are the instructions you use to do that
               and does not imply a conversion ?
               Do you know faddreal8 or something ?
               May be it operates in real8 but i dont know.
               For instance do you know how to load PI
               in real8 ? I know fldpi only and it is real10
               as far as i know.
Title: Re: Converting real8 to string
Post by: qWord on May 02, 2013, 03:22:18 AM
simply set the precision control to 53 or 24 bit and use corresponding values and constants - loading REAL10 values is still possible, but the precision is lost after the first operation1 (due rounding to 53/24 bit).

1: +-*/sqrt()
Title: Re: Converting real8 to string
Post by: jj2007 on May 02, 2013, 03:55:21 AM
The effect can be quite significant:

NameA equ high precision        ; assign a descriptive name here
TestA proc
  FpuSet MbNear64
  mov ebx, AlgoLoops-1        ; loop e.g. 100x
  align 4
  .Repeat
        fldpi
        fld1
        fdiv
        fld1
        fadd
        fldpi
        fmul        ; 13.011197054679151860
        fstp st
        dec ebx
  .Until Sign?
  ret
TestA endp
TestA_endp:

align 16
TestB_s:
NameB equ low precision        ; assign a descriptive name here
TestB proc
  FpuSet MbNear24
  mov ebx, AlgoLoops-1        ; loop e.g. 1000x
  align 4
  .Repeat
        fldpi
        fld1
        fdiv
        fld1
        fadd
        fldpi
        fmul        ; 13.011198043823242190
        fstp st
        dec ebx
  .Until Sign?
  ret
TestB endp
TestB_endp:

Windows, for example, sets precision to 53 bits, afaik with the argument "that's faster than full precision". At least on my trusty old Celeron, the sequence above takes 7.1 cycles for both 64 and 24 bits precision:

Intel(R) Celeron(R) M CPU        420  @ 1.60GHz (SSE3)
loop overhead is approx. 2183/1000 cycles

7110    cycles for 1000 * high precision
7113    cycles for 1000 * low precision

7122    cycles for 1000 * high precision
7111    cycles for 1000 * low precision
Title: Re: Converting real8 to string
Post by: TouEnMasm on May 02, 2013, 04:08:58 AM
The address passed to the function must be STRFLOAT.strf and not STRFLOAT
Not very usable
Quote
                Sorry, but it is very usable for all.

Too much difficult ?
Here is a standard api call
Quote
invoke  ConvertFloat8DSD,addr r8,addr strfloat,4 ;min 3 digits
Title: Re: Converting real8 to string
Post by: qWord on May 02, 2013, 04:21:57 AM
Quote from: jj2007 on May 02, 2013, 03:55:21 AMAt least on my trusty old Celeron, the sequence above takes 7.1 cycles for both 64 and 24 bits precision
not surprisingly, because the operations use the full 64 bit and than round to 53/24 bit.
It might be more interesting to see the effect on transcendental and logarithmic function. Especially because the precision of these functions seems to be implementation specific: For example, Intel guarantees an error below 1 ulp only for Pentium processors or newer (transcendental functions).

EDIT: transcendental and logarithmic functions are not affected by the precision control.
Title: Re: Converting real8 to string
Post by: jj2007 on May 02, 2013, 04:31:51 AM
Quote from: qWord on May 02, 2013, 04:21:57 AMnot surprisingly, because the operations use the full 64 bit and than round to 53/24 bit.

So the question is, why do Windows (and CRT, it seems) unnecessarily sacrifice precision, if full precision is not slower? To maintain compatibility, in the negative sense, with SSE-based libraries? ::)

I can't see any reasonable argument for not using the full 80/64 bit mode...
Title: Re: Converting real8 to string
Post by: qWord on May 02, 2013, 04:35:29 AM
Quote from: jj2007 on May 02, 2013, 04:31:51 AMSo the question is, why do Windows (and CRT, it seems) unnecessarily sacrifice precision, if full precision is not slower? To maintain compatibility, in the negative sense, with SSE-based libraries? ::)
to be compatible with IEEE 754, which is required by many HLLs.(?)
Title: Re: Converting real8 to string
Post by: dedndave on May 02, 2013, 05:25:26 AM
probably the right answer
most compilers support single and double types, few offer much support for extended reals
Title: Re: Converting real8 to string
Post by: jj2007 on May 02, 2013, 05:40:54 AM
Quote from: dedndave on May 02, 2013, 05:25:26 AM
probably the right answer

Caution, the guy has 666 posts :greensml:

Jokes apart: SmplMath (http://sourceforge.net/projects/smplmath/) is REAL10, I suppose?
Title: Re: Converting real8 to string
Post by: qWord on May 02, 2013, 05:59:29 AM
Quote from: jj2007 on May 02, 2013, 05:40:54 AMJokes apart: SmplMath (http://sourceforge.net/projects/smplmath/) is REAL10, I suppose?
for x32 programs, the FPU is used by default whereas the macros does not touch the control word thus the programmer is responsible for that (of course there are helper macros for that). However, for creation of constants REAL8 is the default**.


**RTFM for details :biggrin:
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 02, 2013, 08:20:44 PM
Quote from: qWord on May 02, 2013, 03:22:18 AM
simply set the precision control to 53 or 24 bit and use corresponding values and constants - loading REAL10 values is still possible, but the precision is lost after the first operation1 (due rounding to 53/24 bit).

1: +-*/sqrt()

From Simply FPU by raymond

Control Word
-----------------
The Control Word 16-bit register is used by the programmer to select
between the various modes of computation available from the FPU

The PC field (bits 9 and 8.) or Precision Control determines to what
precision the FPU rounds results after each arithmetic instruction
in one of three ways:

00 = 24 bits (REAL4)
01 = Not used
10 = 53 bits (REAL8)
11 = 64 bits (REAL10) (this is the initialized state)

FINIT / FNINIT (Initialize FPU)
------------------------------------
This instruction initializes the FPU by resetting all
the registers and flags to their default values

    conclusion: we may work in real4 mode or in real8 mode or in real10 mode
                but the FPU is initialized in real10 mode.
                So we need to use FLDCW and FSTCW or only FSTCW to set it
                to real4 or real8

dangerous advices
------------------------

    one very important rule when we do computations is this:
    we should round the result only at the end of a series
    of calculations and NEVER after each operation.

    So, it means that the modes exist but it is useless
    (at least for me).

    i dont know if it takes less time or not (it seems not)
    working in real4 or real8 mode, but i never will use it.
    It's simple, of course.
    I will not return to 16 bits era also.  ;)
    That' all
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 02, 2013, 08:36:09 PM
ToutEnMasm

Quote
Too much difficult ?
Here is a standard api call
No. The only thing is this: i dont like to
            use structures.
            The question seems to be this: There is a
            "standard api call" and "my standard api call" !
            and i dont want to change.
            Also, it seems you like to use "proc uses ebx esi edi"
            and i dont like, i hate it.
            So it seems that the best way is to remove the instruction
            that set the length at [edi-4]. But well you should do
            as you like.  :t

           EDIT:
            About the buffer
            --------------------

            The question is this: why we need to specify a buffer
            to convert a number to string everytime we want to
            print a number if we dont need the buffer ?

            To solve this question we may do this:

            invoke  ConvertReal8DF, addr Real8, 0           <- 0=> no buffer

            (ConvertReal8DF uses ConvertFloat8DF)

            but ConvertReal8DF should return the internal buffer
            address and the question is: whats the best register ?
            may be EDX.

EDIT:
     another important question

     If i use structure as you suggest
     i destroy the logic i follow of
     «1 address 2 things». So we need
     to get the starting address of that
     structure and we need to add 4,
     exactly what i dont want to do. We dont
     need to add nothing. If i have
     the address i have the buffer
     forward and the length behind of
     that address. This is the logic.
Title: Re: Converting real8 to string
Post by: dedndave on May 02, 2013, 10:46:48 PM
in Ray's tutorial, it says that REAL10 is the precision after initialization
that is true after executing FINIT
however, windows sets it to REAL8 before handing control over to an EXE

i usually do an FINIT at the start of my FPU code   :P
i should probably just set the precision - a little more code, but faster than FINIT
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 03, 2013, 01:13:17 AM
Quote from: dedndave on May 02, 2013, 10:46:48 PM
however, windows sets it to REAL8 before handing control over to an EXE
At the start up i do finit ever, so what windows do doesnt matter
              what some other procs do doesnt matter because i dont use it,
              i dont trust.

the code i posted to test the converter we have:           
.code
;====================================================
start:
            finit

              Well, Dave, how do i use crt procs to convert a real8 to string. I want
              to test it, could you help me ?
Title: Re: Converting real8 to string
Post by: dedndave on May 03, 2013, 02:55:39 AM
sprintf can do it
http://msdn.microsoft.com/en-US/library/ybk95axf%28v=vs.80%29.aspx (http://msdn.microsoft.com/en-US/library/ybk95axf%28v=vs.80%29.aspx)

MyReal REAL8 3.14
szFormat db '%9.7lf',0
szBuffer db 20 dup (?)

        invoke  crt_sprintf,offset szBuffer,offset szFormat,MyReal
        print   offset szBuffer
        print   chr$(13,10)

i didn't test that, but it should work   :P
i am not a big "C" guy - lol

EDIT: corrected the code so it works   :biggrin:
you can play with the format string to get different digit counts
Title: Re: Converting real8 to string
Post by: Gunther on May 03, 2013, 03:31:15 AM
Hi Dave,

Quote from: dedndave on May 02, 2013, 10:46:48 PM
in Ray's tutorial, it says that REAL10 is the precision after initialization
that is true after executing FINIT
however, windows sets it to REAL8 before handing control over to an EXE

REAL10 and Windows is a very strange story. You should check that thread (http://masm32.com/board/index.php?topic=1768.0) again.

Gunther
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 03, 2013, 04:21:59 AM
I duplicate the ConvertFloat8 procedures
and replaced Float by Real. If i use ConvertFloat
in ConvertReal we dont get good results.

The new ConvertReal accept 0 to buffer address,
and, in that case, they use an internal buffer
and is null terminated only (it has not length)
and return the pointer in EDX.

These are the last results
. If ConvertReal, buffer address=0
. 3 last letters after 8 means we specify decimal places
. examine is CPU code while fxam is FPU instruction
. ebp means local variables, esp means use esp to get
variables from stack
. In ...8DZ and ...8DZD we use the value not the address

I got 7904 cycles, crt_sprintf, _Real8_2 but we cannot compare
because it uses format string.

Quote
***** Time table *****

324   cycles, ConvertFloat8DXD, direct, fxam, fxtract, esp - 15 digits
327   cycles, ConvertReal8DYD, direct, examine, fxtract, esp - 15 digits
327   cycles, ConvertFloat8DYD, direct, examine, fxtract, esp - 15 digits
328   cycles, ConvertReal8DXD, direct, fxam, fxtract, esp - 15 digits
333   cycles, ConvertReal8DRD, direct, examine, fxtract, ebp - 15 digits
333   cycles, ConvertFloat8DRD, direct, examine, fxtract, ebp - 15 digits
457   cycles, ConvertFloat8DFD, direct, examine, fyl2x, ebp - 15 digits
462   cycles, ConvertReal8DFD, direct, examine, fyl2x, ebp - 15 digits
467   cycles, ConvertFloat8DSD, direct, fxam, fyl2x, ebp - 15 digits
472   cycles, ConvertReal8DSD, direct, fxam, fyl2x, ebp - 15 digits
692   cycles, ConvertFloat8CTD, BCD-CT, fxam, fxtract, esp - 15 digits
699   cycles, ConvertReal8CTD, BCD-CT, fxam, fxtract, esp - 15 digits
703   cycles, ConvertReal8BF, BCD, fxam, fxtract, esp - 15 digits
703   cycles, ConvertFloat8BF, BCD, fxam, fxtract, esp - 15 digits
704   cycles, ConvertFloat8BXD, BCD, fxam, fxtract, ebp - 15 digits
704   cycles, ConvertFloat8BFD, BCD, fxam, fxtract, esp - 15 digits
705   cycles, ConvertFloat8BYD, BCD, examine, fxtract, esp - 15 digits
706   cycles, ConvertReal8BXD, BCD, fxam, fxtract, ebp - 15 digits
708   cycles, ConvertFloat8BX, BCD, fxam, fxtract, ebp - 15 digits
709   cycles, ConvertReal8BY, BCD, examine, fxtract, esp - 15 digits
710   cycles, ConvertReal8BFD, BCD, fxam, fxtract, esp - 15 digits
712   cycles, ConvertReal8CT, BCD-CT, fxam, fxtract, esp - 15 digits
713   cycles, ConvertReal8BYD, BCD, examine, fxtract, esp - 15 digits
714   cycles, ConvertFloat8BY, BCD, examine, fxtract, esp - 15 digits
722   cycles, ConvertFloat8CT, BCD-CT, fxam, fxtract, esp - 15 digits
725   cycles, ConvertReal8BX, BCD, fxam, fxtract, ebp - 15 digits
1066  cycles, ConvertFloat8Z, BCD -old - 15 digits
1075  cycles, ConvertFloat8DX, direct, fxam, fxtract, esp - 15 digits
1081  cycles, ConvertReal8DY, direct, examine, fxtract, esp - 15 digits
1083  cycles, ConvertFloat8DY, direct, examine, fxtract, esp - 15 digits
1084  cycles, ConvertReal8DX, direct, fxam, fxtract, esp - 15 digits
1087  cycles, ConvertFloat8DR, direct, examine, fxtract, ebp - 15 digits
1113  cycles, ConvertFloat8ZX, BCD - old - 15 digits
1114  cycles, ConvertReal8DR, direct, examine, fxtract, ebp - 15 digits
1153  cycles, ConvertReal8DZ, direct, fxam, fxtract, esp - 15 digits
1158  cycles, ConvertFloat8DZ, direct, fxam, fxtract, esp - 15 digits
1159  cycles, ConvertFloat8DZD, direct, fxam, fxtract, esp - 15 digits
1164  cycles, ConvertReal8DZD, direct, fxam, fxtract, esp - 15 digits
1202  cycles, ConvertFloat8DS, direct, fxam, fyl2x, ebp - 15 digits
1202  cycles, ConvertReal8DS, direct, fxam, fyl2x, ebp - 15 digits
1206  cycles, ConvertReal8DF, direct, examine, fyl2x, ebp - 15 digits
1211  cycles, ConvertFloat8DF, direct, examine, fyl2x, ebp - 15 digits
2585  cycles, ConvertFloat8DWD, direct,Save FPU, fxam, fxtract, esp -15 digits
2587  cycles, ConvertReal8DWD, direct,Save FPU, fxam, fxtract, esp -15 digits
2901  cycles, ConvertFloat8BWD, BCD, Save FPU, fxam, fxtract, ebp - 15 digits
2913  cycles, ConvertReal8BWD, BCD, Save FPU, fxam, fxtract, ebp - 15 digits
2917  cycles, ConvertFloat8, BCD, Save FPU -old - 15 digits
3081  cycles, ConvertFloat8BW, BCD, Save FPU, fxam, fxtract, ebp - 15 digits
3087  cycles, ConvertReal8BW, BCD, Save FPU, fxam, fxtract, ebp - 15 digits
3538  cycles, ConvertFloat8DW, direct,Save FPU, fxam, fxtract, esp -15 digits
3540  cycles, ConvertReal8DW, direct,Save FPU, fxam, fxtract, esp -15 digits
********** END **********
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 07, 2013, 02:06:47 AM
Hi
    Here we have the new (better) ASM procedures

        ConvertFloat8DR and ConvertFloat8DRD
        ConvertReal8DR and ConvertReal8DRD

    and the last

        ConvertFloat8DS and ConvertFloat8DSD
        ConvertReal8DS  and ConvertReal8DSD

    . Float version use length behind the address
    . Real     "    doesnt use length

    . Real version only: we may specify string address = 0
      The proc returns the address in EDX

        invoke  ConvertReal8DRD, addr _qword, 0, 14
        print   edx, 13,10

    To use it

        include     PowerTable.inc
        include     Convert8DR.inc
        include     Convert8DRD.inc
        include     Convert8DS.inc
        include     Convert8DSD.inc
       
        uncomment ;$DECIMALPLACES_REAL8  equ 15
       
   
    Test yourself:

            TestCycles8_10D.asm
            TestCycles8_15D.asm
            TestTime8_10D.asm
            TestTime8_15D.asm
           
            TestFloat8DR_10D.asm
            TestReal8DR_10D.asm           
            ...

    All these files are in Converter8 folder.

      note: the old Converter8 had a bug

      EDIT: see the first post
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 12, 2013, 01:50:38 AM
Hi
       i replaced Converter8 folder because i found one bug (the same) in some files
:t
Title: Re: Converting real8 to string
Post by: RuiLoureiro on May 02, 2018, 01:20:59 AM
Hi all,
         i added a new folder Converter8. See the first post and read the last EDIT.
Good luck