News:

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

Main Menu

the random of floating point data

Started by six_L, September 18, 2024, 02:13:27 AM

Previous topic - Next topic

six_L

Hi,all
FP10 MACRO value
        LOCAL vname
        .data
        align 8
        vname REAL10 value
        .code
        EXITM <vname>
ENDM

randf proc @Fmax:QWORD,@Fmin:QWORD
LOCAL num:REAL8
LOCAL @rdx:QWORD

mov @rdx,rdx

finit
fld tbyte ptr [rcx] ;Fmax
fld tbyte ptr [rdx] ;Fmin
fsub ;st0= Fmax-Fmin

invoke iRand, 0, 0000FFFFFFFFFFFFFh
mov       rcx,03FF0000000000000h
or rax,rcx
mov num,rax

fld num ;[1.0-2.0)
fld1
fsub ;[0.0-1.0)

fmul ;[0.0-1.0)*(Fmax-Fmin)
mov rdx,@rdx
fld tbyte ptr [rdx] ;Fmin
fadd ;[0.0-1.0)*(Fmax-Fmin) + Fmin
ret

randf endp

1. the above codes can create the random(REAL8) of floating point data. it's faster six times than some codes who used the "FDIV" instructs.
i used the " GdipDrawEllipse " API to test its result well. The x y(REAL4) coordinates of every little circle is the random of floating point data.
as the following png.
2. How to use
    local x11:REAL4
    local y11:REAL4
    local Fmin:REAL10
    local Fmax:REAL10
       
    finit
    fld    FP10(-3.2)
    fstp    Fmin
    fld    FP10(6.12)
    fstp    Fmax
    invoke  randf,addr Fmax,addr Fmin        ;st0=[@Fmin,@Fmax)
    fstp    x11
3. do you know the other method without "FDIV", that can create a random of floating point data?
Say you, Say me, Say the codes together for ever.

six_L

#1
nobody dispute it, I assume it's correct, goto next.
Comparison of Floating Point Data:
  if |fv_1 - fv_2| > eps, then
    {
    if (fv_1 - fv_2) > 0, then
        fv_1 > fv_2;
    if (fv_1 - fv_2) < 0, then
        fv_1 < fv_2;
    };
   if |fv_1 - fv_2| =< eps, then
    {
    fv_1 = fv_2;
    };
eps: The precision of deviation which you need to control
FpuComp proc lpSrc1:QWORD, lpSrc2:QWORD, lpEps:QWORD
    LOCAL content[136] :BYTE
    LOCAL diffFlag :BOOL

    fsave content
    jmp   src2            ;Src1
srcerr:
    frstor content
srcerr1:
    xor   rax,rax           ;error code
    ret
;----------------------------------------
;load lpSrc2 to FPU
;----------------------------------------
src2:
    mov   rax,lpSrc2
    fld   tbyte ptr [rax]
     
;----------------------------------------
;load lpSrc1 to FPU
;----------------------------------------
src1:
    mov   rax,lpSrc1
    fld   tbyte ptr [rax]

    fsub
   
    ftst            ;compare the value of ST(0) to +0.0
    fstsw ax        ;copy the Status Word containing the result to AX
    fwait            ;insure the previous instruction is completed
    sahf            ;transfer the condition codes to the CPU's flag register
    jpe srcerr        ;the comparison was indeterminate
                ;this condition should be verified first
                ;then only two of the next three conditional jumps
                ;should become necessary, in whatever order is preferred,
                ;the third jump being replaced by code to handle that case
    ja   st0_positive    ;when all flags are 0
    jb   st0_negative    ;only the C0 bit (CF flag) would be set if no error
    ;jz   st0_zero        ;only the C3 bit (ZF flag) would be set if no error   
st0_positive:
    mov diffFlag,TRUE
    jmp @F
st0_negative:
    mov diffFlag,FALSE
@@:
    fabs
   
;----------------------------------------
;load lpEps to FPU
;----------------------------------------
    mov   rax,lpEps
    fld   tbyte ptr [rax]

    fxch
    fcom
    fstsw ax                ;retrieve exception flags from FPU
    fwait
    shr   al,1              ;test for invalid operation
    jc    srcerr            ;clean-up and return result
    sahf                    ;transfer to the CPU flags
    jpe   srcerr            ;error if non comparable
    ja    greater
    jc    smaller
    mov   rax,CMP_EQU       ;|Src1-Src2| = eps
    jmp   finish

smaller:
    mov   rax,CMP_EQU    ;|Src1-Src2| < eps
    jmp   finish

greater:            ;|Src1-Src2| > eps
    .if    diffFlag == TRUE
        mov   rax,CMP_LOWER     ;Src1 < Src2
    .else
        mov   rax,CMP_GREATER   ;Src1 > Src2
    .endif

finish:
    frstor content
    ret
   
FpuComp endp

WorkerThread proc USES rbx rsi rdi Parameters:QWORD
    LOCAL szfV_1[40]:BYTE
    LOCAL szfV_2[40]:BYTE
    LOCAL szBuf[128]:BYTE
    LOCAL fIn:REAL10
    LOCAL fV_1:REAL10
    LOCAL fV_2:REAL10
    LOCAL Fmax:REAL10
    LOCAL Fmin:REAL10
    LOCAL Feps:REAL10
   
    finit   
   
    fld    FP10(-0.01)
    fstp    Fmin
    fld    FP10(0.015)
    fstp    Fmax

    invoke  randf,addr Fmax,addr Fmin        ;st0=[@Fmin,@Fmax)
    fstp    fV_1
    invoke  randf,addr Fmax,addr Fmin        ;st0=[@Fmin,@Fmax)
    fstp    fV_2
       
    ;Print

    fld    fV_1
    fstp    fIn
    invoke    RtlZeroMemory,ADDR szfV_1,sizeof szfV_1
    invoke    FpuFLtoA64,addr fIn,15, ADDR szfV_1, SRC1_REAL or STR_REG

    fld    fV_2
    fstp    fIn
    invoke    RtlZeroMemory,ADDR szfV_2,sizeof szfV_2
    invoke    FpuFLtoA64,addr fIn,15, ADDR szfV_2, SRC1_REAL or STR_REG

    invoke    RtlZeroMemory,ADDR szBuf,sizeof szBuf
    fld    FP10(0.001)
    fstp    Feps

    invoke    FpuComp,ADDR fV_1,ADDR fV_2, addr Feps
    .if    rax == CMP_EQU
        invoke    wsprintf,addr szBuf,CStr("result: ( %s )  =  ( %s )"),addr szfV_1,addr szfV_2
    .elseif rax == CMP_GREATER
        invoke    wsprintf,addr szBuf,CStr("result: ( %s )  >  ( %s )"),addr szfV_1,addr szfV_2
    .elseif rax == CMP_LOWER
        invoke    wsprintf,addr szBuf,CStr("result: ( %s )  <  ( %s )"),addr szfV_1,addr szfV_2
    .else
        invoke    wsprintf,addr szBuf,CStr("result: ( %s )"),CStr("Unknown Error!!!")
    .endif
    invoke    AddLog,addr szBuf
    invoke    AddLog,CStr(13,10,"--------------------------------------------------------------------------------------------",13,10)

    ret

WorkerThread endp
Say you, Say me, Say the codes together for ever.

six_L

#2
hi,ALL
1, Q: why will we use the random of floating point?
   A: Verify certain functions.
   Q: why were you talking to youself?
   A: our member guga has encountered the similar issue before. I don't want to update that old posts.
2, the below codes create an array that consist of the floating random(REAL10), then sort, get the sigma, mean, median,max, min.
3, if the eps is big enough, the element in array is equal with each other.
4, It's easy to change it into REAL4 and REAL8.
5, the attachment include screenshot and exe.
randf proc @Fmax:QWORD,@Fmin:QWORD
    LOCAL    num:REAL8
    LOCAL    @rdx:QWORD
   
    mov    @rdx,rdx
   
    finit
    fld    tbyte ptr [rcx]    ;Fmax
    fld    tbyte ptr [rdx]    ;Fmin
    fsub            ;st0= Fmax-Fmin
   
    invoke    iRand, 0, 0000FFFFFFFFFFFFFh
    mov          rcx,03FF0000000000000h
    or    rax,rcx
    mov    num,rax
   
    fld    num        ;[1.0-2.0)
    fld1
    fsub            ;[0.0-1.0)

    fmul            ;[0.0-1.0)*(Fmax-Fmin)
    mov    rdx,@rdx
    fld    tbyte ptr [rdx]    ;Fmin
    fadd            ;[0.0-1.0)*(Fmax-Fmin) + Fmin
    ret

randf endp

FpuComp proc lpSrc1:QWORD, lpSrc2:QWORD, lpEps:QWORD
    LOCAL content[136] :BYTE
    LOCAL diffFlag :BOOL

    fsave content
    jmp   src2            ;Src1
srcerr:
    frstor content
srcerr1:
    xor   rax,rax            ;error code
    ret
;----------------------------------------
;load lpSrc2 to FPU
;----------------------------------------
src2:
    mov   rax,lpSrc2
    fld   tbyte ptr [rax]
     
;----------------------------------------
;load lpSrc1 to FPU
;----------------------------------------
src1:
    mov   rax,lpSrc1
    fld   tbyte ptr [rax]

    fsub
   
    ftst            ;compare the value of ST(0) to +0.0
    fstsw ax        ;copy the Status Word containing the result to AX
    fwait            ;insure the previous instruction is completed
    sahf            ;transfer the condition codes to the CPU's flag register
    jpe srcerr        ;the comparison was indeterminate
                ;this condition should be verified first
                ;then only two of the next three conditional jumps
                ;should become necessary, in whatever order is preferred,
                ;the third jump being replaced by code to handle that case
    ja   st0_positive    ;when all flags are 0
    jb   st0_negative    ;only the C0 bit (CF flag) would be set if no error
    ;jz   st0_zero        ;only the C3 bit (ZF flag) would be set if no error   
st0_positive:
    mov diffFlag,TRUE
    jmp @F
st0_negative:
    mov diffFlag,FALSE
@@:
    fabs
   
;----------------------------------------
;load lpEps to FPU
;----------------------------------------
    mov   rax,lpEps
    fld   tbyte ptr [rax]

    fxch
    fcom
    fstsw ax                ;retrieve exception flags from FPU
    fwait
    shr   al,1              ;test for invalid operation
    jc    srcerr            ;clean-up and return result
    sahf                    ;transfer to the CPU flags
    jpe   srcerr            ;error if non comparable
    ja    greater
    jc    smaller
    mov   rax,CMP_EQU       ;|Src1-Src2| = eps
    jmp   finish

smaller:
    mov   rax,CMP_EQU    ;|Src1-Src2| < eps
    jmp   finish

greater:            ;|Src1-Src2| > eps
    .if    diffFlag == TRUE
        mov   rax,CMP_LOWER     ;Src1 < Src2
    .else
        mov   rax,CMP_GREATER   ;Src1 > Src2
    .endif

finish:
    frstor content
    ret
   
FpuComp endp

shell_Real10Sort Proc USES rbx rsi rdi pArrData:QWORD,dqArrNum:QWORD,pEps:QWORD,BigFristFlag:BOOL
    LOCAL TmpV1:REAL10
    LOCAL TmpV2:REAL10
    LOCAL @rcx:QWORD

    mov     rsi,pArrData
        mov     rcx,dqArrNum
        shr     rcx,1
        jnc     @1
        inc     rcx
@1:
        or      rcx,rcx
        jz      @Exit

        mov     rdi,rcx
@2:
        mov     r9,rdi
        sub     r9,rcx
@3:
        or      r9,r9
        js      @f

        mov     rax,r9
        add     rax,rcx
    mov    r8,rax
    mov    rax,10
    mul    r8
    fld    TBYTE ptr [rsi+rax]
    fstp    TmpV1
    mov    r8,r9
    mov    rax,10
    mul    r8
    fld    TBYTE ptr [rsi+rax]
    fstp    TmpV2
   

    mov    @rcx,rcx
    invoke    FpuComp,ADDR TmpV1,ADDR TmpV2, pEps
    mov    rcx,@rcx

    cmp    BigFristFlag,0 
    jne    @6 
    cmp    rax,CMP_EQU                   
    je    @4
    cmp    rax,CMP_GREATER                   
    jne    @5   
@4:   
    jmp    @f   
@5:
    jmp    @8 
@6:   
    cmp    rax,CMP_EQU                   
    je    @7   
    cmp    rax,CMP_LOWER                   
    jne    @8 
@7:   
    jmp    @f
@8:
    fld    TmpV1
    mov    r8,r9
    mov    rax,10
    mul    r8
    fstp    TBYTE ptr [rsi+rax]
     
    fld    TmpV2
        mov     rbx,r9
        add     rbx,rcx

    mov    r8,rbx
    mov    rax,10
    mul    r8
    fstp    TBYTE ptr [rsi+rax]

        sub     r9,rcx
        jmp     @3
@@:
        inc     rdi
        cmp     rdi,dqArrNum
        jb      @2

        shr     rcx,1
        jmp     @1
@Exit:
        ret   

shell_Real10Sort EndP

Mean_Real10 Proc USES rbx rsi pArrData:QWORD,dqArrNum:QWORD,plOut_FMean:QWORD
    LOCAL @Fsum:REAL10

    mov     rsi,pArrData
        xor     rbx,rbx
    finit
   
    fld    FP10(0.0)
    fstp    @Fsum
   
    fld    @Fsum
    mov    rcx,10
    .repeat
        mov    rax,rbx
        mul    rcx
        fld    TBYTE ptr [rsi+rax]
        fadd
        inc rbx
    .until rbx == dqArrNum

    fild    dqArrNum
    fdiv
    mov    rax,plOut_FMean
    fstp    TBYTE ptr [rax]

        ret   

Mean_Real10 EndP

Sigma_Real10 Proc USES rbx rsi pArrData:QWORD,dqArrNum:QWORD,plOut_Fsigma:QWORD
    LOCAL @Mean:REAL10
    LOCAL @FsqSum:REAL10

    invoke    Mean_Real10, pArrData, dqArrNum,addr @Mean
   
    mov     rsi,pArrData
        xor     rbx,rbx
   
    finit
    fld    FP10(0.0)
    fstp    @FsqSum
   
    mov    rcx,10
    .repeat
        mov    rax,rbx
        mul    rcx
        fld    TBYTE ptr [rsi+rax]
        fld    @Mean
        fsub                ;Xi-m
        fst    st(1)            ;st0->st1
        fmul                ;st0*st1, (Xi-m)^2
        fld    @FsqSum
        fadd
        fstp    @FsqSum

        inc    rbx
    .until rbx == dqArrNum
    mov    rax,dqArrNum
    dec    rax
    mov    dqArrNum,rax
    fld    @FsqSum
    fild    dqArrNum
    fdiv
    fsqrt
    mov    rax,plOut_Fsigma
    fstp    TBYTE ptr [rax]

        ret   

Sigma_Real10 EndP

WorkerThread proc USES rbx rsi rdi Parameters:QWORD
    LOCAL szTmp[40]:BYTE
    LOCAL szBuf[64]:BYTE
    LOCAL fIn:REAL10
    LOCAL Fmin:REAL10
    LOCAL Fmax:REAL10
    LOCAL NumArrayREAL10:QWORD
    LOCAL FEps:REAL10
    LOCAL SortFlag:BOOL
    LOCAL xFmean:REAL10
    LOCAL xFmedian:REAL10
    LOCAL xFmax:REAL10
    LOCAL xFmin:REAL10
    LOCAL xFsigma:REAL10
   
    invoke    iRand, 5, 9
    mov    NumArrayREAL10,rax
    xor    rdx,rdx
    mov    rcx,10    ;tbyte
    mul    rcx
    invoke    HeapAlloc,hHeap,HEAP_ZERO_MEMORY,rax
    mov    @r10array,rax
   
    finit   
   
    fld    FP10(-2.01)
    fstp    Fmin
    fld    FP10(3.299)
    fstp    Fmax

    ;create array
    xor    rbx,rbx
    mov    rsi,@r10array
    .repeat
        invoke  randf,addr Fmax,addr Fmin        ;st0=[@Fmin,@Fmax)
        xor    rdx,rdx
        mov    rax,10
        mul    rbx
        fstp    tbyte ptr [rsi+rax]

        inc    rbx
    .until rbx==NumArrayREAL10
   
    ;Print  original array
    invoke    AddLog,CStr("original array:")
    invoke    AddLog,CStr(13,10)
    xor    rbx,rbx
    .repeat
        mov    rax,10
        xor    rdx,rdx
        mul    rbx
        fld    tbyte ptr [rsi+rax]
        fstp    fIn
        invoke    RtlZeroMemory,ADDR szTmp,sizeof szTmp
        invoke    FpuFLtoA64,addr fIn,15, ADDR szTmp, SRC1_REAL or STR_REG
        invoke    RtlZeroMemory,ADDR szBuf,sizeof szBuf
        mov    rcx,rbx
        inc    rcx
        invoke    wsprintf,addr szBuf,CStr("%02d)  %s"),rcx ,addr szTmp
        invoke    AddLog,addr szBuf
        invoke    AddLog,CStr(13,10)
        inc    rbx
    .until rbx==NumArrayREAL10
    invoke    AddLog,CStr("--------------------------------------------------------------------------------------------",13,10)

    ;sorting
     mov    SortFlag,FALSE
    invoke    IsDlgButtonChecked, hMain, IDC_CHK 
    .if    rax == BST_CHECKED
        mov    SortFlag,TRUE
    .endif
    fld    FP10(0.001)
    fstp    FEps
    invoke    shell_Real10Sort,@r10array,NumArrayREAL10,addr FEps,SortFlag
       
    ;Print sorted array
    invoke    AddLog,CStr("Sorted array:")
    invoke    AddLog,CStr(13,10)
    xor    rbx,rbx
    .repeat
        mov    rax,10
        xor    rdx,rdx
        mul    rbx
        fld    tbyte ptr [rsi+rax]
        fstp    fIn
        invoke    RtlZeroMemory,ADDR szTmp,sizeof szTmp
        invoke    FpuFLtoA64,addr fIn,15, ADDR szTmp, SRC1_REAL or STR_REG
        invoke    RtlZeroMemory,ADDR szBuf,sizeof szBuf
        mov    rcx,rbx
        inc    rcx
        invoke    wsprintf,addr szBuf,CStr("%02d)  %s"),rcx ,addr szTmp
        invoke    AddLog,addr szBuf
        invoke    AddLog,CStr(13,10)
        inc    rbx
    .until rbx==NumArrayREAL10
    invoke    AddLog,CStr("--------------------------------------------------------------------------------------------",13,10)
   
    ;sigma
    invoke    Sigma_Real10,@r10array,NumArrayREAL10,addr xFsigma
   
    ;max,min
    mov    rax,NumArrayREAL10
    dec    rax
    xor    rdx,rdx
    mov    rcx,10
    mul    rcx
    .if SortFlag == TRUE
        fld    tbyte ptr [rsi+rax]
        fstp    xFmin
        fld    tbyte ptr [rsi]
        fstp    xFmax
    .else
        fld    tbyte ptr [rsi+rax]
        fstp    xFmax
        fld    tbyte ptr [rsi]
        fstp    xFmin
    .endif
   
    ;median,
    mov    rdx,NumArrayREAL10
    and    rdx,1
    .if    rdx != 0            ;
        mov    rcx,NumArrayREAL10    ;Even Number
        shr    rcx,1            ;/2
        mov    rax,10
        mul    rcx
        fld    tbyte ptr [rsi+rax]
        fstp    xFmedian
    .else                    ;Odd Number
        mov    rcx,NumArrayREAL10    ;Even Number
        dec    rcx
        shr    rcx,1            ;/2
        mov    rax,10
        mul    rcx
        fld    tbyte ptr [rsi+rax]
        fld    tbyte ptr [rsi+rax+10]
        fadd
        fld    FP10(2.0)
        fdiv
        fstp    xFmedian
    .endif


    ;mean value
    invoke    Mean_Real10,@r10array,NumArrayREAL10,addr xFmean

    ;print
    fld    xFsigma
    fstp    fIn
    invoke    RtlZeroMemory,ADDR szTmp,sizeof szTmp
    invoke    FpuFLtoA64,addr fIn,15, ADDR szTmp, SRC1_REAL or STR_REG
    invoke    RtlZeroMemory,ADDR szBuf,sizeof szBuf
    invoke    wsprintf,addr szBuf,CStr("sigma =  %s"),addr szTmp
    invoke    AddLog,addr szBuf
    invoke    AddLog,CStr(13,10)

    fld    xFmedian
    fstp    fIn
    invoke    RtlZeroMemory,ADDR szTmp,sizeof szTmp
    invoke    FpuFLtoA64,addr fIn,15, ADDR szTmp, SRC1_REAL or STR_REG
    invoke    RtlZeroMemory,ADDR szBuf,sizeof szBuf
    invoke    wsprintf,addr szBuf,CStr("median =  %s"),addr szTmp
    invoke    AddLog,addr szBuf
    invoke    AddLog,CStr(13,10)

    fld    xFmean
    fstp    fIn
    invoke    RtlZeroMemory,ADDR szTmp,sizeof szTmp
    invoke    FpuFLtoA64,addr fIn,15, ADDR szTmp, SRC1_REAL or STR_REG
    invoke    RtlZeroMemory,ADDR szBuf,sizeof szBuf
    invoke    wsprintf,addr szBuf,CStr("mean =  %s"),addr szTmp
    invoke    AddLog,addr szBuf
    invoke    AddLog,CStr(13,10)

    fld    xFmax
    fstp    fIn
    invoke    RtlZeroMemory,ADDR szTmp,sizeof szTmp
    invoke    FpuFLtoA64,addr fIn,15, ADDR szTmp, SRC1_REAL or STR_REG
    invoke    RtlZeroMemory,ADDR szBuf,sizeof szBuf
    invoke    wsprintf,addr szBuf,CStr("max =  %s"),addr szTmp
    invoke    AddLog,addr szBuf
    invoke    AddLog,CStr(13,10)

    fld    xFmin
    fstp    fIn
    invoke    RtlZeroMemory,ADDR szTmp,sizeof szTmp
    invoke    FpuFLtoA64,addr fIn,15, ADDR szTmp, SRC1_REAL or STR_REG
    invoke    RtlZeroMemory,ADDR szBuf,sizeof szBuf
    invoke    wsprintf,addr szBuf,CStr("min =  %s"),addr szTmp
    invoke    AddLog,addr szBuf
    invoke    AddLog,CStr(13,10)

    invoke    AddLog,CStr("--------------------------------------------------------------------------------------------",13,10)
   
    invoke    HeapFree,hHeap,HEAP_ZERO_MEMORY,@r10array
    ret

WorkerThread endp
Say you, Say me, Say the codes together for ever.

HSE

#3
Hi six_L!

Fantastic. Look good and very simple  :thumbsup:

Here a Masm64 SDK version.

Just to show results, test use an update of real8$ old macro and invoke macro that understand OFFSET word.

Thanks, HSE
Equations in Assembly: SmplMath

six_L

Hi,HSE
Thank you for the respones.

The sorting algorithm about floating point is more worth looking.
Say you, Say me, Say the codes together for ever.