Pass multi - dimensional array from managed code to unmanaged code - c#

I would like to do the following:
Create three dimesinal array in c# code like this:
var myArray = new short[x,y,z];
UnanagedFunction(myArray);
Pass it to unmanaged code (c++) like this:
void UnmanagedFunction(short*** myArray)
{
short first = myArray[0][0][0];
}
UPDATED
When I try the following code I have runtime error:
Attempted to read or write to protected memory.
Thank you!!!

IntPtr Array3DToIntPtr(short[, ,] Val)
{
IntPtr ret = Marshal.AllocHGlobal((Val.GetLength(0) + Val.GetLength(1) + Val.GetLength(2)) * sizeof(short));
int offset = 0;
for (int i = 0; i < Val.GetLength(0); i++)
{
for (int j = 0; j < Val.GetLength(1); j++)
{
for (int k = 0; k < Val.GetLength(2); k++)
{
Marshal.WriteInt16(ret,offset, Val[i, j, k]);
offset += sizeof(short);
}
}
}
return ret;
}
This has been tested and it works, the only limitation is that you have to call Marshal.FreeHGlobal on the array pointer when you are done with it or you will get a memory leak, I would also suggest that you change your c++ function so that it accepts the array dimensions or you will only be able to use 3d arrays of specific size

I'm writing it in pure C#, but if you take away the unsafe static from Func, the Func should work in C/C++. Be aware that I'm note sure sure it's ok ok to write this :-)
I'm using this Indexing into arrays of arbitrary rank in C#
static unsafe void Main(string[] args) {
var myArray = new short[5, 10, 20];
short z = 0;
for (int i = 0; i < myArray.GetLength(0); i++) {
for (int j = 0; j < myArray.GetLength(1); j++) {
for (int k = 0; k < myArray.GetLength(2); k++) {
myArray[i, j, k] = z;
z++;
}
}
}
// myArray[1, 2, 3] == 243
fixed (short* ptr = myArray) {
Func(ptr, myArray.GetLength(0), myArray.GetLength(1), myArray.GetLength(2));
}
}
// To convert to C/C++ take away the static unsafe
static unsafe void Func(short* myArray, int size1, int size2, int size3) {
int x = 1, y = 2, z = 3;
int el = myArray[x * size2 * size3 + y * size3 + z]; // el == 243
}

Related

How to fix this implementaion of the Merge Sort in c#

I've read the CLRS and tried to implement the recursive merge sort algorithm . cant see what the error is but everytime i run it gives me an "Index out of bounds error "
i've been trying for 5h now
static public void MergeSort(int[] input, int IndexStanga, int IndexDreapta)
{
if (IndexStanga < IndexDreapta)
{
int IndexMijloc = (IndexDreapta + IndexStanga) / 2;
MergeSort(input, IndexStanga, IndexMijloc);
MergeSort(input, IndexMijloc + 1, IndexDreapta);
Merge(input, IndexStanga, IndexDreapta, IndexMijloc);
}
}
static public void Merge(int[] input, int stanga, int dreapta, int mijloc)
{
int lungDR = 0;
int lunST = 0;
lungDR = dreapta - mijloc;
lunST = mijloc - stanga + 1;
int[] valDreapta = new int[lungDR + 1];
int[] valStanga = new int[lunST + 1];
valDreapta[valDreapta.Length - 1] = int.MaxValue;
valStanga[valStanga.Length - 1] = int.MaxValue;
int i = 0;
int j = 0;
for (i = stanga; i <= mijloc; i++) valStanga[i] = input[i];
for (i = 0; i < lungDR; i++) { valDreapta[i] = input[i + mijloc + 1]; }
i = 0;
j = 0;
for (int k = 0; k < input.Length; k++)
{
if (valStanga[i] <= valDreapta[j]) //error out of bounds
{
input[k] = valStanga[i];
i++;
}
else
{
input[k] = valDreapta[j];
j++;
}
}
}
Fixes noted in comments below. First fix for moving data from input to valStanga. Second fix for the range on merging back to input. The parameters for merge are in an unusual order, first, last, middle. Normally the order is first, middle, last.
Comments: The program will have issues if the array to be sorted contains elements equal to max integer. It would be more efficient to do a one time allocation of a working array, rather than allocate new sub-arrays on every call to merge. The copy operations can be avoided by changing the direction of merge with each level of recursion.
int i = 0;
int j = 0;
for (i = 0; i < lungDR; i++) { valDreapta[i] = input[i + mijloc + 1]; }
for (i = 0; i < lunST; i++) { valStanga[i] = input[i + stanga]; } // fix
i = 0;
j = 0;
for (int k = stanga; k <= dreapta; k++) // fix
{
if (valStanga[i] <= valDreapta[j])

C# 2D Array calling it another class through obj.method();

Write a Java class that has a static method named count that accepts a 2D-Array of integers and a target integer value as parameters and returns the number of occurrences of the target value in the array. For example, if a variable named list refers to an array containing values {{3,5,7,94}{5,6,3,50}} then the call of count(list, 3) should return 2 because there are 2 occurrences of the value 3 in the array.
Here is my coding and it's not giving me proper output
P.S :-I have been told to take count method as public not static
class java
{
public int count(int [,] list,int n)
{
int c = 0;
for (int i = 0; i <list.Length; i++)
{
for (int j = 0; j < list.Length; j++)
{
if (list[i, j] == n)
{
c++;
}
}
}
return c;
}
class Program
{
static void Main(string[] args)
{
java jv = new java();
int[,] arr = { { 3, 5, 7, 94 }, {5, 6, 3, 50 } };
int k=0;
jv.count(arr,k);
}
}
Iterating Multi-Dimensional arrays requires you to iterate each dimension with it's own Length, which means i and j should be 0-3 and 0-1 respectively.
as can be seen in the picture but for a different dimensioned array:
GetLength(0) would return 4.
GetLength(1) would return 3.
What you are doing is iterating them when i = (0 to Length) over j = (0 to Length) when Length = Height * Width = 8 in your case which means 8 over 8.
So your count() method should look like that:
public int count(int[,] list,int n)
{
int c = 0;
for (int i = 0; i < list.GetLength(0); i++)
{
for (int j = 0; j < list.GetLength(1); j++)
{
if (list[i, j] == n)
{
c++;
}
}
}
return c;
}
if you would like to iterate the array as an array of arrays instead of getting things complicated with "Which dimension am I iterating now?" you can use Jagged Arrays (Of course there are more things to consider about it), this will allow you to replace the whole method with this one short Linq:
public int count(int[][] list,int n)
{
return list.SelectMany(x => x).Count(x => x == n);
}
or:
public int count(int[][] list, int n)
{
return list.Sum(x => x.Count(y => y == n));
}
Note the i against j in inner for.
And do use i <list.GetLength(0) and j < list.GetLength(1) against list.Length
class java
{
public int count(int [,] list,int n)
{
int c = 0;
for (int i = 0; i < list.GetLength(0); i++)
{
for (int j = 0; j < list.GetLength(1); j++)
{
if (list[i, j] == n)
{
c++;
}
}
}
return c;
}
class Program
{
static void Main(string[] args)
{
java jv = new java();
int[,] arr = { {3,5,7,94 }, {5,6,3,50 } };
int k=5;
Console.WriteLine(jv.count(arr,k));
}
}
Since Array has implemented IEnumerable you can simply use foreach loop here (feel free to change static to instance method) :
public static int count(int[,] list, int n)
{
int c = 0;
foreach (var item in list) if (item == n) c++;
return c;
}
Usage:
static void Main()
{
var r = count(new int[,]{
{
5, 8, 7, 8
},
{
0, 8, 9, 3
}}, 8);
Console.WriteLine(r);
output : 3
P.S.
Generally if possible, it is best to use a for loop as it is faster than foreach but in these case i like that if you use foreach you don't have nested for loops nor GetLength(x) calls it's just one line of code and it has almost same performance...
Your error is in this line:
for (int j = 0; i < list.Length; j++)
It should be
for (int j = 0; j < list.Length; j++)

C# convert 1D array to 2D

I find myself converting 1D byte and single arrays to 2D by doing the following. I suspect it is probably as fast as other methods, but perhaps there is a cleaner simpler paradigm? (Linq?)
private static byte[,] byte2D(byte[] input, int height, int width)
{
byte[,] output = new byte[height, width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
output[i, j] = input[i * width + j];
}
}
return output;
}
private static Single[,] single2D(byte[] input, int height, int width)
{
Single[,] output = new Single[height, width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
output[i, j] = (Single)input[i * width + j];
}
}
return output;
}
This doesn't help with making the code inside the methods cleaner, but I noticed that you have 2 basically identical methods that differ only in their types. I suggest using generics.
This would let you define your method only once. Using the where keyword, you can even limit the kind of types you allow your method to work on.
private static T[,] Make2DArray<T>(T[] input, int height, int width)
{
T[,] output = new T[height, width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
output[i, j] = input[i * width + j];
}
}
return output;
}
You would call this method like this
int[] a; //or any other array.
var twoDArray = Make2DArray(a, height, width);
Buffer.BlockCopy(input, 0, output, 0, input.Length); is faster, but fastest is to not copy the array at all.
If you don't really need a separate 2D array, you can just access your 1D array like a 2D array trough a function, property, or custom type. For example:
class D2<T> {
T[] input;
int lenght0;
public d2(T[] input, int lenght0) {
this.input = input;
this.lenght0 = lenght0;
}
public T this[int index0, int index1] {
get { return input[index0 * this.lenght0 + index1]; }
set { input[index0 * this.lenght0 + index1] = value; }
}
}
...
byte[] input = { 1, 2, 3, 4 };
var output = new D2<byte>(input, 2);
output[1, 1] = 0; // now input is { 1, 2, 3, 0 };
Also, in .NET access to multidimensional arrays is a bit slower than access to jagged arrays
Generic function:
private static b[,] to2D<a, b>(a source, valueAt: Func<a, int, b>, int height, int width)
{
var result = new b[height, width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
result[i, j] = valueAt(source, i * width + j);
}
}
return result;
}
var bytes = to2D<byte[], byte>([], (bytes, at) => bytes[at], 10, 20);
I know I am late to the party, but if you want to access a 1d array, list, etc. like it were an n-dimensional array (without copying) you can use https://github.com/henon/SliceAndDice to do so without copying.
// create a 2D array of bytes from a byte[]
var a = new ArraySlice<byte>( new byte[100], new Shape(10,10));
// now access with 2d coordinates
a[7,9]=(byte)56;
Of course, everyone can do it for simple 2d, 3d, ... nd volumes easily. But this lib also allows to do slicing of n-dimensional arrays without copying.

How can I multiply two matrices in C#?

Like described in the title, is there some library in the Microsoft framework which allows to multiply two matrices or do I have to write my own method to do this? // I've got an answer to this by now
Second question:
I wrote this multi class with a MultiplyMatrix method but it doesn't work like I want to. Can anyone help and tell where I made a mistake?
class multi
{
public void MultiplyMatrix(double[,] _A, double[,] _B, int _n, int _m, int _r)
{
int n, m, r;
double si;
n = _n;
m = _m;
r = _r;
double[,] A = new double[n, m];
double[,] B = new double[m, r];
double[,] C = new double[n, r];
A = _A;
B = _B;
try
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < r; j++)
{
si = 0;
for (int k = 0; k < m; k++)
{
si += A[i, m + k] + B[k, r + j];
}
C[i, r + j] = si;
}
}
for (int i = 0; i < C.Length; i++)
{
for (int j = 0; j < C.Length; j++)
{
Console.Write(C[i, j]+" ");
if (j % 3 == 0)
Console.WriteLine();
}
}
}
catch (IndexOutOfRangeException) { } // I always get this exception
}
}
I forgot to tell: I want to make a webservice to multiply on it.
Thanks:)
Multiplication of 2 matrixes:
public double[,] MultiplyMatrix(double[,] A, double[,] B)
{
int rA = A.GetLength(0);
int cA = A.GetLength(1);
int rB = B.GetLength(0);
int cB = B.GetLength(1);
if (cA != rB)
{
Console.WriteLine("Matrixes can't be multiplied!!");
}
else
{
double temp = 0;
double[,] kHasil = new double[rA, cB];
for (int i = 0; i < rA; i++)
{
for (int j = 0; j < cB; j++)
{
temp = 0;
for (int k = 0; k < cA; k++)
{
temp += A[i, k] * B[k, j];
}
kHasil[i, j] = temp;
}
}
return kHasil;
}
}
Whilst there's no built in Maths framework to do this in .NET (could use XNA's Maths library), there is a Matrix in the System.Windows.Media namespace. The Matrix structure has a Multiply method which takes in another Matrix and outputs a Matrix.
Matrix matrix1 = new Matrix(5, 10, 15, 20, 25, 30);
Matrix matrix2 = new Matrix(2, 4, 6, 8, 10, 12);
// matrixResult is equal to (70,100,150,220,240,352)
Matrix matrixResult = Matrix.Multiply(matrix1, matrix2);
// matrixResult2 is also
// equal to (70,100,150,220,240,352)
Matrix matrixResult2 = matrix1 * matrix2;
This is mainly used for 2D transformation:
Represents a 3x3 affine transformation
matrix used for transformations in 2-D
space.
but if it suits your needs, then there's no need for any third party libraries.
Although you can multiply matrices by an iterative approach (for loops), performing the calculations with linear algebra will clean up your code and will give you performance gains that are several times faster!
There is a free library available in nuget - MathNet.Numerics. It makes it extremely easy to multiply matrices:
Matrix<double> a = DenseMatrix.OfArray(new double[,] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } });
Matrix<double> b = DenseMatrix.OfArray(new double[,] { { 1 }, { 2 }, { 3 } });
Matrix<double> result = a * b;
It has no dependencies and can be used in .net core 2.0, making it an excellent choice to avoid iterative matrix multiplication techniques and take advantage of linear algebra.
There is nothing built into .NET. You will have to write the multiplication yourself or use some third party library. I've blogged about one way to achieve this comparing two different implementations : a standard naive algorithm and one using unsafe code.
CSML - C# Matrix Library - is a compact and lightweight package for numerical linear algebra. Many matrix operations known from Matlab, Scilab and Co. are implemented.
See this!
There are no such built in libraries. Unless you are using XNA - it has a Matrix class, though it is limited and designed for 3D games.
There are many matrix libraries for .NET though.
namespace matrix_multiplication
{
class Program
{
static void Main(string[] args)
{
int i, j;
int[,] a = new int[2, 2];
Console.WriteLine("Enter no for 2*2 matrix");
for (i = 0; i < 2; i++)
{
for (j = 0; j < 2; j++)
{
a[i, j] = int.Parse(Console.ReadLine());
}
}
Console.WriteLine("First matrix is:");
for (i = 0; i < 2; i++)
{
for (j = 0; j < 2; j++)
{
Console.Write(a[i,j]+"\t");
}
Console.WriteLine();
}
int[,] b = new int[2, 2];
Console.WriteLine("Enter no for 2*2 matrix");
for (i = 0; i < 2; i++)
{
for (j = 0; j < 2; j++)
{
b[i, j] = int.Parse(Console.ReadLine());
}
}
Console.WriteLine("second matrix is:");
for (i = 0; i < 2; i++)
{
for (j = 0; j < 2; j++)
{
Console.Write(b[i, j] + "\t");
}
Console.WriteLine();
}
Console.WriteLine("Matrix multiplication is:");
int[,] c = new int[2, 2];
for (i = 0; i < 2; i++)
{
for (j = 0; j < 2; j++)
{
c[i,j]=0;
for (int k = 0; k < 2; k++)
{
c[i, j] += a[i, k] * b[k, j];
}
}
}
for (i = 0; i < 2; i++)
{
for (j = 0; j < 2; j++)
{
Console.Write(c[i, j]+"\t");
}
Console.WriteLine();
}
Console.ReadKey();
}
}
}
output
Enter no for 2*2 matrix
8
7
6
0
First matrix is:
8 7
6 0
Enter no for 2*2 matrix
4
3
2
1
second matrix is:
4 3
2 1
Matrix multiplication is:
46 31
24 18
Below is the method to multiply int[3,4] matrix with int[4,3] matrix, it has time complexity of O(n cube) or Cubic time
class Program
{
static void Main(string[] args)
{
MultiplyMatrix();
}
static void MultiplyMatrix()
{
int[,] metrix1 = new int[3,4] { { 1, 2,3,2 }, { 3, 4,5,6 }, { 5, 6,8,4 } };
int[,] metrix2 = new int[4, 3] { { 2, 5, 3 }, { 4, 5, 1 }, { 8, 7, 9 }, { 3, 7, 2 } };
int[,] metrixMultplied = new int[3, 3];
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
for(int i=0;i<4;i++)
{
metrixMultplied[row, col] = metrixMultplied[row, col] + metrix1[row, i] * metrix2[i, col];
}
Console.Write(metrixMultplied[row, col] + ", ");
}
Console.WriteLine();
}
Console.ReadLine();
}
}
Here is my code : 4*4 matrix
for (int i = 0; i < 4; i++)
{
int column = 0;
while (column < 4)
{
int count = 0;
for (int j = 0; j < 4; j++)
{
matrixResult[i, column] += Convert.ToInt32(matrixR[i, j] * matrixT[count, column]);
count = count + 1;
}
column = column + 1;
}
}
If you have a helper to generate, iterate and populate an int[,] matrix like this one:
public class VisitMatrix{
public static int[,] execute(int rows, int columns, Func<int, int, int> fn)
{
int[,] result = new int[rows, columns];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
result[i, j] = fn(i, j);
}
}
return result;
}
}
Now matrix multiplication is as trivial as doing (supposing m1.GetLength(1) == m2.GetLength(0)):
public class MultiplyMatrices{
public static int[,] execute(int[,] m1, int[,] m2, int modulus = 10)
{
return VisitMatrix.execute(m1.GetLength(0), m2.GetLength(1), (i, j) =>
Enumerable.Range(0, m1.GetLength(1)-1)
.Select(k => m1[i, k] * m2[k, j])
.Aggregate(0, (a, b) => a + b, e => e % modulus)
}
}

Best way to convert int[][] to int**?

This is kind of a curiosity question. I do have an existing solution, but I wonder if people know of a better approach.
My callers want to call me with int[][]. I have a routine that needs to process an int**. What's the best way to do this conversion? In other words:
public static void Func1(int[][] data) {
Func2(data); //how to do this?
}
private unsafe static void Func2(int** data) {
//process data
}
Following is the best approach I could come up with. It works fine, but I can't say I'm 100% happy with the recursive approach (and the O(data.Length) stack space it requires)
public static void Main() {
var test=new[] {
new [] {10},
new [] {20,30},
new [] {40,50,60},
new [] {70,80,90,100},
};
MySolution_Func1(test);
}
public unsafe static void MySolution_Func1(int[][] data) {
var items=new int*[data.Length];
Recurse(0, data, items);
}
public unsafe static void Recurse(int index, int[][] data, int*[] build) {
if(index==data.Length) {
fixed(int** finalp=build) {
Func2(finalp);
}
} else {
fixed(int* nextp=data[index]) {
build[index]=nextp;
Recurse(index+1, data, build);
}
}
}
private unsafe static void Func2(int** data) {
for(var j=0; j<4; ++j) {
for(var i=0; i<j+1; ++i) {
Debug.WriteLine("{0},{1}: {2}", j, i, data[j][i]);
}
}
}
There's no need to copy the whole array. You can create an array of pointers (i.e. IntPtr[]), and then cast that to int**. It's not pretty, and I wouldn't suggest doing it. But it can be done. The code below shows how.
int[][] myArray = new int[10][];
for (int i = 0; i < 10; ++i)
{
int[] x = new int[10];
for (int j = 0; j < 10; ++j)
{
x[j] = 10 * i + j;
}
myArray[i] = x;
}
// Output the array
Console.WriteLine("int[][]");
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < 10; ++j)
{
Console.Write("{0}, ", myArray[i][j]);
}
Console.WriteLine();
}
// Convert to int*[]
unsafe
{
GCHandle[] handles = new GCHandle[10];
IntPtr[] ArrayOfPointer = new IntPtr[10];
for (int i = 0; i < 10; ++i)
{
handles[i] = GCHandle.Alloc(myArray[i], GCHandleType.Pinned);
ArrayOfPointer[i] = handles[i].AddrOfPinnedObject();
}
// Okay, let's output that
Console.WriteLine("int*[]");
for (int i = 0; i < 10; ++i)
{
int* p = (int*)ArrayOfPointer[i];
for (int j = 0; j < 10; ++j)
{
Console.Write("{0}, ", *p);
++p;
}
Console.WriteLine();
}
// now convert to int**
GCHandle bigHandle = GCHandle.Alloc(ArrayOfPointer, GCHandleType.Pinned);
int** ppInt = (int**)bigHandle.AddrOfPinnedObject();
// and output it
Console.WriteLine("int**");
int** pa = ppInt;
for (int i = 0; i < 10; ++i)
{
int* p = *pa;
for (int j = 0; j < 10; ++j)
{
Console.Write("{0}, ", *p);
++p;
}
Console.WriteLine();
++pa;
}
// Need to free the handles
bigHandle.Free();
for (int i = 0; i < 10; ++i)
{
handles[i].Free();
}
}
public unsafe void ConvertToNative(int[][] jarray, out int** ptr)
{
ptr= (int**)Marshal.AllocHGlobal(jarray.Length*sizeof(int));
for (int i = 0; i < jarray.Length; i++)
{
*(ptr+i) = (int*)Marshal.AllocHGlobal(jarray[i].Length*sizeof(int));
for (int j = 0; j < jarray[i].Length; j++)
{
(*(i + ptr))[j] = jarray[i][j];
}
}
}
This works but uses unmanaged memory, and there is no recursion, is that valid ?
You can do it with O(1) stack space, if you are willing to copy all the data into another buffer:
public unsafe static void AlternateSolution_Func1(int[][] data) {
var buffer=new int[data.Sum(a => a.Length)];
fixed(int* pBuffer=buffer) {
var items=new int*[data.Length];
int count=0;
for(int i=0; i<data.Length; ++i) {
items[i]=pBuffer+count;
var array=data[i];
for(int j=0; j<array.Length; ++j) {
pBuffer[count++]=array[j];
}
}
fixed(int** pItems=items) {
Func2(pItems);
}
}
}

Categories

Resources