I'm not associated at all with this library, but you can use this.
It's a struct that uses internally an ushort
member, which should be what you are transmitting. If you can't transmit the struct directly for some reason, you could just make the value
field public
, and use that (or use the GetBytes()
method).
I'm unsure about the precision of the conversion though, you should experiment.
The library is C#, but there should be no problem adding it as a C# project to your solution and use it from Vb.Net
Update
I took the time and made a "safe" minimum version in Vb.net. All the code is from that library, all copyrights to him:
Public Class HalfPrecisionConverter
Private Shared BaseTable As UShort() = GenerateBaseTable()
Private Shared ShiftTable As SByte() = GenerateShiftTable()
Private Shared Function GenerateBaseTable() As UShort()
Dim intBaseTable = New UShort(511) {}
For i = 0 To 255
Dim e = CSByte(127 - i)
If e > 24 Then
' Very small numbers map to zero
intBaseTable(i Or &H0) = &H0
intBaseTable(i Or &H100) = &H8000
ElseIf e > 14 Then
' Small numbers map to denorms
intBaseTable(i Or &H0) = CUShort(&H400 >> (18 + e))
intBaseTable(i Or &H100) = CUShort((&H400 >> (18 + e)) Or &H8000)
ElseIf e >= -15 Then
' Normal numbers just lose precision
intBaseTable(i Or &H0) = CUShort((15 - e) << 10)
intBaseTable(i Or &H100) = CUShort(((15 - e) << 10) Or &H8000)
ElseIf e > -128 Then
' Large numbers map to Infinity
intBaseTable(i Or &H0) = &H7c00
intBaseTable(i Or &H100) = &Hfc00
Else
' Infinity and NaN's stay Infinity and NaN's
intBaseTable(i Or &H0) = &H7c00
intBaseTable(i Or &H100) = &Hfc00
End If
Next
Return intBaseTable
End Function
Private Shared Function GenerateShiftTable() As SByte()
Dim intShiftTable = New SByte(511) {}
For i = 0 To 255
Dim e = CSByte(127 - i)
If e > 24 Then
' Very small numbers map to zero
intShiftTable(i Or &H0) = 24
intShiftTable(i Or &H100) = 24
ElseIf e > 14 Then
' Small numbers map to denorms
intShiftTable(i Or &H0) = CSByte(e - 1)
intShiftTable(i Or &H100) = CSByte(e - 1)
ElseIf e >= -15 Then
' Normal numbers just lose precision
intShiftTable(i Or &H0) = 13
intShiftTable(i Or &H100) = 13
ElseIf e > -128 Then
' Large numbers map to Infinity
intShiftTable(i Or &H0) = 24
intShiftTable(i Or &H100) = 24
Else
' Infinity and NaN's stay Infinity and NaN's
intShiftTable(i Or &H0) = 13
intShiftTable(i Or &H100) = 13
End If
Next
Return intShiftTable
End Function
Public Shared Function SingleToHalf([single] As Single) As UShort
Dim value As UInteger = BitConverter.ToUInt32(BitConverter.GetBytes([single]), 0)
Dim result = CUShort(baseTable((value >> 23) And &H1ff) + ((value And &H7fffff) >> shiftTable(value >> 23)))
Return result
End Function
End Class
To use:
HalfPrecisionConverter.SingleToHalf(xx)
It returns a UShort
, if you need the bytes to transmit, you can use BitConverter.GetBytes()
The C# unsafe version should be a bit faster since it does not use BitConverter
and directly uses pointers to convert the single to a UInteger
of its bytes, but I'm not sure VB.NET allows for any kind of pointer conversions