/// /// This file is part of ILNumerics Community Edition. /// /// ILNumerics Community Edition - high performance computing for applications. /// Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net /// /// ILNumerics Community Edition is free software: you can redistribute it and/or modify /// it under the terms of the GNU General Public License version 3 as published by /// the Free Software Foundation. /// /// ILNumerics Community Edition is distributed in the hope that it will be useful, /// but WITHOUT ANY WARRANTY; without even the implied warranty of /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the /// GNU General Public License for more details. /// /// You should have received a copy of the GNU General Public License /// along with ILNumerics Community Edition. See the file License.txt in the root /// of your distribution package. If not, see . /// /// In addition this software uses the following components and/or licenses: /// /// ================================================================================= /// The Open Toolkit Library License /// /// Copyright (c) 2006 - 2009 the Open Toolkit library. /// /// Permission is hereby granted, free of charge, to any person obtaining a copy /// of this software and associated documentation files (the "Software"), to deal /// in the Software without restriction, including without limitation the rights to /// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of /// the Software, and to permit persons to whom the Software is furnished to do /// so, subject to the following conditions: /// /// The above copyright notice and this permission notice shall be included in all /// copies or substantial portions of the Software. /// /// ================================================================================= /// using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Numerics; using ILNumerics.Storage; namespace ILNumerics { /// /// Extension methods for ILNumerics types /// public static class ILExtensionMethods { /// /// Convert this complex ILNumerics array to a system array of type System.Numerics.Complex[] /// /// this ILNumerics array /// [option] if given, this system array will be used as storage for the conversion. Defaul: null (a new System.Array is returned) /// System.Array with the elements of A /// if the storage given does not have sufficient length for all elements of the ILNumerics array /// The elements of the ILNumerics array will be copied to the System.Array and converted to the System.Numerics.Complex type. /// The System.Array returned will contain all elements of the ILNumerics arrays after conversion - in column major order. /// /// This example demonstrates a common scenario for interchanging System.Numerics.Complex[] with ILNumerics complex arrays. It takes the converion between System.Numerics.Complex and ILNumerics.complex /// into account, as well as the memory management of all storage involved. /// /// ILArray<complex> A = sqrtc(B); /// // interfacing an external library as System.Numerics.Complex[] /// // We dont provide a System.Array as target for the conversion, /// // so it will be fetched from the ILNumerics memory management. /// System.Numerics.Complex[] A_MSComplex = A.ToMSComplex(); /// // .. do some work here with A_MSComplex /// // ... /// // The results get converted back to ILNumerics array /// ILArray<complex> Result = A_MSComplex.ToILArray(A.S, true); /// /// For the conversion of the System.Numerics.Complex[] array back to an ILNumerics array, we use the same size (A.S) as before. Here, any size /// would work, as long as it fits into the number of elements of the source System.Array. /// Note that the calls to A.ToMSComplex() and A_MSComplex.ToILArray(A.S, true) will fetch and return all System.Arrays involved into/from the /// ILINumerics memory pool. So if called frequently, no pressure on the GC is produced, what qualifies this scheme for high performance scenarios. /// /// /// public unsafe static Complex[] ToMSComplex(this ILArray A, Complex[] Storage = null) { return ToMSComplexHelper(A.Storage, Storage); } /// /// Convert this complex ILNumerics array to a system array of type System.Numerics.Complex[] /// /// this ILNumerics array /// [option] if given, this system array will be used as storage for the conversion. Defaul: null (a new System.Array is returned) /// System.Array with the elements of A /// if the storage given does not have sufficient length for all elements of the ILNumerics array /// The elements of the ILNumerics array will be copied to the System.Array and converted to the System.Numerics.Complex type. /// The System.Array returned will contain all elements of the ILNumerics arrays after conversion - in column major order. /// /// This example demonstrates a common scenario for interchanging System.Numerics.Complex[] with ILNumerics complex arrays. It takes the converion between System.Numerics.Complex and ILNumerics.complex /// into account, as well as the memory management of all storage involved. /// /// ILArray<complex> A = sqrtc(B); /// // interfacing an external library as System.Numerics.Complex[] /// // We dont provide a System.Array as target for the conversion, /// // so it will be fetched from the ILNumerics memory management. /// System.Numerics.Complex[] A_MSComplex = A.ToMSComplex(); /// // .. do some work here with A_MSComplex /// // ... /// // The results get converted back to ILNumerics array /// ILArray<complex> Result = A_MSComplex.ToILArray(A.S, true); /// /// For the conversion of the System.Numerics.Complex[] array back to an ILNumerics array, we use the same size (A.S) as before. Here, any size /// would work, as long as it fits into the number of elements of the source System.Array. /// Note that the calls to A.ToMSComplex() and A_MSComplex.ToILArray(A.S, true) will fetch and return all System.Arrays involved into/from the /// ILINumerics memory pool. So if called frequently, no pressure on the GC is produced, what qualifies this scheme for high performance scenarios. /// /// /// public unsafe static Complex[] ToMSComplex(this ILInArray A, Complex[] Storage = null) { return ToMSComplexHelper(A.Storage, Storage); } /// /// Convert this complex ILNumerics array to a system array of type System.Numerics.Complex[] /// /// this ILNumerics array /// [option] if given, this system array will be used as storage for the conversion. Defaul: null (a new System.Array is returned) /// System.Array with the elements of A /// if the storage given does not have sufficient length for all elements of the ILNumerics array /// The elements of the ILNumerics array will be copied to the System.Array and converted to the System.Numerics.Complex type. /// The System.Array returned will contain all elements of the ILNumerics arrays after conversion - in column major order. /// /// This example demonstrates a common scenario for interchanging System.Numerics.Complex[] with ILNumerics complex arrays. It takes the converion between System.Numerics.Complex and ILNumerics.complex /// into account, as well as the memory management of all storage involved. /// /// ILArray<complex> A = sqrtc(B); /// // interfacing an external library as System.Numerics.Complex[] /// // We dont provide a System.Array as target for the conversion, /// // so it will be fetched from the ILNumerics memory management. /// System.Numerics.Complex[] A_MSComplex = A.ToMSComplex(); /// // .. do some work here with A_MSComplex /// // ... /// // The results get converted back to ILNumerics array /// ILArray<complex> Result = A_MSComplex.ToILArray(A.S, true); /// /// For the conversion of the System.Numerics.Complex[] array back to an ILNumerics array, we use the same size (A.S) as before. Here, any size /// would work, as long as it fits into the number of elements of the source System.Array. /// Note that the calls to A.ToMSComplex() and A_MSComplex.ToILArray(A.S, true) will fetch and return all System.Arrays involved into/from the /// ILINumerics memory pool. So if called frequently, no pressure on the GC is produced, what qualifies this scheme for high performance scenarios. /// /// /// public unsafe static Complex[] ToMSComplex(this ILOutArray A, Complex[] Storage = null) { return ToMSComplexHelper(A.Storage, Storage); } /// /// Convert this complex ILNumerics array to a system array of type System.Numerics.Complex[] /// /// this ILNumerics array /// [option] if given, this system array will be used as storage for the conversion. Defaul: null (a new System.Array is returned) /// System.Array with the elements of A /// if the storage given does not have sufficient length for all elements of the ILNumerics array /// The elements of the ILNumerics array will be copied to the System.Array and converted to the System.Numerics.Complex type. /// The System.Array returned will contain all elements of the ILNumerics arrays after conversion - in column major order. /// /// This example demonstrates a common scenario for interchanging System.Numerics.Complex[] with ILNumerics complex arrays. It takes the converion between System.Numerics.Complex and ILNumerics.complex /// into account, as well as the memory management of all storage involved. /// /// ILArray<complex> A = sqrtc(B); /// // interfacing an external library as System.Numerics.Complex[] /// // We dont provide a System.Array as target for the conversion, /// // so it will be fetched from the ILNumerics memory management. /// System.Numerics.Complex[] A_MSComplex = A.ToMSComplex(); /// // .. do some work here with A_MSComplex /// // ... /// // The results get converted back to ILNumerics array /// ILArray<complex> Result = A_MSComplex.ToILArray(A.S, true); /// /// For the conversion of the System.Numerics.Complex[] array back to an ILNumerics array, we use the same size (A.S) as before. Here, any size /// would work, as long as it fits into the number of elements of the source System.Array. /// Note that the calls to A.ToMSComplex() and A_MSComplex.ToILArray(A.S, true) will fetch and return all System.Arrays involved into/from the /// ILINumerics memory pool. So if called frequently, no pressure on the GC is produced, what qualifies this scheme for high performance scenarios. /// /// /// public unsafe static Complex[] ToMSComplex(this ILRetArray A, Complex[] Storage = null) { try { return ToMSComplexHelper(A.Storage, Storage); } finally { A.Dispose(); } } unsafe private static Complex[] ToMSComplexHelper(ILDenseStorage A, Complex[] Storage) { if (object.Equals(A, null) || A.Size.NumberOfElements == 0) return new Complex[0]; if (!object.Equals(Storage, null) && Storage.Length < A.Size.NumberOfElements) throw new Exceptions.ILArgumentException("The storage array given is too small for the conversion."); Complex[] retArr = (object.Equals(Storage, null)) ? ILMath.New(A.Size.NumberOfElements) : Storage; GCHandle retHandle = GCHandle.Alloc(retArr, GCHandleType.Pinned); GCHandle inHandle = GCHandle.Alloc(A.GetArrayForRead(), GCHandleType.Pinned); complex* retP = (complex*)retHandle.AddrOfPinnedObject(); complex* inP = (complex*)inHandle.AddrOfPinnedObject(); ILMath.complex2ComplexHelper(inP, retP, A.Size.NumberOfElements); retHandle.Free(); inHandle.Free(); return retArr; } /// /// Convert this System.Numerics.Complex[] array to an ILNumerics array with ILNumerics.complex elements /// /// the source array, System.Numerics.Complex[] /// [optional] if specified, the size and shape of the ILNumerics array returned. Otherwise, a vector of length Storage.Length will be returned. /// [optional] Places the incoming System.Numerics.Complex[] array into the ILNumerics memory pool. Default: false. /// ILNumerics array of element type ILNumerics.complex /// /// If the argument was given, it must define an array shape according to the actual length of . Therefore, /// size.NumberOfElements ≤ Storage.Length must be valid. /// /// In a high performance scenario, it is recommended to have the function recycle the incoming storage after use. If is set to true, /// the user is responsible not to reference the incoming array afterwards. The array will be stored into the ILNumerics memory pool and eventually be used for later /// allocation requests (for instance in ). /// /// This example demonstrates a common scenario for interchanging System.Numerics.Complex[] with ILNumerics complex arrays. It takes the converion between System.Numerics.Complex and ILNumerics.complex /// into account, as well as the memory management of all storage involved. /// /// ILArray<complex> A = sqrtc(B); /// // interfacing an external library as System.Numerics.Complex[] /// // We dont provide a System.Array as target for the conversion, /// // so it will be fetched from the ILNumerics memory management. /// System.Numerics.Complex[] A_MSComplex = A.ToMSComplex(); /// // .. do some work here with A_MSComplex /// // ... /// // The results get converted back to ILNumerics array /// ILArray<complex> Result = A_MSComplex.ToILArray(A.S, true); /// /// For the conversion of the System.Numerics.Complex[] array back to an ILNumerics array, we use the same size (A.S) as before. Here, any size /// would work, as long as it fits into the number of elements of the source System.Array. /// Note that the calls to A.ToMSComplex() and A_MSComplex.ToILArray(A.S, true) will fetch and return all System.Arrays involved into/from the /// ILINumerics memory pool. So if called frequently, no pressure on the GC is produced, what qualifies this scheme for high performance scenarios. /// /// /// if the length of the is less than size.NumberOfElements public unsafe static ILRetArray ToILArray(this Complex[] Storage, ILSize size = null, bool recycleStorage = false) { if (Storage == null || Storage.Length == 0) return ILMath.empty(); ILSize outSize = (size == null) ? ILMath.size(Storage.Length, 1) : size; if (outSize.NumberOfElements > Storage.Length) throw new Exceptions.ILArgumentException("Invalid size definition! The number of elements defined by 'size' must be less or equal to the length of 'Storage'."); complex[] retArr = ILMath.New(outSize.NumberOfElements); GCHandle retHandle = GCHandle.Alloc(retArr, GCHandleType.Pinned); GCHandle inHandle = GCHandle.Alloc(Storage, GCHandleType.Pinned); complex* retP = (complex*)retHandle.AddrOfPinnedObject(); complex* inP = (complex*)inHandle.AddrOfPinnedObject(); ILMath.complex2ComplexHelper(inP, retP, outSize.NumberOfElements); retHandle.Free(); inHandle.Free(); if (recycleStorage) { ILMath.free(Storage); } return ILMath.array(retArr, outSize); } } }