Big Endian -> Little Endian
-
- Posts: 489
- Joined: Apr 18, 2008 4:09
- Location: Los Angeles, CA
- Contact:
Big Endian -> Little Endian
Trying to read 32-bit floating point numbers from a binary data file created by LabView. Apparently LabView uses Big Endian since it was originally developed on a Mac OS. Anyone have a fast Big Endian -> Little Endian converter (to work on single float variable or array of single float)?
Re: Big Endian -> Little Endian
Some endian swapping Macros. However, they are geared towards
ULong / ULongInt and not Single ... (if I've correctly interpreted, the question).
This could be solved, with a Union:
ULong / ULongInt and not Single ... (if I've correctly interpreted, the question).
This could be solved, with a Union:
Code: Select all
Union DW
As Single sdw
As ULong uldw
End Union
Last edited by MrSwiss on Jul 24, 2018 20:32, edited 1 time in total.
Re: Big Endian -> Little Endian
here some discussion on big endian to little endian conversion viewtopic.php?f=3&t=25857&p=235216&hili ... an#p235216
also more specifically dealing with float https://stackoverflow.com/questions/278 ... tle-endian
the answer by Gregor Brandt converted to FB
also more specifically dealing with float https://stackoverflow.com/questions/278 ... tle-endian
the answer by Gregor Brandt converted to FB
Code: Select all
'by Gregor Brandt
function ReverseFloat(byval inFloat as const single) as single
dim retVal as single
dim floatToConvert as zstring ptr = cptr(zstring ptr, @inFloat)
dim returnFloat as zstring ptr = cptr(zstring ptr, @retVal)
returnFloat[0] = floatToConvert[3]
returnFloat[1] = floatToConvert[2]
returnFloat[2] = floatToConvert[1]
returnFloat[3] = floatToConvert[0]
return retVal
end function
-
- Posts: 489
- Joined: Apr 18, 2008 4:09
- Location: Los Angeles, CA
- Contact:
Re: Big Endian -> Little Endian
Thanks for the ideas.
@sarvaldez, I get a segment violation error at this line:
returnFloat[0] = floatToConvert[3]
Is Callocate needed to set aside memory for the arrays?
@sarvaldez, I get a segment violation error at this line:
returnFloat[0] = floatToConvert[3]
Is Callocate needed to set aside memory for the arrays?
Re: Big Endian -> Little Endian
Warning:
This above function writes at least 4 additional bytes behind the Single due to a misuse of Zstring.
IMHO, use 'Byte Ptr' instead of 'Zstring Ptr':
This above function writes at least 4 additional bytes behind the Single due to a misuse of Zstring.
IMHO, use 'Byte Ptr' instead of 'Zstring Ptr':
Code: Select all
function ReverseFloat(byval inFloat as const single) as single
dim retVal as single
dim floatToConvert as byte ptr = cptr(byte ptr, @inFloat)
dim returnFloat as byte ptr = cptr(byte ptr, @retVal)
returnFloat[0] = floatToConvert[3]
returnFloat[1] = floatToConvert[2]
returnFloat[2] = floatToConvert[1]
returnFloat[3] = floatToConvert[0]
return retVal
end function
-
- Posts: 1186
- Joined: May 08, 2006 21:58
- Location: Crewe, England
Re: Big Endian -> Little Endian
Some stuff I wrote a while back, using asm. (To do with MIDI files)
Here's the include:
And here's a test driver
You probably need to define your fields as a Union of Singles and Longs/be4 to get this to work.
Enjoy
Code: Select all
'***********************************************************************
' Big-endian integer Handling
'***********************************************************************
#include once "jevans4949/bigend/bigend.bi"
'***********************************************************************
' Big-endian Operator Functions
'***********************************************************************
operator be4.cast() as integer
asm
mov eax,[This]
mov eax,[eax]
bswap eax
mov [function],eax
end asm
end operator
'
operator be4.let(byval source as integer)
asm
mov ebx,[this]
mov eax,[source]
bswap eax
mov [ebx],eax
end asm
end operator
'
operator be2s.cast() as integer
asm
mov ebx,[This]
movsxb eax,Byte Ptr[ebx]
sal eax,8
mov al,[ebx+1]
mov [Function],eax
end asm
end operator
'
operator be2s.let(byval source as integer)
asm
mov ebx,[This]
mov eax,[source]
mov [ebx],ah
mov [ebx+1],al
end asm
end operator
'
operator be2u.cast() as integer
asm
mov ebx,[This]
movzx eax,Byte Ptr[ebx]
sal eax,8
mov al,[ebx+1]
mov [Function],eax
end asm
end operator
'
operator be2u.let(byval source as integer)
asm
mov ebx,[This]
mov eax,[source]
mov [ebx],ah
mov [ebx+1],al
end asm
end operator
'
operator be3s.cast() as integer
asm
mov ebx,[This]
movsxb eax,Byte ptr[ebx]
sal eax,16
mov ah,[ebx+1]
mov al,[ebx+2]
mov [Function],eax
end asm
end operator
'
operator be3s.let(byval source as integer)
asm
mov ebx,[This]
mov eax,[source]
mov [ebx+1],ah
mov [ebx+2],al
sar eax,8
mov [ebx],ah
end asm
end operator
'
operator be3u.cast() as integer
asm
mov ebx,[This]
movzx eax,Byte ptr[ebx]
sal eax,16
mov ah,[ebx+1]
mov al,[ebx+2]
mov [Function],eax
end asm
end operator
'
operator be3u.let(byval source as integer)
asm
mov ebx,[This]
mov eax,[source]
mov [ebx+1],ah
mov [ebx+2],al
sar eax,8
mov [ebx],ah
end asm
end operator
Code: Select all
'***********************************************************************
' Stuff to pull in lib's
'***********************************************************************
#if (__FB_OUT_LIB__ = 0)
#libpath "/freebasic/lib/win32/jevans4949/bigend"
#inclib "bigend"
#endif
'***********************************************************************
' Big-endian Type definitions
'***********************************************************************
type be4 field=1 '4 byte,assumed signed
i as integer
declare operator cast() as integer
declare operator let(source as integer)
end type
'
type be3s field=1 '3 byte signed
as ubyte h,m,l
declare operator cast() as integer
declare operator let(source as integer)
end type
'
type be3u field=1 '3 byte unsigned
as ubyte h,m,l
declare operator cast() as integer
declare operator let(source as integer)
end type
'
type be2s field=1 '2 byte signed
i as short
declare operator cast() as integer
declare operator let(source as integer)
end type
'
type be2u field=1 '2 byte unsigned
i as ushort
declare operator cast() as integer
declare operator let(source as integer)
end type
'
Code: Select all
'***********************************************************************
' Big-endian integer Handling
'***********************************************************************
#include once "jevans4949/bigend/bigend.bi"
'***********************************************************************
' Big-Endian Test Harness
'***********************************************************************
dim p as ubyte ptr
dim i as integer
dim j as integer
dim x as be4
dim y as be3s
dim z as be2s
dim w as be2u
dim v as be3u
loop1:
Input "Enter value of type long";i
x = i
y = i
z = i
w = i
v = i
p=@x
print "converted to be4: ";hex(*p,2);hex(*(p+1),2);hex(*(p+2),2);hex(*(p+3),2)
p=@y
print "converted to be3s: ";hex(*p,2);hex(*(p+1),2);hex(*(p+2),2)
p=@v
print "converted to be3u: ";hex(*p,2);hex(*(p+1),2);hex(*(p+2),2)
p=@z
print "converted to be2s: ";hex(*p,2);hex(*(p+1),2)
p=@w
print "converted to be2u: ";hex(*p,2);hex(*(p+1),2)
j = x
print "Converted back from be4: ";j
j = y
print "Converted back from be3s: ";j
j = v
print "Converted back from be3u: ";j
j = z
print "Converted back from be2s: ";j
j = w
print "Converted back from be2u: ";j
goto loop1
Enjoy
-
- Posts: 489
- Joined: Apr 18, 2008 4:09
- Location: Los Angeles, CA
- Contact:
Re: Big Endian -> Little Endian SOLVED
@fxm, thanks for catching ptr issue with Zstring. With your byte ptr modification, the code runs correctly.
@jevans I'll do some timing tests, and then consider diving into your asm version.
Thanks to all
@jevans I'll do some timing tests, and then consider diving into your asm version.
Thanks to all
Re: Big Endian -> Little Endian
Didn't know there are "big endian" floats around... but conversion is pretty simple, this snippet converts it twice:
Code: Select all
dim as single MySingle = 123.456
Sub SwitchEndians(TheFloat As Single ptr)
Asm
mov edx, [TheFloat]
mov eax, [edx]
bswap eax
mov [edx], eax
End Asm
End Sub
print "float=";MySingle
SwitchEndians(@MySingle)
print "float=";MySingle
SwitchEndians(@MySingle)
print "float=";MySingle
sleep()
Re: Big Endian -> Little Endian
A simple pure FB Function, using UByte Ptr:
Code: Select all
' eSwpSgl_Func.bas -- 2018-07-24, by MrSwiss
'
' compile: -s console
'
Function eSwpSgl(ByVal si As Const Single) As Single
Dim As Single ret
For i As UInteger = 0 To 3
CPtr(UByte Ptr, @ret)[3 - i] = CPtr(UByte Ptr, @si)[i]
Next
Return ret
End Function
Dim As Single ts1 = 1.0, ts2 = -5.0, tr1 = 0.0, tr2 = 0.0
Print ts1,, ts2 ' show start values
tr1 = eSwpSgl(ts1) : tr2 = eSwpSgl(ts2) ' endiannes swap
Print tr1, tr2 ' show result
ts1 = 0.0 : ts2 = 0.0 ' clear vars. (for return of reverse operation)
ts1 = eSwpSgl(tr1) : ts2 = eSwpSgl(tr2) ' reverse endiannes swap
Print ts1,, ts2 ' show reverse result
Sleep
-
- Posts: 489
- Joined: Apr 18, 2008 4:09
- Location: Los Angeles, CA
- Contact:
Re: Big Endian -> Little Endian
@jj2007 - your ASM conversion is the fastest of the suggested approaches. I suppose this code would work for any 32-bit value (e.g. even for long integer)? It's been a while since I wrote code ASM, what modification would be needed for a 16 bit value (e.g. short integer)?
Re: Big Endian -> Little Endian
BasicScience wrote:what modification would be needed for a 16 bit value (e.g. short integer)?
Code: Select all
bswap eax
shr eax, 16
-
- Posts: 1186
- Joined: May 08, 2006 21:58
- Location: Crewe, England
Re: Big Endian -> Little Endian
jj2007 has the simplest answer for Singles or 4-byte integers - well done!
My code contains solutions for 2- and 3-byte signed and unsigned integers.
Note, however, that my code assumes a 32-bit compile - assumes sizeof(integer) and sizeof(pointer), and does not include 64-bit integers at all. Obviously it wouldn't work a non-Intel/AMD target either.
My code contains solutions for 2- and 3-byte signed and unsigned integers.
Note, however, that my code assumes a 32-bit compile - assumes sizeof(integer) and sizeof(pointer), and does not include 64-bit integers at all. Obviously it wouldn't work a non-Intel/AMD target either.
Re: Big Endian -> Little Endian
Thanks.jevans4949 wrote:jj2007 has the simplest answer for Singles or 4-byte integers - well done!
Interesting. The FPU can handle 2-byte (as in fild word ptr [esp]), 4-byte and 8-byte integers, but I've never heard of a 3-byte integer. Technically, it can be done, of course:My code contains solutions for 2- and 3-byte signed and unsigned integers.
Code: Select all
bswap eax
shr eax, 8
-
- Posts: 1186
- Joined: May 08, 2006 21:58
- Location: Crewe, England
Re: Big Endian -> Little Endian
The MIDI fie specification includes one instance of 3-byte integer, and also wierd variable-length integers - lower 7 bits of each byte are data and top bit indicates another byte follows - e.g &h'8307' decodes to &h'0187'. All integers are big-endian.jj2007 wrote:... but I've never heard of a 3-byte integer ...
EDIT: I once woked for a financial analysis company that had defined a 2-byte compressed float for company accounts data! Can't now remeber the details.
Last edited by jevans4949 on Jul 27, 2018 1:01, edited 1 time in total.
Re: Big Endian -> Little Endian
Wow, that's funny. Since it's MIDI, I wonder whether the Atari folks were involved. In the meantime I got curious and found out that apparently some graphics cards use a 24-bit float format. I never stop learning ;-)