=====Using 32-bit floating point values=====
//by Jon Ripley, August 2006//\\ \\ //BBC BASIC for Windows// stores floating point numbers in 40-bit and 64-bit resolutions and has no built-in support for 32-bit (single precision) floating point numbers. When using the Windows API and functions in third party DLLs it is sometimes necessary to use 32-bit floating point numbers. To ensure that single precision numbers are correctly passed to **SYS** calls they must be stored in integer variables which are also 32-bits wide.\\ \\ The following two functions are required to perform the necessary conversions:\\ \\
* **FN_ConvertToSingle** converts a number to a single precision floating point value
* **FN_ConvertFromSingle** converts a number from a single precision floating point value
\\
DEF FN_ConvertToSingle(A#)
LOCAL A%,P%
PRIVATE F%
IF F%=0 THEN
DIM P% 10
[OPT 2
.F%
mov esi,[ebp+2] ; esi = pointer to A#
mov edi,[ebp+7] ; edi = pointer to A%
fld qword [esi] ; load indirect 64 bit real from esi
fstp dword [edi] ; store indirect 32 bit real to edi
ret
]
ENDIF
A#*=1.0#
CALL F%,A#,A%
=A%
DEF FN_ConvertFromSingle(A%)
LOCAL A#,P%
PRIVATE F%
IF F%=0 THEN
DIM P% 10
[OPT 2
.F%
mov esi,[ebp+2] ; esi = pointer to A%
mov edi,[ebp+7] ; edi = pointer to A#
fld dword [esi] ; load indirect 32 bit real from esi
fstp qword [edi] ; store indirect 64 bit real to edi
ret
]
ENDIF
CALL F%,A%,A#
=A#
\\ **Note:** **FN_ConvertToSingle** is the same routine as **FN_f4** from the supplied //D3DLIB// library, but the assembly language has been commented and the name has been changed for clarity.\\
----
\\ //by Richard Russell, November 2006//\\ \\ The above routines use assembly language code to perform the conversion. An alternative is to use Windows API functions as follows:\\ \\
DEF FN_ConvertToSingle(A#)
LOCAL A%
PRIVATE F%
IF F% = 0 THEN
SYS "LoadLibrary", "OLEAUT32.DLL" TO F%
SYS "GetProcAddress", F%, "VarR4FromR8" TO F%
ENDIF
A#*=1.0#
SYS F%,!^A#,!(^A#+4),^A%
=A%
DEF FN_ConvertFromSingle(A%)
LOCAL A#
PRIVATE F%
IF F% = 0 THEN
SYS "LoadLibrary", "OLEAUT32.DLL" TO F%
SYS "GetProcAddress", F%, "VarR8FromR4" TO F%
ENDIF
SYS F%,A%,^A#
=A#
If speed is critical, use this conversion function:\\
DEF FN_ConvertToSingle(A#)=USR(f4)
where the routine **f4** has been assembled previously as follows:\\
.f4
mov ecx,[^A#+4]
test ecx,&FFFFFF00
jnz f4d
movzx ecx,cl
jecxz f4i
mov edx,[^A#]
add ecx,895
rol edx,1
shld ecx,edx,21
shl edx,20
btr edx,20
rcr ecx,1
mov [^A#],edx
mov [^A#+4],ecx
.f4d
push eax
fld qword [^A#]
fstp dword [esp]
pop eax
ret
;
.f4i
push eax
fild dword [^A#]
fstp dword [esp]
pop eax
ret
Ensure there is at least a 2048-byte gap between the code and any writable data, to prevent thrashing of the instruction cache.