Float/Double error in Lua PPC macs

Archives Forums/BlitzMax Bug Reports/Float/Double error in Lua PPC macs

Tricky(Posted 2012) [#1]
Maybe not the most important bugs (as I may be one of the few using PPC these days (my main system is Intel, but I have a subsystem in PPC)).

Whenever you need to deal with numbers like Float and Double numbers, everything works fine in Intel based machines, so Intel Macs and Windows are fine, and Linux has not been tried, but I don't expect any trouble there at all either.

But as soon as PPC is involved things go wrong when transferring double and float numbers between BlitzMax and Lua my means of the MaxLua module.

If you accept variables of these types from Lua by means of function parameters in functions you registered in Lua none of the numbers come out as they are supposed to be. Integer numbers are fine.
Now I haven't yet checked what will happen if you send numbers of the just named types from BlitzMax to Lua, but I expect it to be problematic too.
Of course I could be a bit behind on Bmax version (1.42 is on my PPC mac).

I did try this out with as well as 'pure PPC' compiler as with Brucey's Universal Binary compiler both with the same results.


xlsior(Posted 2012) [#2]
PPC and Intel processors use a different format to store numerical data, which leads to the unexpected results you're seeing if you don't take that difference into account.

From the blitzmax manual:


Endian format refers to the order multi-byte values are stored. For example, an integer is four bytes long, but in what order should each byte be stored? Low byte first or high byte first?

This choice is generally dictated by the CPU. For example, Intel CPU's such as the pentium store multi-byte values 'low byte first' which is known as little endian. On the other hand, PowerPC CPU's store multi-byte values 'high byte first' which is known as big endian.

Most of the time, you don't have to worry about endian issues. As long as the same endian format is being used to read and write data, there is no problem. However, endian issues do need to be taken into account when reading or writing binary files. For example, writing a binary file on a PC (which is little endian) and reading it back on a Mac (which is big endian) may produce odd results if the file contains multibyte values.

Endian streams help solve this problem by modifying the behaviour of stream commands that read or write multi-byte values. These commands are: ReadShort, ReadInt, ReadLong, ReadFloat, ReadDouble, WriteShort, WriteInt, WriteLong, WriteFloat and WriteDouble.

Functions:
BigEndianStream and LittleEndianStream



To make the powerPC use the same format as the PC, use LittleEndianStream to read/write the data and they should match.


Tricky(Posted 2012) [#3]
LittleEndianStream or BigEndianStream is (as far as my knowledge goes) only an issue when it comes to reading and writing files and since that is NOT what is happening here, the functions named here won't solve the problem.



Let's put it this way.
Make a type like this

Type LOBJ

Method Test(A:double)
print A
end method

End Type

LuaRegisterObject New LOBJ,"LuaObject"


Then make it execute the next Lua script
print(LuaObject.Test(100))


Any result could pop up here, but not the right one. When I replace the 'Double' type with 'Int' it will work, even when using numbers higher than 255.


Cut short, this is not a streaming issue (if it was Little/BigEndianstream would help), but a direct communication error between Lua and BlitzMax.
Still I do think that Endians could be the issue here.

Last edited 2012


Floyd(Posted 2012) [#4]
I had the impression that MaxLua was using strings to transfer numbers. In that case endianness shouldn't matter.

You could test the endianness idea. The single precision floats 1.0 and 4.60060299e-041 have the same representation, but with byte order reversed. If endianness is the problem and one of these numbers is sent the other will be received.

Last edited 2012


Tricky(Posted 2012) [#5]
Strings? Hmmm, I guess MaxLua doesn't do that by default, but there is a "ToFloat()" and "ToDouble()" on strings? If so, I can easily get around this bug at least :)

I'm not working on my PPC right now (and it'll take too much time to set it up right away), but tomorrow I have to use that thing anyway, so then I'll post up some code (my Blitz and Lua code) and show the PPC results, and of course I'll then test the same code out on my Intel Mac and show those results as well. :)


Tricky(Posted 2012) [#6]
Ok, investigation showed that it may not be MaxLua doing the evil here.
The bug was discovered when I wrote APIs for Lua where SetScale was used accepting numbers from Lua to determine the scaling rate. SetOrigin was also used here. Both accepted a 'Double' number directly from a Lua Script and gave incorrect results which I could (in the SetOrigin case) fix by just accepting Ints.

Anyway, the test program and script I used here showed the next results which does appear as they should be...


BMax:
Strict
Type LO
	Method I(A:Int)
	Print "INT: "+A
	End Method

	Method F(A:Float)
	Print "FLOAT: "+A
	End Method

	Method D(A:Double)
	Print "DOUBLE: "+A
	End Method
	
	Method S(A:String)
	Print "STRING: "+A
	End Method
	
	End Type
	
LuaRegisterObject New LO,"L"


Global Src$ = LoadString("Bug.lua")
Print "-- Script~n"+Src+"~n-- End Script ~n~n"


Local class:TLuaClass=TLuaClass.Create( src )
Local instance:TLuaObject=TLuaObject.Create( class,Null )


Lua:
for ak=0,1000,25.25 do
	print('LUA: '..ak)
	L.I(ak)
	L.D(ak)
	L.F(ak)
	L.S(ak)
	end


Output:
Building Bug
Compiling:Bug.bmx
Linking:Bug.debug_PPC
Executing:Bug.debug_PPC
-- Script
for ak=0,1000,25.25 do
	print('LUA: '..ak)
	L.I(ak)
	L.D(ak)
	L.F(ak)
	L.S(ak)
	end


-- End Script 


LUA: 0
INT: 0
DOUBLE: 0.0000000000000000
FLOAT: 0.00000000
STRING: 0
LUA: 25.25
INT: 25
DOUBLE: 25.250000000000000
FLOAT: 25.2500000
STRING: 25.25
LUA: 50.5
INT: 50
DOUBLE: 50.500000000000000
FLOAT: 50.5000000
STRING: 50.5
LUA: 75.75
INT: 75
DOUBLE: 75.750000000000000
FLOAT: 75.7500000
STRING: 75.75
LUA: 101
INT: 101
DOUBLE: 101.00000000000000
FLOAT: 101.000000
STRING: 101
LUA: 126.25
INT: 126
DOUBLE: 126.25000000000000
FLOAT: 126.250000
STRING: 126.25
LUA: 151.5
INT: 151
DOUBLE: 151.50000000000000
FLOAT: 151.500000
STRING: 151.5
LUA: 176.75
INT: 176
DOUBLE: 176.75000000000000
FLOAT: 176.750000
STRING: 176.75
LUA: 202
INT: 202
DOUBLE: 202.00000000000000
FLOAT: 202.000000
STRING: 202
LUA: 227.25
INT: 227
DOUBLE: 227.25000000000000
FLOAT: 227.250000
STRING: 227.25
LUA: 252.5
INT: 252
DOUBLE: 252.50000000000000
FLOAT: 252.500000
STRING: 252.5
LUA: 277.75
INT: 277
DOUBLE: 277.75000000000000
FLOAT: 277.750000
STRING: 277.75
LUA: 303
INT: 303
DOUBLE: 303.00000000000000
FLOAT: 303.000000
STRING: 303
LUA: 328.25
INT: 328
DOUBLE: 328.25000000000000
FLOAT: 328.250000
STRING: 328.25
LUA: 353.5
INT: 353
DOUBLE: 353.50000000000000
FLOAT: 353.500000
STRING: 353.5
LUA: 378.75
INT: 378
DOUBLE: 378.75000000000000
FLOAT: 378.750000
STRING: 378.75
LUA: 404
INT: 404
DOUBLE: 404.00000000000000
FLOAT: 404.000000
STRING: 404
LUA: 429.25
INT: 429
DOUBLE: 429.25000000000000
FLOAT: 429.250000
STRING: 429.25
LUA: 454.5
INT: 454
DOUBLE: 454.50000000000000
FLOAT: 454.500000
STRING: 454.5
LUA: 479.75
INT: 479
DOUBLE: 479.75000000000000
FLOAT: 479.750000
STRING: 479.75
LUA: 505
INT: 505
DOUBLE: 505.00000000000000
FLOAT: 505.000000
STRING: 505
LUA: 530.25
INT: 530
DOUBLE: 530.25000000000000
FLOAT: 530.250000
STRING: 530.25
LUA: 555.5
INT: 555
DOUBLE: 555.50000000000000
FLOAT: 555.500000
STRING: 555.5
LUA: 580.75
INT: 580
DOUBLE: 580.75000000000000
FLOAT: 580.750000
STRING: 580.75
LUA: 606
INT: 606
DOUBLE: 606.00000000000000
FLOAT: 606.000000
STRING: 606
LUA: 631.25
INT: 631
DOUBLE: 631.25000000000000
FLOAT: 631.250000
STRING: 631.25
LUA: 656.5
INT: 656
DOUBLE: 656.50000000000000
FLOAT: 656.500000
STRING: 656.5
LUA: 681.75
INT: 681
DOUBLE: 681.75000000000000
FLOAT: 681.750000
STRING: 681.75
LUA: 707
INT: 707
DOUBLE: 707.00000000000000
FLOAT: 707.000000
STRING: 707
LUA: 732.25
INT: 732
DOUBLE: 732.25000000000000
FLOAT: 732.250000
STRING: 732.25
LUA: 757.5
INT: 757
DOUBLE: 757.50000000000000
FLOAT: 757.500000
STRING: 757.5
LUA: 782.75
INT: 782
DOUBLE: 782.75000000000000
FLOAT: 782.750000
STRING: 782.75
LUA: 808
INT: 808
DOUBLE: 808.00000000000000
FLOAT: 808.000000
STRING: 808
LUA: 833.25
INT: 833
DOUBLE: 833.25000000000000
FLOAT: 833.250000
STRING: 833.25
LUA: 858.5
INT: 858
DOUBLE: 858.50000000000000
FLOAT: 858.500000
STRING: 858.5
LUA: 883.75
INT: 883
DOUBLE: 883.75000000000000
FLOAT: 883.750000
STRING: 883.75
LUA: 909
INT: 909
DOUBLE: 909.00000000000000
FLOAT: 909.000000
STRING: 909
LUA: 934.25
INT: 934
DOUBLE: 934.25000000000000
FLOAT: 934.250000
STRING: 934.25
LUA: 959.5
INT: 959
DOUBLE: 959.50000000000000
FLOAT: 959.500000
STRING: 959.5
LUA: 984.75
INT: 984
DOUBLE: 984.75000000000000
FLOAT: 984.750000
STRING: 984.75

Process complete


The project in which the bugging happens is too complex to post up here, so I'll need to make some sample code resembling this bug later.