I'm still trying to find a quick way to convert a general array of type TOutput into another array of type TInput. All my arrays always have a numeric data type, but since C # does not have a Numeric type restriction, as is often requested, I currently have to live with this restriction. Proposed methods, such as casting for an object before, seem to slow down my cast significantly. I currently have a big if / else construct that checks the type and applies a specific type using pointer arithmetic, but this is a way to handle a great future. Parallel.For seems like a good way to get rid of pointers and speed things up, but still the general limitations of C # seem to be a problem, but still Tout in the code below is a problem. Here is my code:
public static OutputType[] Cast<InputType, OutputType>(InputType[] inputArray_in) { var aRange = Partitioner.Create(0, inputArray_in.Length); OutputType[] aResult = new OutputType[inputArray_in.Length]; Parallel.ForEach(aRange, (r) => { for (int i = r.Item1; i < r.Item2; i++) { aResult[i] = (OutputType)(inputArray_in[i]); } }); return aResult; }
Example:
float[] A = { 0.1f, 0.2f, 0.6f }; int []B = Cast<float, int>(A);
In all cases, my array types are numerical values ββ(float, short, double, ...) and most of the time arrays are about 512x512 images, but there are about 1000 slices on the stack in the volume. Do you see any chance of having an easy way to accomplish this?
Test code
public static class CastTest { delegate double[] CastMethod(int[] input); 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) { return Array.ConvertAll<int, double>(input, x => (double)x); } public static double[] Cast6(int[] input) { var aRange = Partitioner.Create(0, input.Length); int N = input.Length; double[] output = new double[N]; Parallel.ForEach(aRange, (r) => { for (int i = r.Item1; i < r.Item2; i++) output[i] = (double)(input[i]); }); return output; } public unsafe static double[] Cast7(int[] input) { var aRange = Partitioner.Create(0, input.Length); int N = input.Length; double[] output = new double[N]; Parallel.ForEach(aRange, (r) => { fixed (double* output_pinned = output) { double* outp = output_pinned + r.Item1; fixed (int* input_pinned = input) { int* inp = input_pinned + r.Item1; for (int i = r.Item1; i < r.Item2; i++, outp++, inp++) *outp = (double)(*inp); } } }); return output; } public unsafe static double[] Cast8(int[] input) { var result = (from m in input.AsParallel() select (double)m).ToArray(); return result; } public static double[] Cast9(int[] input) { return (from m in input select (double)m).ToArray(); } public static double[] Cast10(int[] input) { return (from m in input.AsParallel() select (double)m).ToArray(); } public static double[] Cast11(int[] input) { return new List<double>(input.Select(p => (double)p)).ToArray(); } static int[] A = new int[100000]; const int runs = 10000; public static void StartTest() { TestMethod("1", Cast1); TestMethod("2", Cast2); TestMethod("3", Cast3); TestMethod("4", Cast4); TestMethod("5", Cast5); TestMethod("6", Cast6); TestMethod("7", Cast7); TestMethod("8", Cast8); TestMethod("9", Cast9); TestMethod("10", Cast10); TestMethod("11", Cast11); } static void TestMethod(string Name, CastMethod method) { var timer = Stopwatch.StartNew(); for (int i = 0; i < runs; i++) { double[] res = method(A); } timer.Stop(); Console.WriteLine(String.Format("{0}: {1}ms", Name, timer.ElapsedMilliseconds)); } }
Thanks. Martin