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.
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.
Great Héctor :thumbsup:
Possible with 256 bit AVX: quadruple double precision?
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
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 × 10
308 should be enough for most applications :cool:
:thumbsup: Close to Real8 range.
(if you accept to lost precision)
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.