I would like to truncate a cube.
If I have a 1d array I can do this:
var oldarray = new double[n];
var newarray = new double[m];
Array.Copy(oldarray, newarray, m);
for m smaller n, obviously oldarray would store some data...
I would like to do the same on a cube, like:
var oldarray = new double[n,n,n];
var newarray = new double[m,m,m];
Array.Copy(oldarray, newarray, m);
Whats the fastest (most performant) way please? (apart from using a triple for loop) thanks.
You could still use Array.Copy, but then the multi-dimensional one:
for (int i = 0 ; i < m ; i++)
{
Array.Copy(oldarray, i, newarray, i, oldarray.GetLength(i));
}
Related
Just curious is there a quicker/neater way to achieve this:
double[] source = ... // some initialisation
var target = new double[1, source.Length];
for (var c = 0; c < source.Length; c++)
{
target[0, c] = source[c];
}
Initialiaze the array like this:
double[,] target = { { /* your list of values */ } };
Then you have a two dimentional array with only one row.
Since you are mentioning this is for P/Invoke, BlockCopy is probably reasonable to use:
double[] source = new double [] {1,2,3,4,7,8,9,0};// some initialisation
double[,] target = new double[1, source.Length];
Buffer.BlockCopy(source, 0, target, 0, source.Length * sizeof(double));
I got stuck with Access violation exception in managed code. Histogram pointer is not null and everything seems ok. Got example of creating IntPtr's from http://www.emgu.com/forum/viewtopic.php?f=8&t=59
// initializing data
var random = new Random();
var array = new double[1000];
for (int i = 0; i < 1000; i++)
{
array[i] = random.NextDouble();
}
var arrayPtr = GetDataPtr(array);
//initializing ranges array
double[] rangesArray = { 0, 1 };
var rangesArrayPtr = GetRangesArrayPtr(rangesArray);
//creating and querying histogram
var histogramStructure = CvInvoke.cvCreateHist(1, new[] {20}, HIST_TYPE.CV_HIST_ARRAY, rangesArrayPtr, true);
var histogram = CvInvoke.cvMakeHistHeaderForArray(1, new[] { 20 }, histogramStructure, arrayPtr, rangesArrayPtr, 1);
CvInvoke.cvNormalizeHist(histogram, 1.0);
CvInvoke.cvQueryHistValue_1D(histogram, 0); // getting exception here
help methods
private static IntPtr[] GetRangesArrayPtr(double[] array)
{
var ranges = new IntPtr[1];
ranges[0] = Marshal.AllocHGlobal(array.Length * sizeof(double));
Marshal.Copy(array, 0, ranges[0], array.Length);
return ranges;
}
private static IntPtr GetDataPtr(double[] array)
{
var ranges = new IntPtr();
ranges = Marshal.AllocHGlobal(array.Length * sizeof(double));
Marshal.Copy(array, 0, ranges,array.Length);
return ranges;
}
I had the same problem in a recent project and solved it by copying the histogram values into a new array.
Double[] histtemp = new double[255];
Histogram.MatND.ManagedArray.CopyTo(histtemp,0);
Now you can access the histogram values in histtemp. I hope it will help future viewers.
I have an array of Floats that need to be converted to a byte array and back to a float[]... can anyone help me do this correctly?
I'm working with the bitConverter class and found myself stuck trying to append the results.
The reason I'm doing this is so I can save runtime values into a IO Stream. The target storage is Azure Page blobs in case that matters. I don't care about what endian this is stored in, as long as it input matches the output.
static byte[] ConvertFloatToByteArray(float[] floats)
{
byte[] ret = new byte[floats.Length * 4];// a single float is 4 bytes/32 bits
for (int i = 0; i < floats.Length; i++)
{
// todo: stuck...I need to append the results to an offset of ret
ret = BitConverter.GetBytes(floats[i]);
}
return ret;
}
static float[] ConvertByteArrayToFloat(byte[] bytes)
{ //to do }
If you're looking for performance then you could use Buffer.BlockCopy. Nice and simple, and probably about as fast as you'll get in managed code.
var floatArray1 = new float[] { 123.45f, 123f, 45f, 1.2f, 34.5f };
// create a byte array and copy the floats into it...
var byteArray = new byte[floatArray1.Length * 4];
Buffer.BlockCopy(floatArray1, 0, byteArray, 0, byteArray.Length);
// create a second float array and copy the bytes into it...
var floatArray2 = new float[byteArray.Length / 4];
Buffer.BlockCopy(byteArray, 0, floatArray2, 0, byteArray.Length);
// do we have the same sequence of floats that we started with?
Console.WriteLine(floatArray1.SequenceEqual(floatArray2)); // True
There's the BitConverter.ToSingle(byte[] value, int startIndex) method that should help out here.
Returns a single-precision floating
point number converted from four bytes
at a specified position in a byte
array.
Your probably want something like (untested):
static float[] ConvertByteArrayToFloat(byte[] bytes)
{
if(bytes == null)
throw new ArgumentNullException("bytes");
if(bytes.Length % 4 != 0)
throw new ArgumentException
("bytes does not represent a sequence of floats");
return Enumerable.Range(0, bytes.Length / 4)
.Select(i => BitConverter.ToSingle(bytes, i * 4))
.ToArray();
}
EDIT: Non-LINQ:
float[] floats = new float[bytes.Length / 4];
for (int i = 0; i < bytes.Length / 4; i++)
floats[i] = BitConverter.ToSingle(bytes, i * 4);
return floats;
You are not moving the position when you copy the float[i] into the byte array, you should write something like
Array.Copy(BitConverter.GetBytes(float[i]),0,res,i*4);
instead of just:
ret = BitConverter.GetBytes(floats[i]);
the inverse function follow the same strategy.
static float[] ConvertByteArrayToFloat(byte[] bytes)
{
if(bytes.Length % 4 != 0) throw new ArgumentException();
float[] floats = new float[bytes.Length/4];
for(int i = 0; i < floats.Length; i++)
{
floats[i] = BitConverter.ToSingle(bytes, i*4);
}
return floats;
}
Convertion from Double[] src to Byte[] dst
can be efficiently done in C# by fixed pointers:
fixed( Double* pSrc = src)
{
fixed( Byte* pDst = dst)
{
Byte* ps = (Byte*)pSrc;
for (int i=0; i < dstLength; i++)
{
*(pDst + i) = *(ps +i);
}
}
}
How can I do the same for List src ?
I.e. how can I get fixed pointer to array Double[]
included in List ?
Thanks.
I have used these helper methods before:
byte[] GetBytesBlock(double[] values)
{
var result = new byte[values.Length * sizeof(double)];
Buffer.BlockCopy(values, 0, result, 0, result.Length);
return result;
}
double[] GetDoublesBlock(byte[] bytes)
{
var result = new double[bytes.Length / sizeof(double)];
Buffer.BlockCopy(bytes, 0, result, 0, bytes.Length);
return result;
}
An example:
List<double> myList = new List<double>(){ 1.0, 2.0, 3.0};
//to byte[]
var byteResult = GetBytesBlock(myList.ToArray());
//back to List<double>
var doubleResult = GetDoublesBlock(byteResult).ToList();
not sure what you are intending, but I think ... you want
System.Runtime.Interopservices.Marshal.StructToPtr.
You can always use the ToArray() method on the List<Double> object to get a Double[].
You can use reflection to get the reference to the private T[] _items field, in the List instance.
Warning: In your code snippet, you need to make sure dstLength is the minimum of dst and src lengths in bytes, so that you don't try to copy more bytes than what are available. Probably you do so by creating dst with exactly the needed size to match the src, but your snippet doesn't make it clear.
Use the List<T>.ToArray() method and operate on the resulting array.
This might work, but you will have a data loss- content of the array will be 3 and 34 .
List<double> list = new List<double>();
list.Add(Math.PI);
list.Add(34.22);
byte[] arr = (from l in list
select (byte)l).ToArray<byte>();
Why don't you just access the list as usual?
List<double> list = new List<double>();
list.Add(Math.PI);
list.Add(34.22);
byte[] res = new byte[list.Count * sizeof(double)];
unsafe
{
fixed (byte* pres = res)
{
for (int i = 0; i < list.Count; i++)
{
*(((double*)pres) + i) = list[i];
}
}
}
I haven't tested it thoroughly and i seldomly need unsafe code, but it seems to work fine.
Edit: here is another (imo preferable) solution, without unsafe code:
int offset = 0;
for (int i = 0; i < list.Count; i++)
{
long num = BitConverter.DoubleToInt64Bits(list[i]);
for (int j = 0; j < 8; j++)
{
res[offset++] = (byte)num;
num >>= 8;
}
}
How to convert an int[,] to byte[] in C#?
Some code will be appreciated
EDIT:
I need a function to perform the following:
byte[] FuncName (int[,] Input)
Since there is very little detail in your question, I can only guess what you're trying to do... Assuming you want to "flatten" a 2D array of ints into a 1D array of bytes, you can do something like that :
byte[] Flatten(int[,] input)
{
return input.Cast<int>().Select(i => (byte)i).ToArray();
}
Note the call to Cast : that's because multidimensional arrays implement IEnumerable but not IEnumerable<T>
It seem that you are writing the types wrong, but here is what you might be looking for:
byte[] FuncName (int[,] input)
{
byte[] byteArray = new byte[input.Length];
int idx = 0;
foreach (int v in input) {
byteArray[idx++] = (byte)v;
}
return byteArray;
}
Here's an implementation that assumes you are attempting serialization; no idea if this is what you want, though; it prefixes the dimensions, then each cell using basic encoding:
public byte[] Encode(int[,] input)
{
int d0 = input.GetLength(0), d1 = input.GetLength(1);
byte[] raw = new byte[((d0 * d1) + 2) * 4];
Buffer.BlockCopy(BitConverter.GetBytes(d0), 0, raw, 0, 4);
Buffer.BlockCopy(BitConverter.GetBytes(d1), 0, raw, 4, 4);
int offset = 8;
for(int i0 = 0 ; i0 < d0 ; i0++)
for (int i1 = 0; i1 < d1; i1++)
{
Buffer.BlockCopy(BitConverter.GetBytes(input[i0,i1]), 0,
raw, offset, 4);
offset += 4;
}
return raw;
}
The BitConverter converts primitive types to byte arrays:
byte[] myByteArray = System.BitConverter.GetBytes(myInt);
You appear to want a 2 dimensional array of ints to be converted to bytes. Combine the BitConverter with the requisite loop construct (e.g foreach) and whatever logic you want to combine the array dimensions.