Re: Little\Big-Endian Single and Double values

From: Francesco Ranieri (Francesco.Ranieri_at_eng.it)
Date: 11/18/04


Date: Thu, 18 Nov 2004 10:52:16 +0100

Thanks Mike... your suggestion helps always very much!
I've seen your code and it seems to me that you flip, simply, all bytes.
I see you're very skilled and I wish you examine this code in order to receive an your advice about:

'----------------------------- START CODE =>
'Structure of 64 bits
Public Type recUD64Bit
    lngLowByte As Long
    lngHighByte As Long
End Type

'APIs declarations
Public Declare Function HToNInt16 Lib "ws2_32.dll" Alias "htons" (ByVal intPRMHostValue As Integer) As Integer
Public Declare Function NToHInt16 Lib "ws2_32.dll" Alias "ntohs" (ByVal lngPRMNetValue As Long) As Integer
Public Declare Function HToNInt32 Lib "ws2_32.dll" Alias "htonl" (ByVal lngPRMHostValue As Long) As Long
Public Declare Function NToHInt32 Lib "ws2_32.dll" Alias "ntohl" (ByVal lngPRMNetValue As Long) As Long

'The my thinking....
Public Function HToNFloat32(ByVal sngPRMHostValue As Single) As Single
Dim lngTemp As Long

    'Cast the float-32 into int-32
    Call CopyMemory(lngTemp, sngPRMHostValue, 4)
   
    'Convert int-32 in Big-Endian
    lngTemp = HToNInt32(lngTemp)
   
    'Cast the int-32 into float-32
    Call CopyMemory(sngPRMHostValue, lngTemp, 4)
   
    'Return the value
    HToNFloat32 = sngPRMHostValue
End Function

Public Function NToHFloat32(ByVal sngPRMNetValue As Single) As Single
    NToHFloat32 = HToNFloat32(sngPRMNetValue)
End Function

Public Function HToNFloat64(ByVal dblPRMHostValue As Double) As Double
Dim lngTemp As Long
Dim recTemp As recUD64Bit

    'Background: Big\Little-Endian notation
    'Position Little-Endian Big-Endian
    '| Byte 1 | -> |Bit08 Bit01| -> |Bit64 Bit57|
    '| Byte 2 | -> |Bit16 Bit09| -> |Bit56 Bit49|
    '| Byte 3 | -> |Bit24 Bit17| -> |Bit48 Bit41|
    '| Byte 4 | -> |Bit32 Bit25| -> |Bit40 Bit33|
    '| Byte 5 | -> |Bit40 Bit33| -> |Bit32 Bit25|
    '| Byte 6 | -> |Bit48 Bit41| -> |Bit24 Bit17|
    '| Byte 7 | -> |Bit56 Bit49| -> |Bit16 Bit09|
    '| Byte 8 | -> |Bit64 Bit57| -> |Bit08 Bit01|

    'Cast the 8 bytes of the Little-Endian double into 8 bytes of the structure
    Call CopyMemory(ByVal recTemp, dblPRMHostValue, 8)

    With recTemp
        'Swaps the first 4 bytes with the last 4 bytes
        lngTemp = .lngHighByte
        .lngHighByte = .lngLowByte
        .lngLowByte = lngTemp

        'Now, swapped the two longs amongst themselves, the situation is:
        'Position Bits
        '| Byte 1 | -> |Bit40 Bit33|
        '| Byte 2 | -> |Bit48 Bit41| 'In .lngLowByte
        '| Byte 3 | -> |Bit56 Bit49|
        '| Byte 4 | -> |Bit64 Bit57|

        '| Byte 5 | -> |Bit08 Bit01|
        '| Byte 6 | -> |Bit16 Bit09| 'In .lngHighByte
        '| Byte 7 | -> |Bit24 Bit17|
        '| Byte 8 | -> |Bit32 Bit25|
      
        'Flips the two DWords
        .lngLowByte = HToNInt32(.lngLowByte)
        .lngHighByte = HToNInt32(.lngHighByte)

        'Now, flipped the two DWords, the situation is:
        'Position Bits
        '| Byte 1 | -> |Bit64 Bit57|
        '| Byte 2 | -> |Bit56 Bit49| 'In .lngLowByte
        '| Byte 3 | -> |Bit48 Bit41|
        '| Byte 4 | -> |Bit40 Bit33|

        '| Byte 5 | -> |Bit32 Bit25|
        '| Byte 6 | -> |Bit24 Bit17| 'In .lngHighByte
        '| Byte 7 | -> |Bit16 Bit09|
        '| Byte 8 | -> |Bit08 Bit01|
    End With
   
    'Recreates the Big-Endian double
    Call CopyMemory(dblPRMHostValue, ByVal VarPtr(recTemp), 8)
   
    'Return the value in Big-Endian notation
    HToNFloat64 = dblPRMHostValue
End Function

Public Function NToHFloat64(ByVal dblPRMNetValue As Double) As Double
    NToHFloat64 = HToNFloat64(dblPRMNetValue)
End Function
'----------------------------- END CODE <=

This code should be perform the same operations of yours... without loops!
I've tryed to execute your code and mine... the result are the same!

Do you think I'm right and...."important" for me.... my code (without loop...) could be slightly faster than your approach (...with loop)??????

Thanks....
Francesco

P.S.
It seems to me that FlipBytes function executes the same operation of NToH\HToNL.. isn't it really?
I've found, also, your code to substitute the NToH\HToNL functions in an older post:

'----------------------------- START CODE =>Private Function SwapEndian(ByVal dw As Long) As Long
    ' by Mike D Sutton, Mike.Sutton@btclick.com, 20040914
    SwapEndian = (((dw And &HFF000000) \ &H1000000) And &HFF&) Or _
                 ((dw And &HFF0000) \ &H100&) Or _
                 ((dw And &HFF00&) * &H100&) Or _
                 ((dw And &H7F&) * &H1000000)
    If (dw And &H80&) Then SwapEndian = SwapEndian Or &H80000000
End Function
'----------------------------- END CODE <=or, the variant (...by Bob O' Bob...), slightly faster:'----------------------------- START CODE =>Private Function FlipDWord(ByVal inDWord As Long) As Long If (inDWord And &H80&) Then FlipDWord = &H80000000 Or _ (((inDWord And &HFF000000) \ &H1000000) And &HFF&) Or _ ((inDWord And &HFF0000) \ &H100&) Or _ ((inDWord And &HFF00&) * &H100&) Or _ ((inDWord And &H7F&) * &H1000000) Else FlipDWord = (((inDWord And &HFF000000) \ &H1000000) And &HFF&) Or _ ((inDWord And &HFF0000) \ &H100&) Or _ ((inDWord And &HFF00&) * &H100&) Or _ ((inDWord And &H7F&) * &H1000000) End IfEnd Function'----------------------------- END CODE <=
and, Donald Lessau has discovered that your code is faster than others approaches and... some more than NToH\HToNL functions!!!!!
I think that I'll use your variant instead NToH\HToNL for my purpose!!!
Thanks again Mike..
Francesco

"Mike D Sutton" <EDais@mvps.org> ha scritto nel messaggio news:ezSLi7MzEHA.3976@TK2MSFTNGP09.phx.gbl...
> > I've an application that have to communicate with another (not mine) via
> > UDP.
> > The communication should be occur by structured messages with Long, Integer,
> > Single and Double fields!
> > I need to convert all fields in Big-Endian notation before sending.
> > For Long and Integer I found the two pairs of functions:
> >
> > NToHL, HToNL (for Long values)
> > NToHS, HToNS (for Integer values)
> >
> > but there isn't anything about Single and Double.
> > Can you help me to find something like:
> >
> > NToHFloat32, HToNFloat32 (for Single values)
> > NToHFloat64, HToNFloat64 (for Double values)
> > ????
> >
> > If there aren't APIs that perform these functions, can you help me in
> > another way?
>
> Here's a generic routine in VB code for flipping any number of bytes and wrapper functions for specifically flipping singles and
> doubles:
>
> '***
> Private Declare Sub GetByte Lib "MSVBVM60.dll" Alias "GetMem1" (ByRef inSrc As Long, ByRef inDst As Byte)
> Private Declare Sub PutByte Lib "MSVBVM60.dll" Alias "PutMem1" (ByRef inDst As Long, ByVal inSrc As Byte)
>
> Private Sub FlipBytes(ByVal inSrc As Long, ByVal inDst As Long, ByVal inCount As Long)
> Dim LoopBytes As Long
> Dim ThisByte As Byte
>
> For LoopBytes = 0 To (inCount - 1)
> Call GetByte(ByVal (inSrc + inCount - LoopBytes - 1), ThisByte)
> Call PutByte(ByVal (inDst + LoopBytes), ThisByte)
> Next LoopBytes
> End Sub
>
> Private Function FlipFloat(ByVal inFloat As Single) As Single
> Call FlipBytes(ByVal VarPtr(inFloat), ByVal VarPtr(FlipFloat), LenB(inFloat))
> End Function
>
> Private Function FlipDouble(ByVal inDouble As Double) As Double
> Call FlipBytes(ByVal VarPtr(inDouble), ByVal VarPtr(FlipDouble), LenB(inDouble))
> End Function
> '***
>
> Hope this helps,
>
> Mike
>
>
> - Microsoft Visual Basic MVP -
> E-Mail: EDais@mvps.org
> WWW: http://EDais.mvps.org/
>
>



Relevant Pages

  • Re: Whats Stable
    ... Public Function TimeDLookUp() As Long ... Dim varStuff As Variant ... Debug.Print!ContractPropID ... Dim lngTimeDL As Long ...
    (microsoft.public.access.formscoding)
  • Load registry hive (AdjustTokenPrivileges error)
    ... Public PrivilegeCount As Int32 ... Public Function RegLoadKey(ByVal hKey As Int32, ... String, ByVal lpFile As String) As Int32 ... Dim strKeyName As String ...
    (microsoft.public.vb.winapi)
  • Load registry hive (AdjustTokenPrivileges error)
    ... Public PrivilegeCount As Int32 ... Public Function RegLoadKey(ByVal hKey As Int32, ... String, ByVal lpFile As String) As Int32 ... Dim strKeyName As String ...
    (microsoft.public.dotnet.languages.vb)
  • Re: How to fill a listview from LINQ query: Solution
    ... It appears that a .CopyToDataTable class existed in the Linq Betas, but the class was cut due to lack of resources. ... Dim dt As New DataTable ... Public Function CopyToDataTable) As DataTable ... 'enumerate the source sequence and load the object values into rows. ...
    (microsoft.public.dotnet.framework.adonet)
  • Re: Function Warning - Null Reference
    ... Sorry about that Stephany, should have guessed. ... Dim myBool As Boolean ... Public Function Dec2hmsAs String ... Dim success As Boolean = False ...
    (microsoft.public.dotnet.languages.vb)