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?
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
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
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
Hi,HSE
Thank you for the respones.
The sorting algorithm about floating point is more worth looking.