I'm receiving byte-arrays containing float variables (32 bit).
In my C# application I'd like to turn byte[] byteArray into a float using bitwise shifting (because it's a lot faster than BitConverter).
Turning a byte-array into a short works like this:
short shortVal = (short)((short)inputBuffer [i++] << 8 | inputBuffer [i++]);
How do I do this for float-variables?
Let's gut the BCL and use its intestines for our purposes:
unsafe public static float ToSingle (byte[] value, int startIndex)
{
int val = ToInt32(value, startIndex);
return *(float*)&val;
}
You can implement ToInt32 using bit shifting.
If you don't need endianness behavior a single unsafe access can give you the float (assuming it's aligned).
Alternatively, you can use a union struct to convert an int to a float.
To get away from C# conventional methods and obtain fast performance, you'll most likely have to implement "unsafe" behavior. You could do something like the C style memory copy.
unsafe public static void MemoryCopy (void* memFrom, void* memTo, int size) {
byte* pFrom = (byte*)memFrom;
byte* pTo = (byte*)memTo;
while (size-- >= 0)
*pTo++ = *pFrom++;
}
This assumes that the float's endianness is the same going into the byte[] as it on the other end.
To use this you'll have to first fix the byte array since the runtime can move it anytime it wants during garbage collection. Something like this:
float f;
unsafe {
fixed (byte* ptr = byteArray) {
MemoryCopy (ptr, &f, sizeof(float));
}
}
Related
I'm currently looking at porting my metro hash implementon to use C#7 features, as several parts might profit from ref locals to improve performance.
The hash does the calculations on a ulong[4] array, but the result is a 16 byte array. Currently I'm copying the ulong array to the result byte buffer, but this takes a bit of time.
So i'm wondering if System.Runtime.CompilerServices.Unsafe is safe to use here:
var result = new byte[16];
ulong[] state = Unsafe.As<byte[], ulong[]>(ref result);
ref var firstState = ref state[0];
ref var secondState = ref state[1];
ulong thirdState = 0;
ulong fourthState = 0;
The above code snippet means that I'm using the result buffer also for parts of my state calculations and not only for the final output.
My unit tests are successful and according to benchmarkdotnet skipping the block copy would result in a 20% performance increase, which is high enough for me to find out if it is correct to use it.
In current .NET terms, this would be a good fit for Span<T>:
Span<byte> result = new byte[16];
Span<ulong> state = MemoryMarshal.Cast<byte, ulong>(result);
This enforces lengths etc, while having good JIT behaviour and not requiring unsafe. You can even stackalloc the original buffer (from C# 7.2 onwards):
Span<byte> result = stackalloc byte[16];
Span<ulong> state = MemoryMarshal.Cast<byte, ulong>(result);
Note that Span<T> gets the length change correct; it is also trivial to cast into a Span<Vector<T>> if you want to use SIMD for hardware acceleration.
What you're doing seems fine, just be careful because there's nothing to stop you from doing this:
byte[] x = new byte[16];
long[] y = Unsafe.As<byte[], long[]>(ref x);
Console.WriteLine(y.Length); // still 16
for (int i = 0; i < y.Length; i++)
Console.WriteLine(y[i]); // reads random memory from your program, could cause crash
C# supports "fixed buffers", here's the kind of thing we can do:
public unsafe struct Bytes
{
public fixed byte bytes[16];
}
then
public unsafe static Bytes Convert (long[] longs)
{
fixed (long * longs_ptr = longs)
return *((Bytes*)(longs_ptr));
}
Try it. (1D arrays of primitive types in C# are always stored as a contiguous block of memory which is why taking the address of the (managed) arrays is fine).
You could also even return the pointer for more speed:
public unsafe static Bytes * Convert (long[] longs)
{
fixed (long * longs_ptr = longs)
return ((Bytes*)(longs_ptr));
}
and manipulate/access the bytes as you want.
var s = Convert(longs);
var b = s->bytes[0];
I am mainly a C++ programmer, but in my spare time I am attempting to come up to speed on C#. I have the following C++ function that I would like to convert-
#define COMPUTE_CRC32(cp,crc) (crc32lookup_table[((unsigned long)crc^(unsigned char)cp)&0xff]^(((unsigned long)crc>>8)&0x00FFFFFF))
unsigned long ComputeCRC32::Update(const void* ptrBytes, long numBytes)
{
const unsigned char* ptr_data = (const unsigned char*) ptrBytes;
while ( --numBytes >= 0 )
{
unsigned char data_byte = *ptr_data++ ;
m_ulCRC = COMPUTE_CRC32( data_byte, m_ulCRC );
}
return m_ulCRC;
}
I know there are many ways to do this but would like to see what the best way was to do it. This is what I have created so far -
public uint Update(object ptrBytes, int numBytes)
{
byte * ptr_data = (byte) ptrBytes;
while (--numBytes >= 0)
{
byte data_byte = *ptr_data++;
m_ulCRC = (GlobalMembersComputeCRC32.crc32lookup_table[((uint)m_ulCRC ^ (byte)data_byte) & 0xff] ^ (((uint)m_ulCRC >> 8) & 0x00FFFFFF));
}
return m_ulCRC;
}
What would be the best way to convert the pointers? Is there a better way to rewrite this in C#?
C# is a language that has pointers, but also has references (and references are not necessarily addresses). An array such as byte[] in C# is the usual way of representing something you might use pointers for in C++.
To use pointers, you use unsafe. If you are thinking in C#, people tend to avoid unsafe as it is generally "unsafe"; the runtime instead enforces checks to avoid things like buffer overruns in arrays. Instead, the psuedo code for Crc32 might be:
public uint Crc32(byte[] data) {
uint result;
for (int i= 0; i < data.Length; i++) {
byte data_byte = data[i];
result = doCrc(...stuff with data_byte...);
}
return result;
}
Note that the for loop uses data.Length as its limit check (ref: Eric Gunnerson: Efficiency of iteration over arrays), as this can be optimised by the JIT against the array length. If you use a separate length parameter it can't be, so this is to be avoided (or combined with length, if the required iteration count might be less than the array length).
These pointers are not doing anything tricky. They're just array iterators.
public uint Update( byte[] ptrBytes, int numBytes )
{
for( int i = 0; i < numBytes; i++ )
{
byte data_byte = ptr_data[i];
m_ulCRC = ...
}
return m_ulCRC;
}
I have a C# NETMF project, and I need to convert a float to a byte[] and vice versa. The problem is, NETMF doesn't have System.BitConverter like .NET, so I can't really find any way of doing it without going low level and doing it myself.
I have always programmed high-level (Java, Python, C#, etc.) and have only dabbled in C++, so I don't really know how to turn a float into a byte array.
What would some sample code of a boilerplate function for doing this look like?
The StructLayoutAttribute is supported by the .NET Micro Framework, so you could use a C++ style union to get the bytes of a float (and the other way around too):
[StructLayout(LayoutKind.Explicit)]
public struct FloatUnion
{
[FieldOffset(0)] public float Value;
[FieldOffset(0)] public byte Byte0;
[FieldOffset(1)] public byte Byte1;
[FieldOffset(2)] public byte Byte2;
[FieldOffset(3)] public byte Byte3;
public byte[] ToByteArray()
{
return new[] { Byte0, Byte1, Byte2, Byte3 };
}
public static byte[] FloatToBytes(float value)
{
return new FloatUnion { Value = value }.ToByteArray();
}
public static float BytesToFloat(byte[] bytes)
{
if (bytes.Length != 4) throw new ArgumentException("You must provide four bytes.");
return new FloatUnion { Byte0 = bytes[0], Byte1 = bytes[1], Byte2 = bytes[2], Byte3 = bytes[3] }.Value;
}
}
Unlike the integers (Int32, Byte, UInt64, etc) where each value is easily determined from the status of each bit in the integer's bytes, there is no intuitive representation of a floating-point number in binary, so the IEEE defined a specification for floating point numbers: IEEE-754. Suffice to say, it isn't simple, but following the rules in the specification will allow you to serialize a .NET System.Single and System.Double instance to a series of bytes.
The desktop .NET Framework actually cheats here. The GetBytes(Single) function actually just casts the Single instance to an Int32 then copies the raw bytes into a 4-byte array using raw pointers. However you can't take this useful shortcut because the micro framework does not support pointers - even worse: the MF doesn't include BinaryWriter either. You'll have to roll your own IEEE-754 serializer I'm afraid.
Use a BinaryWriter on top of a MemoryStream.
How can I convert an int to a byte* at a certain index in a byte*?
Ideally I would like to have something like:
unsafe{
byte* igm=stackalloc byte[8];
igm[4]=4283;
}
It would set the first part of the bit to igm[4] and the rest into igm[5].
Edit: I realize there may be a lot of possible ways to handle this, i am looking for the most efficient way if possible.
try this:
unsafe
{
byte* igm = stackalloc byte[8];
*(int*)(igm + 4) = 4283;
}
Once you realize that you can use simple pointer arithmetic to index anywhere in your byte array, things get a LOT easier.
The type system in C# will prevent you from doing that, as you might have noticed. However, you can cast your pointers to be the appropiate types:
unsafe
{
byte* igm = stackalloc byte[8];
int* intPtr = (int*)igm;
intPtr[1] = 4283;
}
You need to break your int to sizeof(int) count of bytes and then manually set this parts to your byte* at specified indexes.
This will be safer as you'll know WHAT and WHERE you place your data.
his question is about converting between a struct and a byte array. Many solutions are based around GCHandle.Alloc() and Marshal.StructureToPtr(). The problem is these calls generate garbage. For example, under Windows CE 6 R3 about 400 bytes of garbarge is made with a small structure. If the code below could be made to work the solution could be considered cleaner. It appears the sizeof() happens too late in the compile to work.
public struct Data
{
public double a;
public int b;
public double c;
}
[StructLayout(LayoutKind.Explicit)]
public unsafe struct DataWrapper
{
private static readonly int val = sizeof(Data);
[FieldOffset(0)]
public fixed byte Arr[val]; // "fixed" is to embed array instead of ref
[FieldOffset(0)]
public Data; // based on a C++ union
}
You can in fact use the constant value 1 as the size of the fixed array in DataWrapper. There is no bounds checking when accessing an unsafe fixed array nor is there any mechanism to request its length at runtime. The presence of the Data member at offset 0 is enough to ensure that you can actually read and write sizeof(Data) bytes to/from DataWrapper.Arr.
With that said, a more straight forward solution would be to cast a Data* pointer to byte* as follows:
unsafe {
Data d = new Data();
d.a = 125.5;
d.b = 0x7FEEDDEE;
d.c = 130.0;
byte* bytes = (byte*)&d;
for (int i = 0; i < sizeof(Data); i++) {
Console.WriteLine(i + ": " + bytes[i]);
}
}