The MASM Forum

Miscellaneous => Miscellaneous Projects => Topic started by: HSE on April 01, 2023, 01:21:16 AM

Title: Double Double Stack and SmplMath's backend
Post by: HSE on April 01, 2023, 01:21:16 AM
Hi all!!

  Playing with DoubleDouble presicion (http://masm32.com/board/index.php?topic=10678.0) a little more.

  For SmplMath real8 calculations, values are passed to functions in FPU registers.

  In a previous version values were passed to functions in FPU registers, but that use 2 registers for each value, what left few free FPU registers for calculations. SmplMath's Shunting-Yard storage can exaust registers easily in complex equations.

  In this version, values are passed to functions like for real8 functions, in an emulated FPU stack.

  SmplStack store and retrieve DoubleDouble values. By default there are 16 "registers 128 bits wide", but there is no limit to set number of registers. So far R15 GPR is used to point what in FPU could be st(0). R15 is preserved in the same stack.

  SmplStack is easily thread save.

entry_point proc
    local rrTLS()
   
    rrSTACK on
    · · ·
    Double Double calculations 
    · · ·
    rrSTACK off
    waitkey
    invoke ExitProcess,0
    ret

entry_point endp

  Library of DoubleDouble functions contain basic operations previouly used, and now also trigonometry and exponentiation functions from Taylor's series.

  Functions can be called in a direct mode and in equation mode (yet without constant creation  :biggrin:):

    ; Direct mode

    invoke rr_parse,"350.0"
    invoke rr_parse,"4.31"
    call rr_divide
    invoke rr_toSciNotation, addr buffer
    conout chr$("  "), addr buffer, lf, lf

    ; Equation mode

    fSlvSelectBackEnd RR
   
    fSlvRR dd2 = 350.0/4.31
   
    invoke_rr dd2, toSciNotation, addr buffer
    conout chr$("  "), addr buffer, lf, lf

  Like before, this test is using ML64, and Masm64 extension of Masm32 SDK for string functions.

Regards, HSE.
Title: Re: Double Double Stack and SmplMath's backend
Post by: HSE on April 02, 2023, 08:23:18 AM
Added a little parser to create DoubleDouble precision constants at assembling time:
@ParseRR macro Expression:=< >
   
    prr_text textequ <> 
    prr_textbp textequ <> 
    prr_textap textequ <>
    prr_texte textequ <>
     
    prr_first = 1
    prr_exp  = 0
    ceval val_hi = 0
    ceval val_lo = 0
    numDigits = 0 
    FORC char,<&Expression>
        IF prr_first
            prr_negative INSTR 1,<->,<&char>
            prr_first = 0
            IFE prr_negative
                goto other
            ENDIF
        ELSE
    :other   
            prr_cntr INSTR 1,<0123456789>,<&char>
            IF prr_cntr
                IF prr_exp
                    prr_texte CATSTR prr_texte,<&char>                 
                ELSE
                    mreal_rr_multiply val_hi, val_lo,mreal_TEN_hi, mreal_TEN_lo, val_hi, val_lo
                    ceval d2_hi = <&char>
                    ceval d2_lo = 0
                    mreal_rr_add val_hi, val_lo, d2_hi, d2_lo, val_hi, val_lo
                    numDigits = numDigits + 1
                ENDIF
            ENDIF
            hay_point INSTR 1,<.>,<&char>
            IF hay_point
                numBeforeDec = numDigits
            ENDIF
            hay_e INSTR 1,<e>,<&char>
            IF hay_e
                prr_exp = 1
            ENDIF
        ENDIF
    ENDM
 
    IF @SizeStr(%prr_texte)
        valexp = %prr_texte
    ELSE
        valexp = 0
    ENDIF   
    numDecPlaces = numDigits - numBeforeDec - valexp
    IF numDecPlaces eq 0
        EXITM <@CatStr(<{>,MR_TO_IEEE(<REAL8>,val_hi), <,>, MR_TO_IEEE(<REAL8>,val_lo),<}>)> 
    ELSEIF numDecPlaces gt 0
        mreal_rr_pows mreal_TEN_hi, mreal_TEN_lo, numDecPlaces, scale_hi, scale_lo
        mreal_rr_divide val_hi, val_lo, scale_hi, scale_lo, res_hi, res_lo
    ELSEIF numDecPlaces lt 0
        numDecPlaces = numDecPlaces * -1
        mreal_rr_pows mreal_TEN_hi, mreal_TEN_lo, numDecPlaces, scale_hi, scale_lo
        mreal_rr_multiply val_hi, val_lo, scale_hi, scale_lo, res_hi, res_lo
    ENDIF
    IF prr_negative
        mreal_rr_negate val_hi, val_lo, res_hi, res_lo
        EXITM <@CatStr(<{>,MR_TO_IEEE(<REAL8>,res_hi), <,>, MR_TO_IEEE(<REAL8>,res_lo),<}>)> 
    ENDIF
    ;echo_mreal res_hi,18
    ;echo_mreal res_lo,18
    EXITM <@CatStr(<{>,MR_TO_IEEE(<REAL8>,res_hi), <,>, MR_TO_IEEE(<REAL8>,res_lo),<}>)> 
endm

The parser make DoubleDouble precision calculations using an extension of qWord's MREAL macros (https://github.com/ASMHSE/mreal-macros), for example:
mreal_rr_multiply macro _this_hi, _this_lo, tmpy_hi, tmpy_lo, res_hi, res_lo
    ceval _C = mreal_SPLIT * _this_hi
    MR_ROUND _C, _C,53,<bits>
    ceval hx = _C - _this_hi
    ceval _c = mreal_SPLIT * tmpy_hi
    ceval hx = _C - hx
    ceval tx = _this_hi - hx
    ceval hy = _c - tmpy_hi
    ceval _C = _this_hi * tmpy_hi
    ceval hy = _c - hy
    ceval ty = tmpy_hi - hy
    ceval _c = hx * hy - _C + hx * ty + tx * hy + tx * ty + (_this_hi * tmpy_lo + _this_lo * tmpy_hi)
    ceval res_hi = _C + _c
    MR_ROUND res_hi, res_hi,53,<bits>
    ceval hx = _C - res_hi
    ceval res_lo = _c + hx
endm

Now you can write constansts in equations (see first post).

:biggrin: 350.0 is easy because you can directly store like <350.0, 0.0>.

But the simple 4.31 is <4.30999999999999960e+000, 3.90798504668055100e-016>

Update in first post.
Title: Re: Double Double Stack and SmplMath's backend
Post by: daydreamer on April 03, 2023, 02:44:46 PM
Great Héctor  :thumbsup:
Possible with 256 bit AVX: quadruple double precision?
Title: Re: Double Double Stack and SmplMath's backend
Post by: HSE on April 03, 2023, 10:58:18 PM
Hi daydreamer,

Quote from: daydreamer on April 03, 2023, 02:44:46 PM
Possible with 256 bit AVX: quadruple double precision?

:biggrin: I think quad-double hardly ever was implemented because you increase precision but range (the exponents) always remains that of Real8.

HSE
Title: Re: Double Double Stack and SmplMath's backend
Post by: jj2007 on April 03, 2023, 11:19:05 PM
Quote from: HSE on April 03, 2023, 10:58:18 PMI think quad-double hardly ever was implemented because you increase precision but range (the exponents) always remains that of Real8.

±5.0 × 10−324 to ±1.7 × 10308 should be enough for most applications :cool:
Title: Re: Double Double Stack and SmplMath's backend
Post by: HSE on April 03, 2023, 11:47:49 PM
 :thumbsup: Close to Real8 range.
      (if you accept to lost precision)
Title: Re: Double Double Stack and SmplMath's backend
Post by: HSE on July 21, 2023, 04:13:09 AM
Hi all!

A line was missing in Parser Function, failing when there is an exponent:
    invoke rr_parse,chr$("1.256e100")
    pop_rr dd1

And a line messed in Parser Macro, also failing with exponent:
    fSlvRR dd1 = 3.3e17
Updated in first post.

Regards, HSE.