## convert any 32-bit ulong to single 0.0-0.999999

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
D.J.Peters
Posts: 8599
Joined: May 28, 2005 3:28
Contact:

### convert any 32-bit ulong to single 0.0-0.999999

Code: Select all

``````' convert a 32-bit integer number
' in a range of 30 bits = 0 to 1073741823 or hex 0 to 3FFFFFFF
' to a 32 bit float in range of 0.0 to 0.9999999
function u32_2_float(byval value as ulong) as single
dim as ulong  u32 = &H3F800000 or (value and &H3FFFFFFF)
dim as single f32 = *cptr(single ptr, @u32)
return f32 - 1.0f
end function``````
Imagine you have any 32-bit random number generator and the return value should be a single value in range of 0-0.999999

Code: Select all

``````function floatRND(byval seed as ulong=0) as single
static as ulong last0 = 0, last1 = 0
dim as ulong tmp, u32 = &H3F800000
dim as single result  = -1
if seed then
last0  = seed
if last0<1024*64 then last0 shl=16
last1 = 0
elseif last0=last1 then
' first run (or if no seed was giffen before)
last0 = &HBFFFFF ' 0.499999
last1 = last0 shl 16
else
tmp = last0 shl 16
last0 shr= 16
last0 += tmp
last0 += last1
last1 += last0
endif
' convert the ulong to float
u32 or= (last0 and &H3FFFFFFF)
result += *cptr(single ptr, @u32)
'return iif(result>0.9999,1.0f,result)
return result
end function
for i as long= 1 to 10
print floatRND()
next
sleep``````
Last edited by D.J.Peters on Jul 19, 2024 6:45, edited 1 time in total.
deltarho[1859]
Posts: 4438
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

### Re: convert any 32-bit ulong to single 0.0-0.999999

@D.J.Peters

I tried 'Print floatRND(123456789)' and it gave 0.175698 which is wrong.

Anyway, what is wrong with:

Cast( Single, n/2^32 ) where n is a Ulong.
hhr
Posts: 230
Joined: Nov 29, 2019 10:41

### Re: convert any 32-bit ulong to single 0.0-0.999999

It should be 0 <= Rnd < 1.
The following experiment shows that there are exceptions. Perhaps these are rounding errors?

gas64 behaves differently than gas32, gcc32, gcc64. I have tested with the latest Recent builds.

Code: Select all

``````'#cmdline "-gen gcc"

dim as ulong n1 = -1
print n1
dim as double a1
a1 = cast(double,n1)/(2^32)
print a1

print "----------"

dim as ulongint n2 = -1
print n2
dim as double a2
a2 = cast(double,n2)/(2^64)
print a2

print "----------"

dim as ulong n3 = -1
print n3
dim as single a3
a3 = cast(single,n3)/(2^32)
print a3

print "----------"

dim as ulongint i
dim as single n4
do
n4 = rnd
i += 1
loop until n4 = 1
print i, n4

sleep
``````
dafhi
Posts: 1697
Joined: Jun 04, 2005 9:51

### Re: convert any 32-bit ulong to single 0.0-0.999999

very nice, Mr. Peters.

i put in namespace so a person can adjust last1, last0 at any time, and removed if statements

Code: Select all

``````namespace rng

dim as ulong last0 = &HBFFFFF, last1' = last0 shl 16

function f( seed as ulong = 0 ) as single
'' https://www.freebasic.net/forum/viewtopic.php?t=32753
'  static as ulong last0 = &HBFFFFF, last1' = last0 shl 16
'  static as ulong last0 = 0, last1 = 0
static as ulong tmp, u32: u32 = &H3F800000 ''
'static as single result  = -1

last0 xor= seed*123'45678

/'if seed then
last0 = seed*12345678
last1 = 0
elseif last0=last1 then
' first run (or if no seed was giffen before)
last0 = &HBFFFFF ' 0.499999
last1 = last0 shl 16
else'/
tmp = last0 shl 16
last0 shr= 16
last0 += tmp
last0 += last1
last1 += last0
'endif
' convert the ulong to float
u32 or= (last0 and &H3FFFFFFF)
'result += *cptr(single ptr, @u32)
'return iif(result>0.9999,1.0f,result)
return *cptr(single ptr, @u32) - 1'result
end function

end namespace
``````

deltarho[1859]
Posts: 4438
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

### Re: convert any 32-bit ulong to single 0.0-0.999999

dafhi wrote:very nice, Mr. Peters.
Why?

What is wrong with 'Cast( Single, n/2^32 )' where n is a Ulong?

Print Cast( Single, 2^31/2^32 ) => 0.5

What am I missing?

Added: I don't know what 30 bits has to do with the thread's title.
Last edited by deltarho[1859] on Jul 16, 2024 23:54, edited 1 time in total.
dafhi
Posts: 1697
Joined: Jun 04, 2005 9:51

### Re: convert any 32-bit ulong to single 0.0-0.999999

he's doing a floating point hack (which i don't understand) which eliminates the usual division oper
deltarho[1859]
Posts: 4438
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

### Re: convert any 32-bit ulong to single 0.0-0.999999

gcc doesn't use division, either. It converts 1/2^32 to a multiplication.
D.J.Peters
Posts: 8599
Joined: May 28, 2005 3:28
Contact:

### Re: convert any 32-bit ulong to single 0.0-0.999999

deltarho[1859] wrote: Jul 16, 2024 23:43What is wrong with 'Cast( Single, n/2^32 )' where n is a Ulong?
Nothing is wrong

For global illumination I need per pixel or any point on surface 64-1024 random vectors
(that means x,y,z =1024*3 random numbers)
WebAssembly "wasm" is mutch faster if I compile my version "without any division" for the browser you know I'm talking about ?

Joshy
deltarho[1859]
Posts: 4438
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

### Re: convert any 32-bit ulong to single 0.0-0.999999

I have just bit my tongue. I must be mellowing in my dotage.
SARG
Posts: 1804
Joined: May 27, 2005 7:15
Location: FRANCE

### Re: convert any 32-bit ulong to single 0.0-0.999999

hhr wrote: Jul 16, 2024 19:16 gas64 behaves differently than gas32, gcc32, gcc64.
@hhr
Thank you for the report.
Issue fixed. I'll provide later today a new version (before 1.20 release).
SARG
Posts: 1804
Joined: May 27, 2005 7:15
Location: FRANCE

### Re: convert any 32-bit ulong to single 0.0-0.999999

The promised version : https://users.freebasic-portal.de/sarg/fbc64_120.zip

Remarks :
- the problem was due to casting ulong to double/single with values ​​>=&h80000000
- Surprisingly the way I fixed it is very simple, maybe too simple compared to the C compiler, so cases
might not be covered. If it happens tell me.

- in hhr's examples when the C compiler is used with O2 option it directly calculates the value at compile time.

Edit : typo fixed. Thanks
Last edited by SARG on Jul 17, 2024 20:32, edited 2 times in total.
hhr
Posts: 230
Joined: Nov 29, 2019 10:41

### Re: convert any 32-bit ulong to single 0.0-0.999999

The example now works with gas64. Only the link has a typo. https://users.freebasic-portal.de/sarg/fbc64_120.zip works.
SARG
Posts: 1804
Joined: May 27, 2005 7:15
Location: FRANCE

### Re: convert any 32-bit ulong to single 0.0-0.999999

I felt something could go wrong.
My fix caused an issue when casting some LONG values to double/single.....
So new version uploaded (same name).
dafhi
Posts: 1697
Joined: Jun 04, 2005 9:51

### Re: convert any 32-bit ulong to single 0.0-0.999999

no multiply

[update: simpler but period may be reduced. still it's longer than LCG]

Code: Select all

``````function round(in as double, places as ubyte = 2) as string
dim as integer mul = 10 ^ places
return str(csng( int(in * mul + .5) / mul) )
End Function

namespace rng

dim as ulong  tmp, u32, last0 = &HBFFFFF, last1' = last0 shl 16
dim as ulong  a,b

const         lenx8 = len(a) * 8
const         lenBy2 = lenx8 \ 2

const as ulongint 		xorC = &b0000000010000000001000000001000000010000001000001000010001001011
const as ulongint     xorA = &b01010101010101010101010101010101

function f( seed as ulong = 0 ) as single
'' https://www.freebasic.net/forum/viewtopic.php?t=32753

u32 = &H3F800000 ''

#if 1
#if 1
a = a xor seed xor b
#else
a = a xor seed xor (a shl 1) xor b
#endif
b += a shr 1
b xor= xorc

#elseif 1
a xor= xorc
a = b - seed xor a xor a shl 2
b += a shr 1

#elseif 1
b xor= b shl lenby2
b += 3 * (a xor xorC xor seed) shr 1
a xor= b

#else
'static as single result  = -1

last0 xor= seed*12345678

tmp = last0 shl 16
last0 shr= 16
last0 += tmp
last0 += last1
last1 += last0

' convert the ulong to float
'result += *cptr(single ptr, @u32)

b = last0 '' u32 prepare
#endif

u32 or= (b and &H3FFFFFFF)

return *cptr(single ptr, @u32) - 1'result
end function

end namespace

for i as long= 1 to 200
print round( rng.f(), 3); " ";
next

sleep

``````