Is it possible to specialize generics - c#

I'm having a generic Converter class
public class Converter
{
public static TargetType[] Convert<SourceType, TargetType>(SourceType[] data)
where SourceType : struct
where TargetType : struct
{
int N = data.Length;
TargetType[] result = new TargetType[N];
for (int i = 0; i < N; i++)
{
// We does this not work, what can I do else
result[i] = (TargetType)data[i];
}
return result;
}
}
Question 1: Why is is not possible to do the cast? What can I do else? Convert.ChangeType is to slow.
Because of slow performance in general I decided to do it in unsafe code. Unfortunately it's not possible to create pointers to generics - as it is widely known. For that reason I created a converter that decides the type at runtime and performs the casts with a lot of if's.
No one question came up. Can I create a generic Convert routine and specialize it in a way, that in some cases I have defined datatypes. I currently don't know how, but maybe I you read the example you get a clue:
public static double[] Convert<double, int>(int[] data)
{
int N = data.Length;
double[] result = new double[N];
unsafe
{
fixed (int* data_pinned = data)
fixed (double* out_pinned = result)
{
int* A = data_pinned;
double* B = out_pinned;
for (int i = 0; i < N; i++, A++, B++)
{
*B = ((double)*A);
}
}
}
return result;
}
Below you can find a "small" demo project which shows the performance values of different casts:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace ConsoleApplication1
{
public static class CastTest
{
public static unsafe double[] Cast1(int[] input)
{
int N = input.Length;
double[] output = new double[N];
for (int i = 0; i < N; i++) output[i] = (double)(input[i]);
return output;
}
public static unsafe double[] Cast2(int[] input)
{
int N = input.Length;
double[] output = new double[N];
fixed (double* output_pinned = output)
{
double* outp = output_pinned;
fixed (int* input_pinned = input)
{
int* inp = input_pinned;
for (int i = 0; i < N; i++, inp++, outp++) *outp = (double)(*inp);
}
return output;
}
}
public static unsafe double[] Cast3(int[] input)
{
int N = input.Length;
double[] output = new double[N];
fixed (double* output_pinned = output)
{
double* outp = output_pinned;
fixed (int* input_pinned = input)
{
int* inp = input_pinned;
for (int i = 0; i < N; i++) outp[i] = (double)(inp[i]);
}
return output;
}
}
public static unsafe double[] Cast4(int[] input)
{
int N = input.Length;
double[] output = new double[N];
fixed (double* output_pinned = output)
{
fixed (int* input_pinned = input)
{
for (int i = 0; i < N; i++) output_pinned[i] = (double)(input_pinned[i]);
}
}
return output;
}
public static unsafe double[] Cast5(int[] input)
{
double[] output = new double[input.Length];
for (int i = 0; i < input.Length; i++) output[i] = (input[i]);
return output;
}
public static unsafe double[] Cast6(int[] input)
{
Converter<int, double> converter = (A) =>
{
return A;
};
return Array.ConvertAll<int, double>(input, converter);
}
public static void StartTest()
{
int[] A = new int[100000];
int N = 10000;
var w1 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A1 = Cast1(A); }
w1.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 1, w1.ElapsedMilliseconds));
var w2 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A2 = Cast2(A); }
w2.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 2, w2.ElapsedMilliseconds ));
var w3 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A3 = Cast3(A); }
w3.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 3, w3.ElapsedMilliseconds));
var w4 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A4 = Cast4(A); }
w4.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 4, w4.ElapsedMilliseconds));
var w5 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A5 = Cast5(A); }
w5.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 5, w5.ElapsedMilliseconds));
var w6 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A6 = Cast6(A); }
w6.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 6, w6.ElapsedMilliseconds));
}
}
}
Any help is greatly appreciated to improve the performance.
The sizes for array size and repetitions are real values for me. In fact for testing purpose these values are also a little lower than normally used.
Is there a possibility to do this?
Thanks
Martin

It's not possible to do the cast because there's no guarantee that there is a conversion between the two types involved. What if SourceType is Guid and TargetType is double? The compiler basically can't emit a conversion.
The simplest approach is probably to provide a delegate:
public static TTarget[] Convert<TSource, TTarget>(TSource[] data,
Func<TSource, TTarget> conversion)
{
TargetType[] result = new TargetType[data.Length];
for (int i = 0; i < data.Length; i++)
{
result[i] = conversion(data[i]);
}
return result;
}
Of course this is basically the same as calling Array.ConvertAll... does that not do what you want?
Yes, there'll be a small performance overhead from calling the conversion frequently - but have you proved to yourself that that performance overhead is a problem? I would at least try using Array.ConvertAll as a first attempt.

Related

How can I find index of the array in C#?

I am trying to find index of an array.Probably doing this is easy but I couldn't do that.I tried to add a function(findIndex),looking at a website but I am getting an error.How can I find the index?
namespace exmple.Filters
{
class dnm2
{
public static byte[] Shape(byte[] data)
{
byte[] shape = new byte[data.Length];
byte count = 0;
for (int i = 0; i < data.Length; i++)
{
if (data[i] == 0)
{
shape[i] = (data[i]);
int index = shape.findIndex(count);
int[] a = {1, 2, 3};
int index = a.Indexof((int)3);
count += 1;
}
}
return shape;
}
public static int findIndex<T>(this T[] array, T item)
{
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
for (int i = 0; i < array.Length; i++)
{
if (comparer.Equals(array[i], item)) {
return i;
}
}
return -1;
}
}
Array.IndexOf() gives you the index of an object in an array. Just make sure you use the same data types, i.e. byte here.
This is the full code, tested in .NET 4.5.2
using System;
namespace ConsoleApp2
{
class Program
{
static void Main()
{
byte[] data = { 5, 4, 3, 2, 1 };
Console.WriteLine(Array.IndexOf(data, (byte)2));
Console.ReadLine();
}
}
}
Alternate way is to use Array.FindIndex(array, predicate)
var zeroBasedIndex = Array.FindIndex(data, x => x == (byte)2);
Not sure what you are trying to do but I have fixed your code.
namespace Exmple.Filters
{
public static class DNM
{
public static byte[] Shape(byte[] data)
{
byte[] shape = new byte[data.Length];
byte count = 0;
for (int i = 0; i < data.Length; i++)
{
if (data[i] == 0)
{
shape[i] = (data[i]);
int index = shape.FindIndex1(count);
int[] a = { 1, 2, 3 };
int index1 = Array.IndexOf(a, (int)3);
count += 1;
}
}
return shape;
}
public static int FindIndex1(this byte[] array, byte item)
{
EqualityComparer<byte> comparer = EqualityComparer<byte>.Default;
for (int i = 0; i < array.Length; i++)
{
if (comparer.Equals(array[i], item))
{
return i;
}
}
return -1;
}
}
}
there were few issues in your code
Naming rule violations
byte[] already has an FindIndex so compiler was getting confused which one to use (I just removed the generic things and changed the name)
array object doesn't have a IndexOf Method, Array class has a method.

C# Multithreading - Performance Issue

I have console application with numerical calculation, which I am trying to parallel using the ThreadPool.
I got object state as class (simple-data-passing):
public class DataContainer
{
public double[,] Exa;
public double[] EQ;
public int iStart;
public int iEnd;
}
Definition for WaitCallback
private void Calculate(object state)
{
DataContainer data = state as DataContainer;
for (int m = data.iStart; m < data.iEnd; m++)
{
double temp= 0.0;
for (int i = 0; i < 500000; i++)
{
for (int j = i + 1; j < 500000; j++)
{
//Some-Long-Calculation based on data.Exa-around 200 math operation with results of double EQC
if (EQC> temp) { temp= EQC; } //line performance issue-temp is declared in first for-loop block;
}
}
}
}
Execution:
WaitCallback waitCallback = Calculate;
const int numberOfThreads = 100;
ThreadPool.SetMaxThreads(30, 100);
for (int i = 0; i < numberOfThreads; i++)
{
DataContainer tempContainer = new DataContainer();
tempContainer.Exa = Exa;
tempContainer.EQ = EQ;
tempContainer.iStart = CalculateStart(i);
tempContainer.iEnd = CalculateEnd(i);
ThreadPool.QueueUserWorkItem(waitCallback, tempContainer);
}
int numberOfTotalThreads = 0;
int numberOfMaxThreads = 0;
int numberOfWorkingThreads = 0;
int temp = 0;
//do-while - waiting to finish all calculation
do
{
ThreadPool.GetAvailableThreads(out numberOfTotalThreads, out temp);
ThreadPool.GetMaxThreads(out numberOfMaxThreads, out temp);
numberOfWorkingThreads = numberOfMaxThreads - numberOfTotalThreads;
Console.WriteLine("Number of working threads {0}", numberOfWorkingThreads);
Thread.Sleep(1000);
} while (numberOfWorkingThreads > 0);
So one marked line:
if (EQC> temp) { temp= EQC; }
Time exeuction of program slow down from 40s to 600s.
Could you advice how these line should be written to avoid that problem?

Converting Codility solution to C# (Grocery-store, Hydrogenium 2013)

In order to learn and understand how Dijkstra's algorithm is used to solve the "Grocery Store" ([Hydrogenium 2013]: https://codility.com/programmers/challenges/hydrogenium2013) problem on codility, I'm trying to rewrite the #2, O(n^2) solution(https://codility.com/media/train/solution-grocery-store.pdf) in C#.
1) What language are those solutions written in?
2) What would be the C# equivalent to this bit of code?
G = [[]] *N
for i in xrange(M):
G[A[i]] = G[A[i]] + [(B[i], C[i])]
G[B[i]] = G[B[i]] + [(A[i], C[i])]
This is what I have so far
int[] G = new int[N];
for (int i = 0; i < M; i++)
{
G[A[i]] = G[A[i]];
G[B[i]] = G[B[i]];
}
Thanks in advance,
Gregory
Downloaded IDLE (a python IDE...kind of) and figured it out. It appears to be adding pairs to each array element. Here's the code I came up with if anyone else happens to stumble across the same problem.
private struct nodePair
{
public int node;
public int time;
public nodePair(int node, int time)
{
this.node = node;
this.time = time;
}
}
public int solution(int[] A, int[] B, int[] C, int[] D)
{
int M = A.Length;
int N = D.Length;
//build the graph
List<nodePair>[] G = new List<nodePair>[N];
for (int i = 0; i < N; i++)
{
G[i] = new List<nodePair>();
}
for (int i = 0; i < M; i++)
{
G[A[i]].Add(new nodePair(B[i], C[i]));
G[B[i]].Add(new nodePair(A[i], C[i]));
}
//initialize the distance table
int[] dist = new int[N];
for (int i = 0; i < N; i++)
{
dist[i] = int.MaxValue;
}
bool[] visited = new bool[N];
for (int i = 0; i < N; i++)
{
visited[i] = false;
}
//look for the minimum value
int ii = 0; ;
dist[0] = 0;
for (int k = 0; k < N; k++)
{
int s = int.MaxValue;
//find the minimum
for (int j = 0; j < N; j++)
{
if ((dist[j] < s) && (visited[j] == false))
{
s = dist[j];
ii = j;
}
}
visited[ii] = true;
if (s < D[ii])
{
return s;
}
List<nodePair> thisNodeLIst = G[ii];
foreach (nodePair oneNode in thisNodeLIst)
{
dist[oneNode.node] = Math.Min(dist[oneNode.node], s + oneNode.time);
}
}//for
return -1;
}
}

Serialization and deserialization of an int matrix c#

I'm using a c# WCF service and I need to return a int[,] to the client in one of my method. The problem is multidimensional arrays are not supported by WCF so I think my only option is returning a byte array in this way:
public byte[] DistanceMatrix()
{
int[,] matrix;
//DOING THINGS HERE
IFormatter formatter = new BinaryFormatter();
var ms = new MemoryStream();
formatter.Serialize(ms, matrix);
return ms.ToArray();
}
But I don't know how to deserialize the byte[] back to an int[,].
This excellent blog post by Josh Reuben can help you:
Extension methods that will allow you to convert prior to serialization and convert back after deserialization:
public static T[,] ToMultiD<T>(this T[][] jArray)
{
int i = jArray.Count();
int j = jArray.Select(x => x.Count()).Aggregate(0, (current, c) => (current > c) ? current : c);
var mArray = new T[i, j];
for (int ii = 0; ii < i; ii++)
{
for (int jj = 0; jj < j; jj++)
{
mArray[ii, jj] = jArray[ii][jj];
}
}
return mArray;
}
public static T[][] ToJagged<T>(this T[,] mArray)
{
var cols = mArray.GetLength(0);
var rows = mArray.GetLength(1);
var jArray = new T[cols][];
for (int i = 0; i < cols; i++)
{
jArray[i] = new T[rows];
for (int j = 0; j < rows; j++)
{
jArray[i][j] = mArray[i, j];
}
}
return jArray;
}

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