/// /// 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.Text; using ILNumerics; using ILNumerics.Exceptions; using ILNumerics.Storage; using ILNumerics.Misc; namespace ILNumerics { public partial class ILMath { #region convenience functions (real arguments) /// /// Complex conjugate of A /// /// Input array /// The array itself /// This overload is provided for convenience only. It eases the implementation of complex functions, where complex conjugate transposes are needed. public static ILRetArray conj (ILInArray A) { using (ILScope.Enter(A)) return A.C; } /// /// Complex conjugate of A /// /// Input array /// The array itself /// This overload is provided for convenience only. It eases the implementation of complex functions, where complex conjugate transposes are needed. public static ILRetArray conj (ILInArray A) { using (ILScope.Enter(A)) return A.C; } #endregion convenience functions (real arguments) /// Complex conjugate of array A /// Input array /// Complex conjugate of array A /// If the input array is empty, an empty array will be returned. /// The array returned will be a dense array. public unsafe static ILRetArray conj(ILInArray A) { using (ILScope.Enter(A)) { if (A.IsEmpty) return new ILRetArray(A.Size); ILSize inDim = A.Size; complex[] arrA = A.GetArrayForRead(); complex[] retArr; int outLen = inDim.NumberOfElements; bool inplace = true; if (!A.TryGetStorage4InplaceOp(out retArr)) { retArr = ILMemoryPool.Pool.New(outLen); inplace = false; } int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1; if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) { if (outLen / workItemCount > Settings.s_minParallelElement1Count) { workItemLength = outLen / workItemCount; //workItemLength = (int)((double)outLen / workItemCount * 1.05); } else { workItemLength = outLen / 2; workItemCount = 2; } } else { workItemLength = outLen; workItemCount = 1; } ILDenseStorage retStorage = new ILDenseStorage(retArr, inDim); Action worker = data => { Tuple range = (Tuple)data; complex* cp = ((complex*)range.Item4 + range.Item1); complex* cLast = cp + range.Item2; if (range.Item5) { // inplace while (cp < cLast) { (*cp).imag = (*cp).imag * -1.0; cp++; } } else { complex* ap = ((complex*)range.Item3 + range.Item1); while (cp < cLast) { (*cp).real = (*ap).real; (*cp).imag = (*ap).imag * -1.0; ap++; cp++; } } System.Threading.Interlocked.Decrement(ref workerCount); //retStorage.PendingEvents.Signal(); }; //retStorage.PendingEvents = new System.Threading.CountdownEvent(workItemCount); fixed (complex* arrAP = arrA) fixed (complex* retArrP = retArr) { for (; i < workItemCount - 1; i++) { Tuple range = new Tuple (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace); System.Threading.Interlocked.Increment(ref workerCount); ILThreadPool.QueueUserWorkItem(i, worker, range); } // the last (or may the only) chunk is done right here worker(new Tuple (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace)); ILThreadPool.Wait4Workers(ref workerCount); } return new ILRetArray(retStorage); } } /// Complex conjugate of array A /// Input array /// Complex conjugate of array A /// If the input array is empty, an empty array will be returned. /// The array returned will be a dense array. public unsafe static ILRetArray conj (ILInArray< fcomplex > A) { using (ILScope.Enter(A)) { if (A.IsEmpty) return new ILRetArray(A.Size); ILSize inDim = A.Size; fcomplex[] arrA = A.GetArrayForRead(); fcomplex [] retArr; int outLen = inDim.NumberOfElements; bool inplace = true; if (!A.TryGetStorage4InplaceOp(out retArr)) { retArr = ILMemoryPool.Pool.New(outLen); inplace = false; } int i = 0, workItemCount = Settings.s_maxNumberThreads, workItemLength, workerCount = 1; if (Settings.s_maxNumberThreads > 1 && outLen / 2 > Settings.s_minParallelElement1Count) { if (outLen / workItemCount > Settings.s_minParallelElement1Count) { workItemLength = outLen / workItemCount; //workItemLength = (int)((double)outLen / workItemCount * 1.05); } else { workItemLength = outLen / 2; workItemCount = 2; } } else { workItemLength = outLen; workItemCount = 1; } ILDenseStorage retStorage = new ILDenseStorage(retArr, inDim); Action worker = data => { Tuple range = (Tuple)data; fcomplex* cp = ((fcomplex*)range.Item4 + range.Item1); fcomplex* cLast = cp + range.Item2; if (range.Item5) { // inplace while (cp < cLast) { (*cp).imag = (*cp).imag * -1.0f; cp++; } } else { fcomplex* ap = ((fcomplex*)range.Item3 + range.Item1); while (cp < cLast) { (*cp).real = (*ap).real; (*cp).imag = (*ap).imag * -1.0f; ap++; cp++; } } System.Threading.Interlocked.Decrement(ref workerCount); //retStorage.PendingEvents.Signal(); }; //retStorage.PendingEvents = new System.Threading.CountdownEvent(workItemCount); fixed ( fcomplex* arrAP = arrA) fixed ( fcomplex* retArrP = retArr) { for (; i < workItemCount - 1; i++) { Tuple range = new Tuple (i * workItemLength, workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace); System.Threading.Interlocked.Increment(ref workerCount); ILThreadPool.QueueUserWorkItem(i,worker, range); } // the last (or may the only) chunk is done right here worker(new Tuple (i * workItemLength, outLen - i * workItemLength, (IntPtr)arrAP, (IntPtr)retArrP, inplace)); ILThreadPool.Wait4Workers(ref workerCount); } return new ILRetArray(retStorage); } } } }