' 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

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.

'#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

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 ?

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.

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