///
/// 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);
}
}
}