News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Converting string to real4

Started by RuiLoureiro, April 15, 2013, 04:35:25 AM

Previous topic - Next topic

RuiLoureiro

#15
Quote from: dedndave on April 24, 2013, 04:35:00 AM
the problem is, you are looking at info for the REAL10 format
there are 10 bytes, or 5 words - you are looking at 4 words   :P
the first column shows the exponent, bits 78 to 64
the second column shows the significand, bits 63 to 0

+infinity = 7FFF_8000_0000_0000_0000
-infinity = FFFF_8000_0000_0000_0000

Ohh yes it is
                    ; --------------------------
                    ;     examine real 10
                    ; --------------------------
Quote
                    mov      eax, dword ptr [ebx+0]
                    mov      ecx, dword ptr [ebx+4]
                   
                    mov      dx,  word ptr [ebx+8]
                    shl        dx, 1                                ; move sign -> carry
                    cmp      dx, 0FFFEH
                    je         short _isNAN                    ; All = 1
                    ;
                    ;
                    ;
                    and     ecx, 80000000h
                    jnz     short _start
                    jz      _iszero

                    ; -------------------
                    ;    It is NAN
                    ; -------------------
        _isNAN: or      eax, eax
                    jnz     _erro1                  <--------- NAN

                    xor     ecx, 80000000h
                    jnz     _erro1                  <--------- NAN

                    mov     dx,  word ptr [ebx+8]

                    mov     al, '+'
   
                    and     dx, 8000H                   
                    jz      _isinfinity     ; is +infinity

                    ;------------
                    ; is -infinity
                    ; ------------
                    mov     al, '-'                   
                    jmp     _isinfinity   ; is -infinity
                                       
                    ; --------------------
                    ;    test for sign
                    ; --------------------
        _start:  mov     dx, word ptr [ebx+8]

dedndave

REAL10
  Exponent                     Significand                  Meaning

    0000       0000_0000_0000_0000                          Signed Zero
               0000_0000_0000_0001 to 7FFF_FFFF_FFFF_FFFF   Signed Denormal
               8000_0000_0000_0000 to FFFF_FFFF_FFFF_FFFF   Signed Pseudo-Denormal

0001 to 7FFE   0000_0000_0000_0000 to 7FFF_FFFF_FFFF_FFFF   Invalid
               8000_0000_0000_0000 to FFFF_FFFF_FFFF_FFFF   Signed Normal

    7FFF       0000_0000_0000_0000 to 7FFF_FFFF_FFFF_FFFF   Invalid
               8000_0000_0000_0000                          Signed Infinity
               8000_0000_0000_0001 to BFFF_FFFF_FFFF_FFFF   Signaling NaN
               C000_0000_0000_0000                          Indefinite Quiet NaN
               C000_0000_0000_0001 to FFFF_FFFF_FFFF_FFFF   Quiet NaN


you might find it easier to deal with the exponent like this, rather than using SHL
        movzx   edx,  word ptr [ebx+8]
        mov     ecx, dword ptr [ebx+4]
        mov     _Sign, edx                     ;a local variable to save the sign for later
        mov     eax, dword ptr [ebx+0]
        and     dx, 7FFFh
        je      Test_Exp_0_Special_Values

        cmp     dx, 7FFFh
        je      Test_Exp_7FFF_Special_Values

        test    ecx, ecx
        jns     Invalid_Value

the only special values for exponent = 0 are signed zeros
so - if the significand is not zero, increment the exponent and evaluate it the same as a normal

all values are special for exponent = 7FFF

sooner or later, you are going to want the exponent with bit 0 right-justified   :P

dedndave

#17
the one i am writing will evaluate all reals
you pass it a pointer to the real, and a wParam
it uses an internal buffer for the string - so the caller doesn't need to make one

the high word of wParam is used to determine the type
0 = REAL10
1 = REAL4
2 = REAL8

the low word of wParam allows them to limit the number of signifigant digits

here is my outline that i am using to write the code
maybe it will help you   :t
;*****************************************************

; Operational Overview
;
;The routine is divided into the following seven sections.
;Each section begins with a detailed outline.
;
; 1. Strategy
; 2. Left-Shift Scaling (for large values)
; 3. Exponential Scaling (for small values)
; 4. Base Conversion
; 5. Scientific Formatting
; 6. Routine Exit
; 7. Special Values

;*****************************************************

;Strategy Section
;
; 1. validate wParam high word and determine type of real to be processed
;    a. type:
;       0 for real10
;       1 for real4
;       2 for real8
;    b. any other value yields an error result:
;       EAX = ERROR_INVALID_PARAMETER = 87
;       ECX = 0
;       EDX = pointer to null string
; 2. if wParam low word is 0, set the default number of digits
;    a. default maximum signifigant digits:
;       21 digits for real10
;       9 digits for real4
;       17 digits for real8
; 3. store the sign for later use (refer to the Scientific Format code section)
;    a. stored in a local variable: bit 31 clear if positive, set if negative
; 4. filter out special values (refer to the Special Values code section)
;    a. for all real types:
;       signed 0
;       signed infinity
;    b. additional special value for real4 and real8 types:
;       NaN
;    c. additional special values for real10 type:
;       Indefinite QNaN
;       QNaN
;       SNaN
;       Invalid
; 5. standardize numerical format, allowing all types to be processed the same way
;    a. sign stored in a local variable (see part 3)
;    b. exponent:
;       real10 exponent is 15 bits of the high word, sign bit removed
;       real4 exponent is 8 bits of the high word, sign bit removed, shifted right by 7
;       real8 exponent is 11 bits of the high word, sign bit removed, shifted right by 4
;    c. qword significand:
;       for real10 type, integer bit 63 is explicit
;       for real4 type, integer bit 23 is set if it is not a denormal value
;       for real8 type, integer bit 52 is set if it is not a denormal value
; 6. adjust exponent by subtracting "fraction-adjusted" bias
;    a. for denormal values, we add one to the exponent, then process as a normal
;    b. fraction-adjusted bias:
;       real10 bias is 16383, fraction-adjusted bias is 16383+63 = 16446
;       real4 bias is 127, fraction-adjusted bias is 127+23 = 150
;       real8 bias is 1023, fraction-adjusted bias is 1023+52 = 1075
; 7. branch according to exponent
;    a. if the fraction-adjusted exponent is 0, no scaling required, do base conversion
;    b. if the fraction-adjusted exponent is positive, scale by left-shifting
;    c. if the fraction-adjusted exponent is negative, scale by exponentiation

;*****************************************************

RuiLoureiro

Quote from: dedndave on April 24, 2013, 04:54:40 AM

you might find it easier to deal with the exponent like this, rather than using SHL
        movzx   edx,  word ptr [ebx+8]
        mov     ecx, dword ptr [ebx+4]
        mov     _Sign, edx                     ;a local variable to save the sign for later
        mov     eax, dword ptr [ebx+0]
        and     dx, 7FFFh
        je      Test_Exp_0_Special_Values

        cmp     dx, 7FFFh
        je      Test_Exp_7FFF_Special_Values

        test    ecx, ecx
        jns     Invalid_Value


Hummm Dave, i dont follow your argument. I remove the sign and if i may i go to
start. I read it again and i dont want to change it, for now.

Quote
the only special values for exponent = 0 are signed zeros
so - if the significand is not zero, increment the exponent and evaluate it the same as a normal
no, i dont want to follow this. What is there is what is there.
...

Quote
sooner or later, you are going to want the exponent with bit 0 right-justified   :P
no, depends and we have it in a variable
                You may replace test by or, i dont use it

dedndave

Quotethe only special values for exponent = 0 are signed zeros
so - if the significand is not zero, increment the exponent and evaluate it the same as a normal
Quoteno, i dont want to follow this. What is there is what is there.

from the computation guide...
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_math.html

denormals (aka subnormals) and pseudo-denormals are stored with the exponent adjusted to 0
to make them evaluate the same as a normal, add 1 to the exponent
the 0 value is used to signal that they are not normals

REAL4 and REAL8 denormals are similar, but you do not set the implicit integer bit




RuiLoureiro

Hi Dave,
         Yesterday i had not enough time to pay attention
         to some details. I wrote 14 procs to real10 and real8
         and tested it.
         
         Here, Table 1 is your table and
         Table 2 is what i want to do
Table 1
Quote
REAL10
  Exponent                     Significand                  Meaning

    0000   0000_0000_0000_0000                          Signed Zero
               0000_0000_0000_0001 to 7FFF_FFFF_FFFF_FFFF   Signed Denormal
               8000_0000_0000_0000 to FFFF_FFFF_FFFF_FFFF   Signed Pseudo-Denormal

0001 to 7FFE   0000_0000_0000_0000 to 7FFF_FFFF_FFFF_FFFF   Invalid
               8000_0000_0000_0000 to FFFF_FFFF_FFFF_FFFF   Signed Normal

    7FFF       0000_0000_0000_0000 to 7FFF_FFFF_FFFF_FFFF   Invalid
               8000_0000_0000_0000                          Signed Infinity
               8000_0000_0000_0001 to BFFF_FFFF_FFFF_FFFF   Signaling NaN
               C000_0000_0000_0000                          Indefinite Quiet NaN
               C000_0000_0000_0001 to FFFF_FFFF_FFFF_FFFF   Quiet NaN

Table 2
Quote
REAL10
  Exponent                     Significand                  Meaning

    0000             0000_0000_0000_0000                          ZERO
                         0000_0000_0000_0001 to 7FFF_FFFF_FFFF_FFFF   Denormal
                         8000_0000_0000_0000 to FFFF_FFFF_FFFF_FFFF   Pseudo-Denormal

0001 to 7FFE     0000_0000_0000_0000 to 7FFF_FFFF_FFFF_FFFF <-ERROR_1 (*)
                          8000_0000_0000_0000 to FFFF_FFFF_FFFF_FFFF <------- REAL10

    7FFF             0000_0000_0000_0000 to 7FFF_FFFF_FFFF_FFFF   ERROR_1
                        8000_0000_0000_0000                                           Infinity
                        8000_0000_0000_0001 to BFFF_FFFF_FFFF_FFFF   ERROR_1
                        C000_0000_0000_0000                                        ERROR_1
                        C000_0000_0000_0001 to FFFF_FFFF_FFFF_FFFF   ERROR_1
(*) particular case

        To follow it better the 10 bytes pointed by EBX are:

                        string pointed by edi
                       
                        mov     eax, [ebx+0]
                        mov     ecx, [ebx+4]
                        mov     dx,  [ebx+8]     ; s+exponent

        We have some ways to decode it. You have your own, of course.
        But my idea is to think that the number we have is a real10 number.
        It is not error, it is not infinity, it is not NAN, etc, it
        is a real10 number.

Quote
        In this way, first, we test exponent for 7FFFh.

          . If exponent=7FFFh i assume "it_is_NAN", so... we have error/infinity.
         
          . If ECX has sign bit set:

                    . If exponent <> 0  -> is real10  -> goto _start
                    . If                =  0  -> is Pseudo-Denormal
       
          . If ECX has NO sign bit set:

                    . If exponent <> 0  -> is error
                    . If                =  0  -> is Zero/Denormal
                   
            Is zero if  «or  eax,ecx» is zero.
           
---------------------------------------------------------------------------------------
        The problem is: what to do if it is Pseudo-Denormal or Denormal
        and why. If we need to change the exponent, we need a local
        variable to set the 10 bytes from where we load it to FPU.
        The problem of sign: we may set it to string immediately.
        If we use BCD we dont need the sign, but we may set it to
        string immediately, also. If it is error, we remove it,
        no problems: start at edi-1. If it is zero, also.

        I think it is correct, now.

dedndave

what's it called ?
"lemniscate"
you'd think i would have known that   :(

ASCII = 0ECh, if you have the right font
in console mode, it displays correctly
but, if i redirect it to a text file, it is the letter "i"   :redface:
i don't like that, because it's too close to the lower case "iota", which is used for (-1)1/2




RuiLoureiro

#22
Here 3 macros to examine real10
Is there any problem ?
I like EXAMINE3REAL10.

Quote
EXAMINE1REAL10  MACRO       ; 39 instructions

                ; --------------------------
                ;          examine
                ; --------------------------
                mov     eax, dword ptr [ebx+0]                               
                mov     ecx, dword ptr [ebx+4]
                   
                mov     dx,  word ptr [ebx+8]
                shl     dx, 1                      ; remove sign to carry
                cmp     dx, 0FFFEH                 ; <=> 7FFFh
                je      short _isNAN               ; all = 1
               
                ; --------------------
                ;   it is not NAN
                ; --------------------
                and     ecx, 80000000h
                jz      short _noECXsign
               
                ; --------------------------
                ; It must be Real10/Denormal
                ; --------------------------                 
                or      dx, dx
                jnz     short _start
                jmp     _isDenormal
               
               
    _noECXsign: or      dx, dx
                jnz     _erro1
               
                ; --------------------
                ; may be Zero/Denormal
                ; --------------------
                or      eax, ecx               
                jz      _iszero

                ; --------------------
                ;   may be Denormal
                ;  or Pseudo-Denormal
                ; --------------------
    _isDenormal:mov     eax, dword ptr [ebx+0]
                lea     ebx, Real10Buf
                ;
                mov     [ebx+0], eax
                mov     [ebx+4], ecx
                mov     dx, word ptr [ebx+8]
                mov     dl, 1
                mov     word ptr [ebx+8], dx
                jmp     _start
               
                ; -------------------
                ;    It is NAN
                ; -------------------
    _isNAN:     or      eax, eax
                jnz     _erro1
               
                ; ---------------------
                ;       eax= 0
                ; ecx must be 80000000h
                ;    to be infinity
                ; ---------------------
                xor     ecx, 80000000h
                jnz     _erro1
               
                ; --------------
                ; It is infinity
                ; -------------- 
                mov     dx,  word ptr [ebx+8]

                mov     al, '+'
   
                and     dx, 8000H                   
                jz      _isinfinity     ; is +infinity

                ;------------
                ; is -infinity
                ; ------------
                mov     al, '-'                   
                jmp     _isinfinity     ; is -infinity
                                       
                ; --------------------
                ;    test for sign
                ; --------------------
    _start:     mov     al, ' '
                ;
                and     word ptr [ebx+8], 8000H   
                jz      short @F
                ;
                mov     al, '-'
               
        @@:     mov     byte ptr [edi], al
                add     edi, 1
                   
                ; ---------------------
                ; start load the real 10
                ; ---------------------
                fld      tbyte ptr [ebx]    ; st(0) = X     
ENDM
; --------------------------------------------------------------
another one

Quote
EXAMINE2REAL10  MACRO       ; 37 instructions
                ; --------------------------
                ;          examine
                ; --------------------------
                mov     eax, dword ptr [ebx+0]                               
                mov     ecx, dword ptr [ebx+4]
                   
                mov     dx,  word ptr [ebx+8]
                shl     dx, 1                      ; remove sign -> carry
                cmp     dx, 0FFFEH
                je      short _isNAN               ; all = 1

                or      dx, dx
                jnz     short _ECXsign
                               
                ; --------------------
                ; may be Zero/Denormal
                ; --------------------
                or      eax, ecx               
                jz      _iszero
               
                ; --------------------
                ;    is Denormal
                ; or Pseudo-Denormal
                ; --------------------
                mov     eax, dword ptr [ebx+0]
                lea     ebx, Real10Buf
                ;
                mov     [ebx+0], eax
                mov     [ebx+4], ecx
                mov     dx, word ptr [ebx+8]
                mov     dl, 1
                mov     word ptr [ebx+8], dx               
                jmp     _start
               
    _ECXsign:   and     ecx, 80000000h
                jnz     short _start
                jmp     _erro1
   
                ; -------------------
                ;    It is NAN
                ; -------------------
    _isNAN:     or      eax, eax
                jnz     _erro1
               
                ; ---------------------
                ;       eax= 0
                ; ecx must be 80000000h
                ;    to be infinity
                ; ---------------------
                xor     ecx, 80000000h
                jnz     _erro1
               
                ; --------------
                ; It is infinity
                ; -------------- 
                mov     dx,  word ptr [ebx+8]

                mov     al, '+'
   
                and     dx, 8000H                   
                jz      _isinfinity     ; is +infinity

                ;------------
                ; is -infinity
                ; ------------
                mov     al, '-'                   
                jmp     _isinfinity     ; is -infinity
                                       
                ; --------------------
                ;    test for sign
                ; --------------------
    _start:     mov     al, ' '
                ;
                and     word ptr [ebx+8], 8000H   
                jz      short @F
                ;
                mov     al, '-'
               
        @@:     mov     byte ptr [edi], al
                add     edi, 1
                   
                ; ---------------------
                ; start load the real 10
                ; ---------------------
                fld      tbyte ptr [ebx]    ; st(0) = X     
ENDM
; ------------------------------------------------------------
another one

Quote
EXAMINE3REAL10  MACRO       ; 31 instructions
                ; --------------------------
                ;          examine
                ; --------------------------
                mov     ecx, dword ptr [ebx+4]

                mov     al, 20h                   
                mov     dx,  word ptr [ebx+8]
                shl     dx, 1                      ; remove sign -> carry
                jnc     short @F
                mov     al, '-'
                ;
        @@:     mov     byte ptr [edi], al
                add     edi, 1
               
                mov     eax, dword ptr [ebx+0]
               
                cmp     dx, 0FFFEH
                je      short _isNAN               ; all = 1

                or      dx, dx
                jnz     short _ECXsign
                               
                ; --------------------
                ; may be Zero/Denormal
                ; --------------------
                or      eax, ecx               
                jz      _iszero
               
                ; --------------------
                ;    is Denormal
                ; or Pseudo-Denormal
                ; --------------------
                mov     eax, dword ptr [ebx+0]
                lea     ebx, Real10Buf          ; local 10 bytes

                ; --------------------------------
                ; the sign is alredy in the buffer
                ; --------------------------------
                add     dx, 1
                mov     [ebx+0], eax
                mov     [ebx+4], ecx
                mov     word ptr [ebx+8], dx
                jmp     _start
               
    _ECXsign:   and     ecx, 80000000h
                jnz     short _start
                jmp     _erro1
   
                ; -------------------
                ;    It is NAN
                ; -------------------
    _isNAN:     or      eax, eax
                jnz     _erro1
               
                ; ---------------------
                ;       eax= 0
                ; ecx must be 80000000h
                ;    to be infinity
                ; ---------------------
                xor     ecx, 80000000h
                jnz     _erro1
               
                ; --------------
                ; It is infinity
                ; -------------- 
                jmp     _isinfinity

                ; ---------------------
                ; start load the real 10
                ; ---------------------
    _start:     fld      tbyte ptr [ebx]    ; st(0) = X
ENDM

Gunther

Hi Dave,

Quote from: dedndave on April 25, 2013, 01:00:35 AM
what's it called ?
"lemniscate"

yes, that's the lemniscate; a very interesting curve.

Gunther
You have to know the facts before you can distort them.

RuiLoureiro

#24
Quote from: dedndave on April 25, 2013, 01:00:35 AM
what's it called ?
"lemniscate"
you'd think i would have known that   :(

ASCII = 0ECh, if you have the right font
in console mode, it displays correctly
but, if i redirect it to a text file, it is the letter "i"   :redface:
i don't like that, because it's too close to the lower case "iota", which is used for (-1)1/2




:biggrin:
                     i guess you like geometric figures ! :greensml:

dedndave

Quote from: RuiLoureiro on April 25, 2013, 01:10:22 AM
i guess you like geometric fugures ! :greensml:

oh, i do !
especially conic sections   :P
oh - and boobs, of course (.)(.)

dedndave

Rui, the only thing i would mention is.....

the REAL10 invalid values will never be generated by the FPU
however, NaN's (including indefinites) can be generated by the FPU


dedndave


dedndave

hi Rui,

well, i have decimal digits - i just need to work on rounding and scientific format   :P
0000_00000000_00000000: 00000000 00000002 +0
8000_00000000_00000000: 00000000 00000002 -0
0000_00000000_00000001: 00000000 00002CE7 364519953188247460252
0000_7FFFFFFF_FFFFFFFF: 00000000 00002CFA 336210314311209350589
0000_80000000_00000000: 00000000 00002CFA 336210314311209350626
0000_FFFFFFFF_FFFFFFFF: 00000000 00002CFA 672420628622418701216
0001_00000000_00000000: 00000006 00000007 Invalid
7FFE_7FFFFFFF_FFFFFFFF: 00000006 00000007 Invalid
0001_80000000_00000000: 00000000 00002CFA 336210314311209350626
4000_C90FDAA2_2168C235: 00000000 0000003F 314159265358979323851
7FFE_FFFFFFFF_FFFFFFFF: 00000000 00001345 118973149535723176502
7FFF_00000000_00000000: 00000006 00000007 Invalid
7FFF_7FFFFFFF_FFFFFFFF: 00000006 00000007 Invalid
7FFF_80000000_00000000: 00000001 00000002 +∞
FFFF_80000000_00000000: 00000001 00000002 -∞
7FFF_80000000_00000001: 00000005 00000004 SNaN
7FFF_BFFFFFFF_FFFFFFFF: 00000005 00000004 SNaN
7FFF_C0000000_00000000: 00000003 0000000F Indefinite QNaN
7FFF_C0000000_00000001: 00000004 00000004 QNaN
7FFF_FFFFFFFF_FFFFFFFF: 00000004 00000004 QNaN

00000000: 00000000 00000002 +0
80000000: 00000000 00000002 -0
00000001: 00000000 00000069 140129846432481707092
007FFFFF: 00000000 00000070 117549421069244107548
00800000: 00000000 00000070 117549435082228750796
BF800000: 00000000 00000018 100000000000000000000
7F7FFFFF: 00000000 00000027 340282346638528859811
7F800000: 00000001 00000002 +∞
FF800000: 00000001 00000002 -∞
7F800001: 00000002 00000003 NaN
7FFFFFFF: 00000002 00000003 NaN

00000000_00000000: 00000000 00000002 +0
80000000_00000000: 00000000 00000002 -0
00000000_00000001: 00000000 000002EF 494065645841246544176
000FFFFF_FFFFFFFF: 00000000 000002FF 222507385850720088902
00100000_00000000: 00000000 000002FF 222507385850720138309
BFF00000_00000000: 00000000 00000035 100000000000000000000
7FEFFFFF_FFFFFFFF: 00000000 00000135 179769313486231570814
7FF00000_00000000: 00000001 00000002 +∞
FFF00000_00000000: 00000001 00000002 -∞
7FF00000_00000001: 00000002 00000003 NaN
7FFFFFFF_FFFFFFFF: 00000002 00000003 NaN


after the hex real:, there are 2 dwords in hex
the first one is the status returned in EAX
the second one is the string length returned in ECX
although, i have truncated them all to 21 digits for testing
EDX points to the string