anefeletos
anefeletos

Reputation: 702

How to cast an array of structures (of double values) to an array of double values

I am trying to create a wrapper to treat System.Numeric.Complex array as array of double, i.e. to treat {{1,2},{3,4},{5,6},{7,8} as {1,2,3,4,5,6,7,8}. I use these arrays for FFT so this way will be more efficient because avoids copying and iterating huge arrays. But i stuck on a strange chimeric monster: A Double array object of kind double[] {System.Numerics.Complex[4], instead of double[8]!!. What's that?

I am not an interop expert so excuse any essential blunder; I read some related stuff here and here and I wonder if the case is that these arrays are overlapped. Τhis code almost works except for that it returns half of the values:

 //using System.Runtime.InteropServices;
 //using System.Numeric;

    [StructLayout(LayoutKind.Explicit)]
    public struct ComplexArray2serialWrapper
    {
        [FieldOffset(0)] private Complex[] ComplexArray;
        [FieldOffset(0)] private double[] DoubleArray;

        public ComplexArray2serialWrapper(Complex[] NewcomplexArray) : this() { ComplexArray = NewcomplexArray; }
        public ComplexArray2serialWrapper(double[] NewSerialComplexArray) : this() { DoubleArray = NewSerialComplexArray; }
        public static implicit operator double[] (ComplexArray2serialWrapper source) { return source.DoubleArray; }
    }


    public static void TestWrapper()
    {
        Complex[] cc = { new Complex(1, 2), new Complex(3, 4), new Complex(5, 6), new Complex(7, 8) };  
        double[] DoubleComplexChimeraMonster = new ComplexArray2serialWrapper(cc);
        var parenttype = DoubleComplexChimeraMonster.GetType(); // result = System.Numerics.Complex[]
        //!!! but in watch window type shown as=  double[] {System.Numerics.Complex[4]}

        var ChildrenType = DoubleComplexChimeraMonster[0].GetType(); //System.Double
        //In Watch window, children types shown chimeric:        
        //{ (1, 2)} Double {System.Numerics.Complex} 
        //{ (3, 4)} Double {System.Numerics.Complex} 
        //{ (5, 6)} Double {System.Numerics.Complex} 
        //{ (7, 8)} Double {System.Numerics.Complex}

        double i1 = DoubleComplexChimeraMonster[0]; //=1 (as expected)
        double i2 = DoubleComplexChimeraMonster[1]; //=2 (as expected)
        double i3 = DoubleComplexChimeraMonster[2]; //=3 (as expected)
        double i4 = DoubleComplexChimeraMonster[3]; //=4 (as expected)
        var l = DoubleComplexChimeraMonster.Length; //=4 (8 expected)


        //So trying to get i5-i8 will throw an exception e.g.:
        //DoubleComplexChimeraMonster(4)  --> exception (5 expected)

    }

Upvotes: 0

Views: 483

Answers (1)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112372

You expect the arrays to store only the doubles. But they also store the array length and a reference to a type descriptor. Therefore, your approach of overlapping two .NET types does not work. C# is not C.

DoubleComplexChimeraMonster is statically typed as double[], however GetType() retrieves the runtime type, which happens to be Complex[].

Overlapping values at the same memory location works for primitive value types. But System.Array is a class.

As Marc Gravell says in this answer of the link you provided, unsafe pointers might be the way to go.

Upvotes: 1

Related Questions