User Tools

Site Tools


using_2032-bit_20floating_20point_20values

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.

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
using_2032-bit_20floating_20point_20values.txt · Last modified: 2024/01/05 00:21 by 127.0.0.1