Request: Double data types

Archives Forums/Blitz3D Bug Reports/Request: Double data types

markcw(Posted 2008) [#1]
I'm guessing the reason doubles were never added to b3d or b+ was because it is a non-trivial task. But just in case it was for some other reason I am requesting native double data types for Blitz3D. There is a dll made by a user here which allows double conversion but this won't work with other dll's that have functions with doubles as parameters, rendering them useless.

I suggest the following syntax for doubles:

Thanks for your time.

_33(Posted 2008) [#2]
I also want doubles, because I need them for converting fractionals with more precision.

markcw(Posted 2008) [#3]
I have to add a correction to this post. I have recently discovered it is possible to pass a double as 2 integers to a function in a dll with a double parameter. This was figured out ages ago actually for OpenGL functions.

Zethrax(Posted 2008) [#4]
I have to add a correction to this post. I have recently discovered it is possible to pass a double as 2 integers to a function in a dll with a double parameter. This was figured out ages ago actually for OpenGL functions.

That could come in handy. What's the syntax for doing that, markcw? Do you just add the singles together in the dll function call (eg. ExampleDllFunctionCall( singlevar1 + singlevar2 ))?

markcw(Posted 2008) [#5]
This should explain it.

Zethrax(Posted 2008) [#6]
Thanks for the info.

markcw(Posted 2008) [#7]
I couldn't find a DblToSng function anywhere. This might work but is untested.

Edit: Well it looks like it does work going by this simple test, although it's not incredibly accurate it is sufficient.

markcw(Posted 2008) [#8]
I fixed the accuracy problem and have made a module:

The problem was this line:
Sfract = ((DH And 1048575) Shl 3) + (DL Shr 28)
Should have been this:
Sfract = ((DH And 1048575) Shl 3) + (DL Shr 29)

_33(Posted 2008) [#9]
markcw, incidentally, just wondering if this thread would draw your attention to a problem that I found converting floats to a string:

I still haven't got the perfect routine to do so, and would really be grateful for help on this one. I still don't have the perfect routine for this. The goal in the end is to have the ascii codes stored in a bank, and of course the issue is to have a speedy way of doing this, not use string conversion operations.

markcw(Posted 2008) [#10]
I don't see what the problem is, all the numbers in the test were as expected.

_33(Posted 2008) [#11]
markcw, I know that's because the for loop was generating a number that the function liked. Try this for loop instead:
For i# = -125.0 To 125.0 Step 15.7

markcw(Posted 2008) [#12]
Yeah, I thought that after posting. Where'd you get this code from? Might help.

_33(Posted 2008) [#13]
Oh I tried many attempts at it. It is my code. I have many other routines to convert floats to ascii byte values, but they all give innacurate values due to some problem on how floats are handled in blitz. Also the reason why I use my routine instead of string manipulation and so on is because I work with banks (for a script language parser I made).

markcw(Posted 2008) [#14]
Well I had a go but nothing yet. I did however, after some reading, discover how to calculate a float from an integer, and then I found some code to do the reverse. So I added these to my Float2Double module as Float2Int and Int2Float.

_33(Posted 2008) [#15]
See here, I can't properly isolate the values after the decimal point. Blitz returns unusual, results, and there is no function I know in blitz to get only the fraction part of a number:
For i# = -125.0 To 125.0 Step 14.554
ln = write_FLOAT(i)

Function write_FLOAT%(num_in#)
Local num_upper% = Floor(num_in)
Local num_lower% = (num_in - Float num_upper) * 100000.0
Write num_upper + "." + Abs(num_lower)
End Function

In this case, it starts to break the value after 4 decimals...

See the problem in blitz is there is no reliable function that return the fraction portion of a number. If I had that, it would probably make my life easier for what I need to accomplish.

Here is how I try to study the float values from a binary standpoint:
Graphics 1024,768,32,2
Print "       1 = " + Bin$(Get_Float_Content(1))
Print "      -1 = " + Bin$(Get_Float_Content(-1))
Print "       2 = " + Bin$(Get_Float_Content(2))
Print "      -2 = " + Bin$(Get_Float_Content(-2))
Print "       3 = " + Bin$(Get_Float_Content(3))
Print "      -3 = " + Bin$(Get_Float_Content(-3))
Print "     1.1 = " + Bin$(Get_Float_Content(1.1))
Print "     1.2 = " + Bin$(Get_Float_Content(1.2))
Print "    -1.2 = " + Bin$(Get_Float_Content(-1.2))
Print "    1000 = " + Bin$(Get_Float_Content(1000))
Print "   -1000 = " + Bin$(Get_Float_Content(-1000))
Print "   65535 = " + Bin$(Get_Float_Content(65535))
Print "   65536 = " + Bin$(Get_Float_Content(65536))
Print " 65536.1 = " + Bin$(Get_Float_Content(65536.1))
Print "131072.1 = " + Bin$(Get_Float_Content(131072.1))
Print "262144.1 = " + Bin$(Get_Float_Content(262144.1))
Print "  524288 = " + Bin$(Get_Float_Content(524288))
Print " 1048576 = " + Bin$(Get_Float_Content(1048576))
Print "1048576.1= " + Bin$(Get_Float_Content(1048576.1))
Print "1048576.2= " + Bin$(Get_Float_Content(1048576.2))
Print "1048576.3= " + Bin$(Get_Float_Content(1048576.3))
Print "1048576.4= " + Bin$(Get_Float_Content(1048576.4))
Print "2097152.4= " + Bin$(Get_Float_Content(2097152.4))
Print "2097152.6= " + Bin$(Get_Float_Content(2097152.6))


Function Get_Float_Content%(value#)
   Local fb% = CreateBank(4)
   ret% = PeekInt(fb,0)
   Return ret
End Function

Detail on the composition of a float:

markcw(Posted 2008) [#16]
Would this help you?

Edit: see below.

_33(Posted 2008) [#17]
So, with this, it is possible to get the whole, and the fraction :P Very nice coding markcw, surprisingly simple and efficient!

EDIT: The only drawback I found is the usage of the value#^value% which is rather very slow when interpreted in bliltz. So, I managed a small efficient Exp10 routine to go with your function :P Just toss in the multiplier, and it will return the multiply factor.
Function Exp10#(value%) ; about 8 times faster than 10^value
   Select value
      Case 0 : Return 1.0          ; 10^0
      Case 1 : Return 10.0         ; 10^1
      Case 2 : Return 100.0        ; 10^2
      Case 3 : Return 1000.0       ; 10^3
      Case 4 : Return 10000.0      ; 10^4
      Case 5 : Return 100000.0     ; 10^5
      Case 6 : Return 1000000.0    ; 10^6
      Case 7 : Return 10000000.0   ; 10^7
      Case 8 : Return 100000000.0  ; 10^8
      Case 9 : Return 1000000000.0 ; 10^9
   End Select
End Function
Basically you'd say:
Return Fraction / Exp10(FractionPart)

markcw(Posted 2008) [#18]
Er, thanks but I forgot about very big and very small values and a few other things. So while that code looks right there are bugs. The good news is that I've fixed it.

just found and fixed another bug. I think that's it now but I'm not sure.
another change, removed a bit that wasn't needed.
last edit, fixes a rounding error and adds a cheat if less than 1.

Edit: see below.

_33(Posted 2008) [#19]
markcw, is it me or is FractionPart giving out some irregularities?

markcw(Posted 2008) [#20]
Nope, it's not you. There are still some bugs with this code and I'm trying to fix them. You can see the problem if you get random values in a loop and string compare with the fraction until you get an error. The problem with FractionPart is that when you subtract the whole - floor(whole) you don't get the exact fraction, you get an approximation which means sometimes FractionPart will be quite inaccurate. I'm not sure what to do about it yet.

_33(Posted 2008) [#21]
markcw, I got good and bad news about single precision. The good news is I found some good web document about the internals. The article has a C code example which does something that I need. I converted it to Blitz code. The bad news is, I have an imprecision in the fractions, yet again!!!! And it sounds like the same problems that we have generally speaking. The example code follows, and notice my debug prints ;) HINT: The first frac should of been 16384
pf (-772.1)

Function pf(x#)

   Print "float = " + x

   Local fb% = CreateBank(4)
   xx% = PeekInt(fb,0)
   sign% = xx Shr 31
   expo% = ((xx Shr 23) And $ff) - $7F
   man% = (xx And ((1 Shl 23) - 1)) And $7FFFFFFF ; I removed the sign bit here (maybe pointless)
   man% = man Or (1 Shl 23)

   s$ = ""
   If sign = 1 Then s$ = "-"
   Print s$ + (man Shr (23 - expo)) + "."

   frac% = man And ((1 Shl (23 - expo)) -1)
   base% = 1 Shl (23 - expo) : Print "base:" + base
   c% = 0
   While (frac > 0 And c < 6)
      c = c + 1
      frac = frac * 10 : Print "frac:" + frac
      Print (frac / base)
      frac = frac Mod base
End Function


markcw(Posted 2008) [#22]
Well, I have another version of FloatFraction here. This one may be slightly better but it still isn't 100% accurate. The thing about floats is that they aren't exact, they're a close approximation, so I don't think you're ever going to get exactly what you want. I'm finished with this effort, I don't want to spend any more time on it.

Edit: see below.

markcw(Posted 2008) [#23]
Well I somehow have managed to prove myself wrong, again, because I appear to have a version that is 100% accurate. It's a little slower but worth it. I found a way to isolate the wrong values and then round up in these rare cases.

Edit: see below.

markcw(Posted 2008) [#24]
Another update to FloatFraction, hopefully the last one. I fixed a bug in the wholepart loop that I created. I also am not returning stuff before the end any more as that doesn't really help.

Edit: see below.

_33(Posted 2008) [#25]
still not 100%, but thumbs up for the effort.

markcw(Posted 2008) [#26]
Could you elaborate perhaps?

_33(Posted 2008) [#27]
When I run this last one, I get roughly 1500 errors on a 100 000 run. I have no clue why! Tell me it's not because I have an AMD. I'm using Blitz3D v1.99. By the way, I want to know if you have run the small sample I posted earlier, see if you get errors in the conversion.

markcw(Posted 2008) [#28]
The errors in the test loop should actually be correct, it's just that the string compare method can't handle the exponent form.

markcw(Posted 2008) [#29]
Yeah, you're right Jacques, there are still errors. It's with numbers less than 1. I had a cheat in where if WholePart was zero then just return Abs(Value#) but then I realized this wouldn't really help if you want to get the exact value so I took it out. I'll try to fix it.

_33(Posted 2008) [#30]
Hey there Mark, here is a little something I did. I got my own version of the FloatFraction running in there which is a very optimized version of one of your early tries. I got a performance bench and a trial error test also. Enjoy!

markcw(Posted 2008) [#31]
Well, I have a new function, this once's my favorite because it's not so ugly. It won't work for values smaller than 1.0e-004 so I cheat after that and just return Abs(value#). I couldn't fix the inaccuracies in these very small values, but none of the other versions could do this anyway. If you get any errors let me know what range they're in.