convert 3 dimensional array to a 2 dimensional array - c#

I have this byte array:
byte[,,] somedata = new byte[100,150,3];
~somedata is now populated by an external input.
I want to use the values in just this:
byte[,] useThisDataOnly = new byte[100,150];
Presently, I use this:
foreach (int x=0,x< 100; x++)
{
foreach (int y=0,y< 150; y++)
{
useThisDataOnly [x,y] = somedata[x,y,0];
}
}
Is there a quicker way to do this at all?
Also, I am going to flatten this useThisDataOnly (as I heard it is quicker to manipulate with).
Any suggestions?

The difficulty you have with optimising this is that the bytes that you want to leave out are in the most "rapidly moving" index.
What I mean by that is: If you assign consecutive numbers to each array element like so:
byte[,,] source = new byte[100, 150, 3];
for (int i = 0, n = 0; i < 100; ++i)
for (int j = 0; j < 150; ++j)
for (int k = 0; k < 3; ++k, ++n)
source[i, j, k] = unchecked ((byte)n);
If you printed out the contents in flattened order, you'd get 0..255 repeating.
Then you exclude the final dimension:
for (int i = 0; i < 100; ++i)
for (int j = 0; j < 150; ++j)
dest[i, j] = source[i, j, 0];
If you print the result out in flattened order, you'll get:
0, 3, 6, 9, 12, 15, ...
So you can see that in order to transform the input to the output you need to take every third byte, and unfortunately there is no quick way to do that.
However, if you were able to ask for the array to be created with the index to be omitted first:
byte[,,] source = new byte[3, 100, 150];
then you would be able to use Buffer.BlockCopy().
I guess this isn't an option - if not, the hand-coded loop is probably the quickest you'll be able to do it without resorting to unsafe code.
Unsafe code
Here's how you can do it using unsafe code and pointers. This might not even make it faster, so before choosing to do it like this you need to (a) be sure that doing the simple way is really too slow and (b) do some careful timings of a release build using Stopwatch to ensure that it really is worth using unsafe code.
Also be aware of the drawbacks of using unsafe code! Unsafe code requires elevated permissions and can cause your program to crash with low-level C++-style wild pointer errors!
using System;
using System.Diagnostics;
namespace Demo
{
internal static class Program
{
static void Main()
{
byte[,,] source = new byte[100, 150, 3];
for (int i = 0, n = 0; i < 100; ++i)
for (int j = 0; j < 150; ++j)
for (int k = 0; k < 3; ++k, ++n)
source[i, j, k] = unchecked ((byte)n);
byte[,] dest1 = new byte[100, 150];
byte[,] dest2 = new byte[100, 150];
for (int i = 0; i < 100; ++i)
for (int j = 0; j < 150; ++j)
dest1[i, j] = source[i, j, 0];
unsafe
{
fixed (byte* sp = source)
fixed (byte* dp = dest2)
{
byte* q = dp;
byte* p = sp;
for (int i = 0; i < 100*150; ++i)
{
*q++ = *p;
p += 3;
}
}
}
for (int i = 0; i < 100; ++i)
for (int j = 0; j < 150; ++j)
Trace.Assert(dest1[i, j] == dest2[i, j], "Arrays should be identical");
}
}
}
I personally don't think that it will be too slow using the simple, safe loop anyway, but now at least you have some code to try out.

Related

C# also gives Double Folded Array Leash

int[] x = { 1, 2, 3, 4,5 };
int[] y = { 5, 4, 3, 2, 1 };
int[,] s=new int[(x.Length)*(x.Length),2];
for (int i = 0; i < x.Length; i++)
{
for (int j = 0; j < y.Length; i++)
{
s[i, j] = x[i] * y[j];
Console.WriteLine(x[i] + " * " + y[j] + " = " + s[i, j]);
}
}
IndexOutOfRangeException: Index was outside the bounds of the array.
It gives a memory error, but it says it hangs the memory of the variable, but I transfer more than the field of the series. I couldn't figure out what the problem was. Can you help?
IndexOutOfRangeException: Index was outside the bounds of the array.
Change:
for (int i = 0; i < x.Length; i++)
{
for (int j = 0; j < y.Length; i++)
To:
for (int i = 0; i <= x.Length-1; i++)
{
for (int j = 0; j <= y.Length-1; j++)
Also this line:
int[,] s=new int[(x.Length)*(x.Length),2];
Although no big problems but if x[] and y[] are different lengths might cause issues with storing i,j values. Did you mean to declare like :=
int[,] s=new int[(x.Length)*(y.Length),2];

Efficiency in swapping array elements vs Array indices

I have a quick question: I know that the complexity of both snippets is same. Yet, I want to know which one is comparatively better and why? This is the selection sort code:
This is what I wrote:
for (int i = 0; i < n - 1; i++)
{
for (int j = i + 1; j <= n - 1; j++)
{
if (a[j] < a[i])
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
This is what my friend wrote:
for (int i = 0; i < n - 1; i++)
{
int iMin = i;
for (int j = i + 1; j <= n - 1; j++)
{
if (a[j] < a[i])
{
iMin = j;
}
int temp = a[i];
a[i] = a[iMin];
a[iMin] = temp;
}
}
Your code is slightly faster because you make swaps only when a[j] < a[i], whereas your friend's code is always making a swap. So, in most cases, your code will make less swaps.
The complexity of both codes are indeed the same, but your "constants" are smaller, so your code is faster.

C#: Out of memory Exception

I have written a console application
Int64 sum = 0;
int T = Convert.ToInt32(Console.ReadLine());
Int64[] input = new Int64[T];
for (int i = 0; i < T; i++)
{
input[i] = Convert.ToInt32(Console.ReadLine());
}
for (int i = 0; i < T; i++)
{
int[,] Matrix = new int[input[i], input[i]];
sum = 0;
for (int j = 0; j < input[i]; j++)
{
for (int k = 0; k < input[i]; k++)
{
Matrix[j, k] = Math.Abs(j - k);
sum += Matrix[j, k];
}
}
Console.WriteLine(sum);
}
When I gave input as
2
1
999999
It gave Out of memory exception. Can you please help.
Look at what you are allocating:
input[] is allocated as 2 elements (16 bytes) - no worries
But then you enter values: 1 and 999999 and in the first iteration of the loop attempt to allocate
Matrix[1,1] = 4 bytes - again no worries,
but the second time round you try to allocate
Matrix[999999, 999999]
which is 4 * 10e12 bytes and certainly beyond the capacity of your computer even with swap space on the disk.
I suspect that this is not what you really want to allocate (you'd never be able to fill or manipulate that many elements anyway...)
If you are merely trying to do the calculations as per your original code, there is not need to allocate or use the array, as you only ever store one value and immediately use that value and then never again.
Int64 sum = 0;
int T = Convert.ToInt32(Console.ReadLine());
Int64[] input = new Int64[T];
for (int i = 0; i < T; i++)
input[i] = Convert.ToInt32(Console.ReadLine());
for (int i = 0; i < T; i++)
{
// int[,] Matrix = new int[input[i], input[i]];
sum = 0;
for (int j = 0; j < input[i]; j++)
for (int k = 0; k < input[i]; k++)
{
//Matrix[j, k] = Math.Abs(j - k);
//sum += Matrix[j, k];
sum += Math.Abs(j - k);
}
Console.WriteLine(sum);
}
But now beware - a trillion sums is going to take forever to calculate - it won't bomb out, but you might like to take a vacation, get married and have kids before you can expect a result.
Of course instead of doing the full squared set of calculations, you can calculate the sum thus:
for (int i = 0; i < T; i++)
{
sum = 0;
for (int j = 1, term = 0; j < input[i]; j++)
{
term += j;
sum += term * 2;
}
Console.WriteLine(sum);
}
So now the calculation is O(n) instead of O(n^2)
And if you need to know what the value in Matrix[x,y] would have been, you can calculate it by the simple expression Math.Abs(x - y) thus there is no need to store that value.

Best/Fastest Way To Change/Access Elements of a Matrix

I'm quite new to C# and I'm having difficult with our arrays, arrays of arrays, jagged arrays, matrixes and stuff. It's quite different from the C++ , since I can't get a reference (unless I use unsafe code) to a row of a matrix, using pointers and stuff.
Anyway, here's the problem: I have a struct/class called "Image" that cointains 1024 columns and 768 lines. For each line/column theres a 'pixel' struct/class that contains 3 bytes. I'd like to get/set pixels in random places of the matrix as fast as possible.
Let's pretend I have a matrix with 25 pixels. That is 5 rows and 5 columns, something like this:
A B C D E
F G H I J
K L M N O
P Q R S T
U V X W Y
And I need to compare M to H and R. Then M to L and N. Then I need to 'sum' G+H+I+L+M+N+Q+R+S.
How can I do that?
Possibilities:
1) Create something like pixel[5][5] (that's a jagged array, right?), which will be slow whenever I try to compare elements on different columns, right?
2) Create something like pixel[25] , which won't be as easy to code/ready because I'll need to do some (simple) math each and everything I want to access a element
3) Create something like pixe[5,5] (that's a multi-dimensional array, right?)... But I don't know how that will be translated to actual memory... If it's going to be a single block of memory, like the pixe[25], or what...
Since I intend to do this operations ('random' sums/comparison of elements that are in different rows/columns) tens of thousands of times per image. And I have 1000+ imagens. Code optimization is a must... Sadly I'm not sure which structure / classe I should use.
TL;DR: Whats the FASTEST and whats the EASIEST (coding wise) way of getting/setting elements in random positions of a (fixed size) matrix?
edit: I do not want to compare C++ to C#. I'm just saying I AM NEW TO C# and I'd like to find the best way to accomplish this, using C#. Please don't tell me to go back to C++.
I have worked on pixel based image processing in C#. I found that pattern #2 in your list is fastest. For speed, you must forget about accessing pixels via some kind of nice abstract interface. The pixel processing routines must explicitly deal with the width and height of the image. This makes for crappy code in general, but unless Microsoft improves the C# compiler, we are stuck with this approach.
If your for loops start at index 0 of an array, and end at array.Length - 1, the compiler will optimize out the array index bounds testing. This is nice, but typically you have to use more than one pixel at a time while processing.
I just finished testing, heres the result:
SD Array Test1: 00:00:00.9388379
SD Array Test2: 00:00:00.4117926
MD Array Test1: 00:00:01.4977765
MD Array Test2: 00:00:00.8950093
Jagged Array Test1: 00:00:03.6850013
Jagged Array Test2: 00:00:00.5036041
Conclusion: Single dimensional array is the way to go... Sadly we lose in readability.
And heres the code:
int[] myArray = new int[10000 * 10000];
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
myArray[(i*10000)+j] = i+j;
}
}
Stopwatch sw = new Stopwatch();
int sum = 0;
sw.Start();
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
sum += myArray[(j * 10000) + i];
}
}
sw.Stop();
Console.WriteLine("SD Array Test1: " + sw.Elapsed.ToString());
sum=0;
sw.Restart();
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
sum += myArray[(i * 10000) + j];
}
}
sw.Stop();
Console.WriteLine("SD Array Test2: " + sw.Elapsed.ToString());
myArray = null;
int[,] MDA = new int[10000, 10000];
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
MDA[i, j] = i + j;
}
}
sum = 0;
sw.Restart();
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
sum += MDA[j, i];
}
}
sw.Stop();
Console.WriteLine("MD Array Test1: " + sw.Elapsed.ToString());
sw.Restart();
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
sum += MDA[i, j];
}
}
sw.Stop();
Console.WriteLine("MD Array Test2: " + sw.Elapsed.ToString());
MDA = null;
int[][] JA = new int[10000][];
for (int i = 0; i < 10000; i++)
{
JA[i] = new int[10000];
}
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
JA[i][j] = i + j;
}
}
sum = 0;
sw.Restart();
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
sum += JA[j][i];
}
}
sw.Stop();
Console.WriteLine("Jagged Array Test1: " + sw.Elapsed.ToString());
sw.Restart();
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 10000; j++)
{
sum += JA[i][j];
}
}
sw.Stop();
Console.WriteLine("Jagged Array Test2: " + sw.Elapsed.ToString());
MDA = null;
Console.ReadKey();

Using parallel in C#

I'm new to threading and parallelism. I have this method for a game in C# and need to use parallel iteration. How could I use this on the for loops in the below method?
public int[,] GetLegalMoves()
{
int[,] legalMoves = new int[8, 8];
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
if (IsMoveLegal(i, j)) legalMoves[i, j] = 1;
else legalMoves[i, j] = 0;
return legalMoves;
}
This could be parallelized by parallelizing your outer loop:
public int[,] GetLegalMoves()
{
int[,] legalMoves = new int[8, 8];
Parallel.For(0, 8, i =>
{
for (int j = 0; j < 8; j++)
if (IsMoveLegal(i, j)) legalMoves[i, j] = 1;
else legalMoves[i, j] = 0;
});
return legalMoves;
}
That being said, this will likely cause this to run slower, as an 8x8 matrix is such a small value that the overhead of scheduling the parallel work is likely higher than the gains made, unless IsMoveLegal is a fairly expensive operation.
This will also require that IsMoveLegal be safe to use from multiple threads.

Categories