What kind of variable should I initialize and how do I do it?
For example
byte[][][] data = ?????;
The function is from LibJpeg.NET library. The function definition is
Int32 jpeg_read_raw_data (
Byte[][][] data,
Int32 max_lines
)
There is no good documentation for this function, so I don't know what to send it, but I want to try to send something and see what the function will return.
The problem is that I don't know how to call it.
byte[][][] is an array of (arrays of (arrays of bytes)), also called a jagged array. It's not the same as a three-dimensional array (e.g. byte[,,] x = new byte[10,5,3];).
Here is an example for allocating and initializing such a structure:
byte[][][] a = new byte[10][][];
for (int i = 0; i < 10; i++)
{
a[i] = new byte[5][];
for (int ii = 0; i < 5; i++)
{
a[i][ii] = new byte[3];
a[i][ii][0] = 42;
a[i][ii][1] = 52;
a[i][ii][2] = 62;
}
}
Oh, and by the way, here's a related question: C# 3 dimensional array definition issue.
And here's the MSDN entry on jagged arrays: http://msdn.microsoft.com/en-us/library/2s05feca.aspx.
byte[][][] data is a 3 dimensional array, allocate it accordingly
= {{{0,1,2}{3,4,5}{6,7,8}}
{{0,1,2}{3,4,5}{6,7,8}}
{{0,1,2}{3,4,5}{6,7,8}}}
NOTE! THIS WILL NOT WORK! This is a jagged array, so unless you define data as byte[3,3,3] then you are going to go nowhere.
It occurred to me: I have no idea why you are using this library. Is there a reason the built in .NET JPEG classes aren't sufficient? If so, I imagine there would be a way to use the LibJpeg.NET library to get a byte stream from a file and arrange it into a 3D array. This seems like a very "hacky" way to do this, and it makes me wonder if it's just a port of a C library with no updates to fit into a framework like .NET or even OOP.
After a short look into the sources of LibJpeg.NET it looks like you should initialize the first dimension of the data array with the number of scan lines:
byte[][][] data = new byte[max_lines][][];
The rest of the array is filled when reading the raw data.
I'm not too familiar with that API so I don't know how you would get the number of scan lines though.
Just to correct firoso's answer, you can allocate arrays like that, he just has not specified the types as required in C# (His code would work in Java, AFAIK)
private byte[][][] lol =
{
new[]
{
new byte[] {0, 1, 2},
new byte[] {3, 4, 5},
new byte[] {6, 7, 8}
},
new[]
{
new byte[] {0, 1, 2},
new byte[] {3, 4, 5},
new byte[] {6, 7, 8}
},
new[]
{
new byte[] {0, 1, 2},
new byte[] {3, 4, 5},
new byte[] {6, 7, 8}
}
};
The new[] is actually a shortcut for new byte[][] and the new byte[] cannot be shortened to new[] as then the compiler infers the numbers types as int.
I would not recommend using this method if you can use Heinzi's iterative method instead; I am only pointing out it is possible to allocate multidimensional arrays like this (it is good for a lot of specific data).
Related
Im trying to pass as parameter this matrix:
double[,] array2 = new double[4, 5]
{
{ 45, -6, 8, -3, 48 },
{ 0, -56.733333, 3.6444444, -6.8666667, 26.8666667 },
{ 0, 0, 78.17111712, -15.2432, -133.378378},
{ 0, 0, 0, 94.190193, 319.457667}
};
But when I try to use it in the other function i get problems with out of range, I dont know what I'm doing wrong since I'm using the same range that I specified when I created the objetc double[,] Im using the next code:
For passing the matrix:
Example1 a = new Example1();
a.function(array2,4,5);
Using the function:
public double[] function(double[,] nn, int n, int m)
{
double[,] ma = new double[n, m];
ma = nn;
double[] x = new double[5] { 0, 0, 0, 0, 0 };
x[n] = ma[n, m] / ma[n, n];
return x;
}
Im getting the error when I try to use ma[n,m] / ma[n,n] And I dont know why is happenig cause ma[n,m] it happens to exist and ma[n,n] happens to exist to.
If in doubt, read the documentation
Arrays (C# Programming Guide)
Array Overview
An array has the following properties:
An array can be Single-Dimensional, Multidimensional or Jagged.
The number of dimensions and the length of each dimension are established when the array instance is created. These values can't be
changed during the lifetime of the instance.
The default values of numeric array elements are set to zero, and reference elements are set to null.
A jagged array is an array of arrays, and therefore its elements are reference types and are initialized to null.
Arrays are zero indexed: an array with n elements is indexed from 0 to n-1.
Array elements can be of any type, including an array type.
Array types are reference types derived from the abstract base type Array. Since this type implements IEnumerable and IEnumerable<T>, you
can use foreach iteration on all arrays in C#.
Some further reading
Multidimensional Arrays
Zero-based numbering
Why are zero-based arrays the norm?
The problem is that the matrix does not recognize double [4,5] cause when declarated goes from [0..3] taking 4 spaces and the [4,#] will take 5 spaces.
For Serialization of Primitive Array, i'am wondering how to convert a Primitive[] to his corresponding byte[]. (ie an int[128] to a byte[512], or a ushort[] to a byte[]...)
The destination can be a Memory Stream, a network message, a file, anything.
The goal is performance (Serialization & Deserialization time), to be able to write with some streams a byte[] in one shot instead of loop'ing' through all values, or allocate using some converter.
Some already solution explored:
Regular Loop to write/read
//array = any int[];
myStreamWriter.WriteInt32(array.Length);
for(int i = 0; i < array.Length; ++i)
myStreamWriter.WriteInt32(array[i]);
This solution works for Serialization and Deserialization And is like 100 times faster than using Standard System.Runtime.Serialization combined with a BinaryFormater to Serialize/Deserialize a single int, or a couple of them.
But this solution becomes slower if array.Length contains more than 200/300 values (for Int32).
Cast?
Seems C# can't directly cast a Int[] to a byte[], or a bool[] to a byte[].
BitConverter.Getbytes()
This solution works, but it allocates a new byte[] at each call of the loop through my int[]. Performances are of course horrible
Marshal.Copy
Yup, this solution works too, but same problem as previous BitConverter one.
C++ hack
Because direct cast is not allowed in C#, i tryed some C++ hack after seeing into memory that array length is stored 4 bytes before array data starts
ARRAYCAST_API void Cast(int* input, unsigned char** output)
{
// get the address of the input (this is a pointer to the data)
int* count = input;
// the size of the buffer is located just before the data (4 bytes before as this is an int)
count--;
// multiply the number of elements by 4 as an int is 4 bytes
*count = *count * 4;
// set the address of the byte array
*output = (unsigned char*)(input);
}
and the C# that call:
byte[] arrayB = null;
int[] arrayI = new int[128];
for (int i = 0; i < 128; ++i)
arrayI[i] = i;
// delegate call
fptr(arrayI, out arrayB);
I successfully retrieve my int[128] into C++, switch the array length, and affecting the right adress to my 'output' var, but C# is only retrieving a byte[1] as return. It seems that i can't hack a managed variable like that so easily.
So i really start to think that all theses casts i want to achieve are just impossible in C# (int[] -> byte[], bool[] -> byte[], double[] -> byte[]...) without Allocating/copying...
What am-i missing?
How about using Buffer.BlockCopy?
// serialize
var intArray = new[] { 1, 2, 3, 4, 5, 6, 7, 8 };
var byteArray = new byte[intArray.Length * 4];
Buffer.BlockCopy(intArray, 0, byteArray, 0, byteArray.Length);
// deserialize and test
var intArray2 = new int[byteArray.Length / 4];
Buffer.BlockCopy(byteArray, 0, intArray2, 0, byteArray.Length);
Console.WriteLine(intArray.SequenceEqual(intArray2)); // true
Note that BlockCopy is still allocating/copying behind the scenes. I'm fairly sure that this is unavoidable in managed code, and BlockCopy is probably about as good as it gets for this.
Aside from looping. Is there an efficient way to instantiate a 2D array from multiple 1D arrays.
My 1D arrays must behave as column vectors in my 2D rectangular array. So Column 0 = First 1D array, Column 1 = Second 1D Array, etc...
I've also tried System.Buffer.BlockCopy, but block copy will roll the single 1D array into multiple columns which is not what I want.
Simple example of how I want to transform:
var c1 = new int[] {1, 2, 3, 4};
var c2 = new int[] {5, 6, 7, 8};
var result = new int[,]
{{1,5},
{2,6},
{3,7},
{4,8}};
Looping with unsafe code and pointers will be the fasted approach that C# can offer. Use unsafe because it eliminates the bounds checking which cannot be eliminated in this case b the current JIT.
Loop sequentially through the 2D array in memory order when writing. This means that you need to write row-by-row instead of column-by-column. This trick optimizes memory access and allows you to just increment the write pointer instead of calculating the address each time (y*width+y).
Aside from looping this will do(since you did not specify this as also a no solution):
var c1 = new int[] { 1, 2, 3, 4 };
var c2 = new int[] { 5, 6, 7, 8 };
var c3 = new int[,]
{
{c1[0],c2[0]},
{c1[1],c2[1]},
{c1[2],c2[2]},
{c1[3],c2[3]}
};
I'm kinda new to C# and want to port some program from C# to PHP
one thing strange for me is,
double[][] rate = { new double[] { 1, 2, 3, 4, 5 },
new double[] { 2, 4, 6, 8, 10}
};
double[,,] quest = {{{1,2,3,4}, {1,1,2,3}, {2,3,4,5}},
{{2,3,4,5}, {1,1,1,1}, {3,3,3,3}}
};
for ( int i = 0; i < f.Length; i++ ){
dummy = rate[i][(int)quest[1, 1, 1] - 3];
}
my question is,
why can you call cube-array quest[1,1,1] this way, but then again why call array rate[i][blah] like in PHP?
do they work interchangeably? just a matter of expression , or something more than I know?
int[,,] is a multidimensional array. It's also called a rectangular array, as it's more like an X-dimensional rectangular block of ints (with X=3 in this case). Each slice, row, and column of the array has the same size as any other slice/row/column, respectively.
int[][][] is an array of arrays of arrays of ints. It's more treeish. It's also called a "jagged" array, because each array at a given index can have different lengths.
In many cases, the two can do the same things, but they each have their strengths. Rectangular arrays have a predictable "shape", and you don't have to be as paranoid about whether x[a, b, c] exists if a, b and c are within the bounds you set when you created the array. You also don't have to worry about creating arrays and subarrays for each level of the array. On the other hand, jagged arrays can be more flexible when it comes to resizing and expanding one part of the array without doing the whole thing.
As far as analogous structures go, a jagged array is closer to how PHP tends to treat arrays.
The first one is array-of-array and the another is Multidimensional array.
here is the link talk about this Arrays
I developing an image processing software.
int size = 3;
int[,] kernel = new int[size, size] {
{1, 2, 1},
{2, 4, 2},
{1, 2, 1}
};
When I compile my code, I have a compile error message "A constant value is expected" from size variable. I understand I can put 3 on my kernel array initialization or make my size constant. What I ask is the technical reason behind this error because this error don't make any sense for me.
You can either create an array with empty values by specifying only the size (which may be variable), or list the values in an initializer and optionally specify a constant size. But you can't combine an initializer with a non-constant size. In the case of the initializer you're allowed to specify constant values for the size, if you want to make sure that the initializer results in an array of a specific size.
Just get rid of the size parameters, your initializer list already specifies the size.
The compiler requires a constant expression for the array ranks. You can declare size as const int, or you can just let the compiler figure it out from the initialization expression:
int[,] kernel = new int[,] {
{1, 2, 1},
{2, 4, 2},
{1, 2, 1}
};
In the delclaration your are adding the elements, so you don't need to specify the size.
So this will work :
int[,] kernel = new int[,] {
{1, 2, 1},
{2, 4, 2},
{1, 2, 1}
};