Code archives/Miscellaneous/FloatToDouble Module for B3D/B+

This code has been declared by its author to be Public Domain code.

Download source code

FloatToDouble Module for B3D/B+ by markcw2008
I recently discovered that you can declare doubles as 2 integers and convert a float into a double as 2 integers in Blitz. This was figured out ages ago for OpenGL but isn't in the code archives. I then found some WinBatch code and converted it to Blitz, so I thought I'd tidy it up and release it as a module.

Update: This module now includes 2 new functions, FloatToInt and IntToFloat. These allow 'type casting' without needing to use a bank.

Create a file in your userlibs folder called "floattodouble.decls" and copy/paste this code in.
.lib " "
;FloatToDouble Module Decls

FloatToDouble%(value#, dpart)
DoubleToFloat#(dho, dhi)
FloatToInt%(value#)
IntToFloat#(value)

Save this code entry as "floattodouble.bb" and include it in your main program. See the test code below for example usage.
;FloatToDouble Module for B3D/B+
;Author: markcw, edited 29 Nov 08

;DLL functions with doubles for parameters can be declared
;as 2 integers instead. Then you can use FloatToDouble to convert a
;float into 2 integers which are the binary equivalent of a double
;but with the same value as the float. Finally you can pass
;the 2 integers to the 2 parameters in the DLL function.
;For example, glDepthRange takes 2 doubles so the decls would be:
;glDepthRange(zNearLo,zNearHi, zFarLo,zFarHi):"glDepthRange"
;Then a 'wrapper' function can be written to take 2 floats:
;bbglDepthRange(zNear#,zFar#)

Function FloatToDouble(value#, dpart = 0)
 ;Converts a float into a double as 2 integers
 ;dpart -> Double flag indicating which part to return, 0=dlo, 1=dhi
 ;Returns a low or high double integer - decimal equivalent of the float
 ;Site: techsupt.winbatch.com/TS/T000001034F21.html

 Local integer, sign, exponent, fraction, dexp, dlo, dhi
 integer = FloatToInt(value#)
 sign = integer And $80000000 ;Sign bit
 exponent = integer And $7F800000 ;8-bit exponent
 fraction = integer And $007FFFFF ;23-bit mantissa
 dexp = ((exponent Shr 23) - 127 + 1023) Shl 20 ;Double exponent
 dlo = (fraction And 7) Shl 29
 dhi = sign Or dexp Or (fraction Shr 3)
 If dpart = 0 Then Return dlo
 Return dhi

End Function

Function DoubleToFloat#(dlo, dhi)
 ;Converts a double as 2 integers into a float
 ;dlo -> Low double integer, dhi -> High double integer
 ;Returns a float - decimal equivalent of the double as 2 integers
 ;Site: techsupt.winbatch.com/TS/T000001034F21.html

 Local dsgn, sign, dexp, exponent, fraction
 dsgn = Abs(dhi Shr 31) ;Double sign
 sign = dsgn Shl 31 ;Sign bit
 dexp = Abs((dhi Shr 20) - (dsgn Shl 11)) ;Double exponent
 exponent = (dexp + 127 - 1023) Shl 23 ;8-bit exponent
 fraction = ((dhi And $000FFFFF) Shl 3) + (dlo Shr 29) ;23-bit mantissa
 Return IntToFloat(sign Or exponent Or fraction)

End Function

Function FloatToInt(value#)
 ;Converts a float into a float as an integer
 ;Returns an integer that is the binary equivalent of the float
 ;Site: wiki.tcl.tk/756

 Local sign, exponent, fraction#
 Local f1f#, f2f#, f3f#, se1, e2f1, f1, f2, f3
 If value# > 0 Then sign = 0 Else sign = 1
 value# = Abs(value#)
 exponent = Int(Floor(Log(value#) / 0.69314718055994529)) + 127
 fraction# = (value# / (2 ^ (exponent - 127))) - 1
 If exponent < 0 Then exponent = 0 : fraction# = 0.0 ;Round off to zero
 If exponent > 255 Then exponent = 255 ;Outside legal range for a float
 fraction# = fraction# * 128.0
 f1f# = Floor(fraction#)
 fraction# = (fraction# - f1f#) * 256.0
 f2f# = Floor(fraction#)
 fraction# = (fraction# - f2f#) * 256.0
 f3f# = Floor(fraction#)
 f1 = Int(f1f#) : f2 = Int(f2f#) : f3 = Int(f3f#)
 se1 = (sign Shl 7) Or (exponent Shr 1) ;Sign and Exponent1
 e2f1 = ((exponent And 1) Shl 7) Or f1 ;Exponent2 and Fraction1
 Return (se1 Shl 24) Or (e2f1 Shl 16) Or (f2 Shl 8) Or f3

End Function

Function IntToFloat#(value)
 ;Converts a float as an integer into a float
 ;Returns a float that is the binary equivalent of the integer
 ;Site: www.cs.princeton.edu/introcs/91float/

 Local sign, exponent, fraction
 sign = (value And $80000000) Shr 31
 exponent = (value And $7F800000) Shr 23
 fraction = value And $007FFFFF
 Return (-1 ^ sign) * (2 ^ (exponent - 127)) * (1 + (fraction / (2 ^ 23)))

End Function

Comments

markcw2008
This is just an accuracy test which shows converting from a float to a double as 2 integers and back to a float.
;FloatToDouble Test

Include "floattodouble.bb" ;FloatToDouble Module

SeedRnd MilliSecs()

For count = 0 To 9
 value# = Rnd(-5000, 5000)

 dlo = FloatToDouble(value#, 0) ;Get low double integer
 dhi = FloatToDouble(value#, 1) ;Get high double integer
 test# = DoubleToFloat(dlo, dhi) ;Get float from double as 2 integers

 Print "value# = " + value#
 Print " test# = " + test#
Next

WaitKey()
End



markcw2008
This is another accuracy test to show converting a float into an integer and then back to a float.
;FloatToInt Test

Include "floattodouble.bb" ;FloatToDouble Module

SeedRnd MilliSecs()

For count = 0 To 9
 value# = Rnd(-5000, 5000)

 integer = FloatToInt(value#) ;Get integer from float
 test# = IntToFloat(integer) ;Get float from integer

 Print "value# = " + value#
 Print " test# = " + test#
Next

WaitKey()
End



_332008
Here's a contender for the Float2Int and Int2Float but using a bank:
Function Float2Int_bank%(value#)
   Local bank% = CreateBank(4)
   PokeFloat(bank,0,value)
   Local ret% = PeekInt(bank,0)
   FreeBank(bank)
   Return ret
End Function

Function Int2Float_bank#(value%)
   Local bank% = CreateBank(4)
   PokeInt(bank,0,value)
   Local ret# = PeekFloat(bank,0)
   FreeBank(bank)
   Return ret
End Function



Code Archives Forum