Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Functions/builtin/sort.cs @ 11194

Last change on this file since 11194 was 9102, checked in by gkronber, 12 years ago

#1967: ILNumerics source for experimentation

File size: 120.1 KB
Line 
1///
2///    This file is part of ILNumerics Community Edition.
3///
4///    ILNumerics Community Edition - high performance computing for applications.
5///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
6///
7///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
8///    it under the terms of the GNU General Public License version 3 as published by
9///    the Free Software Foundation.
10///
11///    ILNumerics Community Edition is distributed in the hope that it will be useful,
12///    but WITHOUT ANY WARRANTY; without even the implied warranty of
13///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14///    GNU General Public License for more details.
15///
16///    You should have received a copy of the GNU General Public License
17///    along with ILNumerics Community Edition. See the file License.txt in the root
18///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
19///
20///    In addition this software uses the following components and/or licenses:
21///
22///    =================================================================================
23///    The Open Toolkit Library License
24///   
25///    Copyright (c) 2006 - 2009 the Open Toolkit library.
26///   
27///    Permission is hereby granted, free of charge, to any person obtaining a copy
28///    of this software and associated documentation files (the "Software"), to deal
29///    in the Software without restriction, including without limitation the rights to
30///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
31///    the Software, and to permit persons to whom the Software is furnished to do
32///    so, subject to the following conditions:
33///
34///    The above copyright notice and this permission notice shall be included in all
35///    copies or substantial portions of the Software.
36///
37///    =================================================================================
38///   
39
40using System;
41using System.Collections.Generic;
42using System.Text;
43using ILNumerics.Algorithms;
44using ILNumerics.Exceptions;
45using ILNumerics.Data;
46using ILNumerics.Misc;
47
48
49namespace ILNumerics {
50    public partial class ILMath {
51
52
53        /// <summary>
54        /// Sort data in A along first non singleton dimension
55        /// </summary>
56        /// <param name="A">Input array, n-dimensional</param>
57        /// <returns>Sorted array of the same size as A</returns>
58        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm.
59        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
60        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
61        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
62        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
63        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
64        /// </remarks>
65        public static ILRetArray< double > sort (ILInArray< double > A) {
66            using (ILScope.Enter(A)) {
67                int fnsd = A.Size.WorkingDimension();
68                if (fnsd < 0) return A.C;
69                return sort(A, fnsd, false);
70            }
71        }
72        /// <summary>
73        /// Sort data in A along first non singleton dimension
74        /// </summary>
75        /// <param name="A">Input array, n-dimensional</param>
76        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
77        /// <returns>Sorted array of the same size as A</returns>
78        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data
79        /// along the first non singleton dimension will get sorted independently from data
80        /// in the next row/column.
81        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
82        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
83        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
84        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
85        /// </remarks>
86        public static ILRetArray< double > sort (ILInArray< double > A, bool descending) {
87            using (ILScope.Enter(A)) {
88                int fnsd = A.Size.WorkingDimension();
89                if (fnsd < 0) return A.C;
90                return sort(A, fnsd, descending);
91            }
92        }
93        /// <summary>
94        /// Sort data in A along dimension 'dim'
95        /// </summary>
96        /// <param name="A">Input array, n-dimensional</param>
97        /// <param name="descending">Direction of sorting</param>
98        /// <param name="dim">Dimension index to sort along</param>
99        /// <returns>Sorted array of the same size as A</returns>
100        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
101        /// algorithm. 
102        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
103        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
104        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
105        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
106        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
107        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
108        /// </remarks>
109        public static ILRetArray< double > sort (ILInArray< double > A, int dim, bool descending) {
110            if (object.Equals (A,null))
111                throw new Exception("parameter A must not be null");
112            using (ILScope.Enter(A)) {
113                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
114                    throw new ILArgumentException("invalid dimension argument");
115                if (dim >= A.Size.NumberOfDimensions)
116                    return A.C;
117                // early exit: scalar/ empty
118                if (A.IsEmpty || A.IsScalar)
119                    return A.C;
120                ILArray< double> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
121                int inc = ret.Size.SequentialIndexDistance(dim);
122                int dimLen = A.Size[dim];
123                int maxRuns = A.Size.NumberOfElements / dimLen;
124                int posInArr = 0;
125                if (descending) {
126                    if (maxRuns == 1) {
127                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
128                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
129                       
130                        double[] retArr = ret.GetArrayForWrite();
131                        System.Threading.Tasks.Parallel.For(0, maxRuns,
132                            (c) => {
133                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
134                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
135                            });
136                    } else {
137                       
138              double[] retArr = ret.GetArrayForWrite();
139                        for (int c = 0; c < maxRuns; c++) {
140                            if (posInArr >= A.Size.NumberOfElements)
141                                posInArr -= (A.Size.NumberOfElements - 1);
142                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
143                            posInArr += dimLen * inc;
144                        }
145                    }
146                } else {
147                    // ascending
148                    if (maxRuns == 1) {
149                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
150                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
151                         
152                        double[] retArr = ret.GetArrayForWrite();
153                        System.Threading.Tasks.Parallel.For(0, maxRuns,
154                            (c) => {
155                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
156                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
157                            });
158                    } else {
159                       
160                        double[] retArr = ret.GetArrayForWrite();
161                        for (int c = 0; c < maxRuns; c++) {
162                            if (posInArr >= A.Size.NumberOfElements)
163                                posInArr -= (A.Size.NumberOfElements - 1);
164                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
165                            posInArr += dimLen * inc;
166                        }
167                    }
168                }
169                //if (descending) {
170                //    for (int c = 0; c < maxRuns; c++) {
171                //        if (posInArr >= A.Dimensions.NumberOfElements)
172                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
173                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
174                //        posInArr += dimLen * inc;
175                //    }
176                //} else {
177                //    // ascending
178                //    for (int c = 0; c < maxRuns; c++) {
179                //        if (posInArr >= A.Dimensions.NumberOfElements)
180                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
181                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
182                //        posInArr += dimLen * inc;
183                //    }
184                //}
185                return ret;
186            }
187        }
188        /// <summary>
189        /// Sort data in A along dimension 'dim'
190        /// </summary>
191        /// <param name="A">Input array, n-dimensional</param>
192        /// <param name="descending">Direction of sorting</param>
193        /// <param name="dim">Dimension index to sort along</param>
194        /// <param name="Indices">[Output] Returns permutation matrix</param>
195        /// <returns>Sorted array of the same size as A</returns>
196        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
197        /// algorithm. 
198        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
199        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
200        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
201        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
202        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original
203        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
204        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5);
205        /// //A:
206        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
207        /// ILArray&lt;double&gt; I;
208        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
209        /// //R:
210        /// // 0.1231  0.1423  0.2991  0.4324  0.9231 
211        /// //I:
212        /// // 2  3  4  0  1
213        /// </code>
214        /// </example>
215        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
216        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
217        /// </remarks>
218        public static ILRetArray< double> sort( ILInArray< double> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
219            using (ILScope.Enter(A)) {
220                if (object.Equals(A, null))
221                    throw new Exception("parameter A must not be null");
222                if (object.Equals(Indices, null)) {
223                    return sort(A,dim,descending);
224                }
225                if (dim >= A.Size.NumberOfDimensions)
226                    throw new ILArgumentException("invalid dimension argument");
227                // early exit: scalar/ empty
228                if (A.IsEmpty) {
229                    Indices.a = empty<double>(ILSize.Empty00);
230                    return empty< double>(ILSize.Empty00);
231                }
232                if (A.IsScalar) {
233                    Indices.a = 0;
234                    return A.C;
235                }
236                if (dim < 0) {
237                    dim = A.S.WorkingDimension();
238                }
239                int[] tmpDims = A.Size.ToIntArray();
240                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
241                    if (i == dim)
242                        tmpDims[i] = A.Size[dim];
243                    else
244                        tmpDims[i] = 1;
245                }
246                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
247                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
248                tmpDims = A.Size.ToIntArray();
249                tmpDims[dim] = 1;
250                Indices.a = repmat(Indices, tmpDims);
251                //}
252                ILArray<double> ret = A.C;
253                int inc = ret.Size.SequentialIndexDistance(dim);
254                int dimLen = A.Size[dim];
255                int maxRuns = A.Size.NumberOfElements / dimLen;
256                int posInArr = 0;
257                if (descending) {
258                    if (maxRuns == 1) {
259                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
260                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
261                        double [] retArr = ret.GetArrayForWrite();
262                        double[] indArr = Indices.GetArrayForRead();
263                        System.Threading.Tasks.Parallel.For(0, maxRuns,
264                            (c) => {
265                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
266                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
267                        });
268                    } else {
269                        for (int c = 0; c < maxRuns; c++) {
270                            if (posInArr >= A.Size.NumberOfElements)
271                                posInArr -= (A.Size.NumberOfElements - 1);
272                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
273                            posInArr += dimLen * inc;
274                        }
275                    }
276                } else {
277                    // ascending
278                    if (maxRuns == 1) {
279                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
280                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
281                       
282                        double[] retArr = ret.GetArrayForWrite();
283                        double[] indArr = Indices.GetArrayForRead();
284                        System.Threading.Tasks.Parallel.For(0, maxRuns,
285                            (c) => {
286                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
287                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
288                            });
289                    } else {
290                        for (int c = 0; c < maxRuns; c++) {
291                            if (posInArr >= A.Size.NumberOfElements)
292                                posInArr -= (A.Size.NumberOfElements - 1);
293                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
294                            posInArr += dimLen * inc;
295                        }
296                    }
297                }
298                return ret;
299            }
300        }
301
302#region HYCALPER AUTO GENERATED CODE
303
304        /// <summary>
305        /// Sort data in A along first non singleton dimension
306        /// </summary>
307        /// <param name="A">Input array, n-dimensional</param>
308        /// <returns>Sorted array of the same size as A</returns>
309        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm.
310        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
311        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
312        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
313        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
314        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
315        /// </remarks>
316        public static ILRetArray< Int64 > sort (ILInArray< Int64 > A) {
317            using (ILScope.Enter(A)) {
318                int fnsd = A.Size.WorkingDimension();
319                if (fnsd < 0) return A.C;
320                return sort(A, fnsd, false);
321            }
322        }
323        /// <summary>
324        /// Sort data in A along first non singleton dimension
325        /// </summary>
326        /// <param name="A">Input array, n-dimensional</param>
327        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
328        /// <returns>Sorted array of the same size as A</returns>
329        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data
330        /// along the first non singleton dimension will get sorted independently from data
331        /// in the next row/column.
332        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
333        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
334        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
335        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
336        /// </remarks>
337        public static ILRetArray< Int64 > sort (ILInArray< Int64 > A, bool descending) {
338            using (ILScope.Enter(A)) {
339                int fnsd = A.Size.WorkingDimension();
340                if (fnsd < 0) return A.C;
341                return sort(A, fnsd, descending);
342            }
343        }
344        /// <summary>
345        /// Sort data in A along dimension 'dim'
346        /// </summary>
347        /// <param name="A">Input array, n-dimensional</param>
348        /// <param name="descending">Direction of sorting</param>
349        /// <param name="dim">Dimension index to sort along</param>
350        /// <returns>Sorted array of the same size as A</returns>
351        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
352        /// algorithm. 
353        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
354        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
355        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
356        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
357        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
358        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
359        /// </remarks>
360        public static ILRetArray< Int64 > sort (ILInArray< Int64 > A, int dim, bool descending) {
361            if (object.Equals (A,null))
362                throw new Exception("parameter A must not be null");
363            using (ILScope.Enter(A)) {
364                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
365                    throw new ILArgumentException("invalid dimension argument");
366                if (dim >= A.Size.NumberOfDimensions)
367                    return A.C;
368                // early exit: scalar/ empty
369                if (A.IsEmpty || A.IsScalar)
370                    return A.C;
371                ILArray< Int64> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
372                int inc = ret.Size.SequentialIndexDistance(dim);
373                int dimLen = A.Size[dim];
374                int maxRuns = A.Size.NumberOfElements / dimLen;
375                int posInArr = 0;
376                if (descending) {
377                    if (maxRuns == 1) {
378                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
379                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
380                       
381                        Int64[] retArr = ret.GetArrayForWrite();
382                        System.Threading.Tasks.Parallel.For(0, maxRuns,
383                            (c) => {
384                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
385                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
386                            });
387                    } else {
388                       
389              Int64[] retArr = ret.GetArrayForWrite();
390                        for (int c = 0; c < maxRuns; c++) {
391                            if (posInArr >= A.Size.NumberOfElements)
392                                posInArr -= (A.Size.NumberOfElements - 1);
393                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
394                            posInArr += dimLen * inc;
395                        }
396                    }
397                } else {
398                    // ascending
399                    if (maxRuns == 1) {
400                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
401                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
402                       
403                        Int64[] retArr = ret.GetArrayForWrite();
404                        System.Threading.Tasks.Parallel.For(0, maxRuns,
405                            (c) => {
406                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
407                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
408                            });
409                    } else {
410                       
411                        Int64[] retArr = ret.GetArrayForWrite();
412                        for (int c = 0; c < maxRuns; c++) {
413                            if (posInArr >= A.Size.NumberOfElements)
414                                posInArr -= (A.Size.NumberOfElements - 1);
415                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
416                            posInArr += dimLen * inc;
417                        }
418                    }
419                }
420                //if (descending) {
421                //    for (int c = 0; c < maxRuns; c++) {
422                //        if (posInArr >= A.Dimensions.NumberOfElements)
423                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
424                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
425                //        posInArr += dimLen * inc;
426                //    }
427                //} else {
428                //    // ascending
429                //    for (int c = 0; c < maxRuns; c++) {
430                //        if (posInArr >= A.Dimensions.NumberOfElements)
431                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
432                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
433                //        posInArr += dimLen * inc;
434                //    }
435                //}
436                return ret;
437            }
438        }
439        /// <summary>
440        /// Sort data in A along dimension 'dim'
441        /// </summary>
442        /// <param name="A">Input array, n-dimensional</param>
443        /// <param name="descending">Direction of sorting</param>
444        /// <param name="dim">Dimension index to sort along</param>
445        /// <param name="Indices">[Output] Returns permutation matrix</param>
446        /// <returns>Sorted array of the same size as A</returns>
447        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
448        /// algorithm. 
449        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
450        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
451        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
452        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
453        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original
454        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
455        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5);
456        /// //A:
457        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
458        /// ILArray&lt;double&gt; I;
459        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
460        /// //R:
461        /// // 0.1231  0.1423  0.2991  0.4324  0.9231 
462        /// //I:
463        /// // 2  3  4  0  1
464        /// </code>
465        /// </example>
466        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
467        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
468        /// </remarks>
469        public static ILRetArray< Int64> sort( ILInArray< Int64> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
470            using (ILScope.Enter(A)) {
471                if (object.Equals(A, null))
472                    throw new Exception("parameter A must not be null");
473                if (object.Equals(Indices, null)) {
474                    return sort(A,dim,descending);
475                }
476                if (dim >= A.Size.NumberOfDimensions)
477                    throw new ILArgumentException("invalid dimension argument");
478                // early exit: scalar/ empty
479                if (A.IsEmpty) {
480                    Indices.a = empty<double>(ILSize.Empty00);
481                    return empty< Int64>(ILSize.Empty00);
482                }
483                if (A.IsScalar) {
484                    Indices.a = 0;
485                    return A.C;
486                }
487                if (dim < 0) {
488                    dim = A.S.WorkingDimension();
489                }
490                int[] tmpDims = A.Size.ToIntArray();
491                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
492                    if (i == dim)
493                        tmpDims[i] = A.Size[dim];
494                    else
495                        tmpDims[i] = 1;
496                }
497                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
498                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
499                tmpDims = A.Size.ToIntArray();
500                tmpDims[dim] = 1;
501                Indices.a = repmat(Indices, tmpDims);
502                //}
503                ILArray<Int64> ret = A.C;
504                int inc = ret.Size.SequentialIndexDistance(dim);
505                int dimLen = A.Size[dim];
506                int maxRuns = A.Size.NumberOfElements / dimLen;
507                int posInArr = 0;
508                if (descending) {
509                    if (maxRuns == 1) {
510                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
511                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
512                       Int64 [] retArr = ret.GetArrayForWrite();
513                        double[] indArr = Indices.GetArrayForRead();
514                        System.Threading.Tasks.Parallel.For(0, maxRuns,
515                            (c) => {
516                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
517                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
518                        });
519                    } else {
520                        for (int c = 0; c < maxRuns; c++) {
521                            if (posInArr >= A.Size.NumberOfElements)
522                                posInArr -= (A.Size.NumberOfElements - 1);
523                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
524                            posInArr += dimLen * inc;
525                        }
526                    }
527                } else {
528                    // ascending
529                    if (maxRuns == 1) {
530                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
531                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
532                       
533                        Int64[] retArr = ret.GetArrayForWrite();
534                        double[] indArr = Indices.GetArrayForRead();
535                        System.Threading.Tasks.Parallel.For(0, maxRuns,
536                            (c) => {
537                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
538                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
539                            });
540                    } else {
541                        for (int c = 0; c < maxRuns; c++) {
542                            if (posInArr >= A.Size.NumberOfElements)
543                                posInArr -= (A.Size.NumberOfElements - 1);
544                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
545                            posInArr += dimLen * inc;
546                        }
547                    }
548                }
549                return ret;
550            }
551        }
552        /// <summary>
553        /// Sort data in A along first non singleton dimension
554        /// </summary>
555        /// <param name="A">Input array, n-dimensional</param>
556        /// <returns>Sorted array of the same size as A</returns>
557        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm.
558        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
559        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
560        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
561        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
562        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
563        /// </remarks>
564        public static ILRetArray< Int32 > sort (ILInArray< Int32 > A) {
565            using (ILScope.Enter(A)) {
566                int fnsd = A.Size.WorkingDimension();
567                if (fnsd < 0) return A.C;
568                return sort(A, fnsd, false);
569            }
570        }
571        /// <summary>
572        /// Sort data in A along first non singleton dimension
573        /// </summary>
574        /// <param name="A">Input array, n-dimensional</param>
575        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
576        /// <returns>Sorted array of the same size as A</returns>
577        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data
578        /// along the first non singleton dimension will get sorted independently from data
579        /// in the next row/column.
580        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
581        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
582        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
583        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
584        /// </remarks>
585        public static ILRetArray< Int32 > sort (ILInArray< Int32 > A, bool descending) {
586            using (ILScope.Enter(A)) {
587                int fnsd = A.Size.WorkingDimension();
588                if (fnsd < 0) return A.C;
589                return sort(A, fnsd, descending);
590            }
591        }
592        /// <summary>
593        /// Sort data in A along dimension 'dim'
594        /// </summary>
595        /// <param name="A">Input array, n-dimensional</param>
596        /// <param name="descending">Direction of sorting</param>
597        /// <param name="dim">Dimension index to sort along</param>
598        /// <returns>Sorted array of the same size as A</returns>
599        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
600        /// algorithm. 
601        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
602        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
603        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
604        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
605        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
606        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
607        /// </remarks>
608        public static ILRetArray< Int32 > sort (ILInArray< Int32 > A, int dim, bool descending) {
609            if (object.Equals (A,null))
610                throw new Exception("parameter A must not be null");
611            using (ILScope.Enter(A)) {
612                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
613                    throw new ILArgumentException("invalid dimension argument");
614                if (dim >= A.Size.NumberOfDimensions)
615                    return A.C;
616                // early exit: scalar/ empty
617                if (A.IsEmpty || A.IsScalar)
618                    return A.C;
619                ILArray< Int32> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
620                int inc = ret.Size.SequentialIndexDistance(dim);
621                int dimLen = A.Size[dim];
622                int maxRuns = A.Size.NumberOfElements / dimLen;
623                int posInArr = 0;
624                if (descending) {
625                    if (maxRuns == 1) {
626                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
627                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
628                       
629                        Int32[] retArr = ret.GetArrayForWrite();
630                        System.Threading.Tasks.Parallel.For(0, maxRuns,
631                            (c) => {
632                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
633                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
634                            });
635                    } else {
636                       
637              Int32[] retArr = ret.GetArrayForWrite();
638                        for (int c = 0; c < maxRuns; c++) {
639                            if (posInArr >= A.Size.NumberOfElements)
640                                posInArr -= (A.Size.NumberOfElements - 1);
641                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
642                            posInArr += dimLen * inc;
643                        }
644                    }
645                } else {
646                    // ascending
647                    if (maxRuns == 1) {
648                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
649                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
650                       
651                        Int32[] retArr = ret.GetArrayForWrite();
652                        System.Threading.Tasks.Parallel.For(0, maxRuns,
653                            (c) => {
654                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
655                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
656                            });
657                    } else {
658                       
659                        Int32[] retArr = ret.GetArrayForWrite();
660                        for (int c = 0; c < maxRuns; c++) {
661                            if (posInArr >= A.Size.NumberOfElements)
662                                posInArr -= (A.Size.NumberOfElements - 1);
663                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
664                            posInArr += dimLen * inc;
665                        }
666                    }
667                }
668                //if (descending) {
669                //    for (int c = 0; c < maxRuns; c++) {
670                //        if (posInArr >= A.Dimensions.NumberOfElements)
671                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
672                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
673                //        posInArr += dimLen * inc;
674                //    }
675                //} else {
676                //    // ascending
677                //    for (int c = 0; c < maxRuns; c++) {
678                //        if (posInArr >= A.Dimensions.NumberOfElements)
679                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
680                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
681                //        posInArr += dimLen * inc;
682                //    }
683                //}
684                return ret;
685            }
686        }
687        /// <summary>
688        /// Sort data in A along dimension 'dim'
689        /// </summary>
690        /// <param name="A">Input array, n-dimensional</param>
691        /// <param name="descending">Direction of sorting</param>
692        /// <param name="dim">Dimension index to sort along</param>
693        /// <param name="Indices">[Output] Returns permutation matrix</param>
694        /// <returns>Sorted array of the same size as A</returns>
695        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
696        /// algorithm. 
697        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
698        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
699        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
700        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
701        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original
702        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
703        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5);
704        /// //A:
705        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
706        /// ILArray&lt;double&gt; I;
707        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
708        /// //R:
709        /// // 0.1231  0.1423  0.2991  0.4324  0.9231 
710        /// //I:
711        /// // 2  3  4  0  1
712        /// </code>
713        /// </example>
714        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
715        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
716        /// </remarks>
717        public static ILRetArray< Int32> sort( ILInArray< Int32> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
718            using (ILScope.Enter(A)) {
719                if (object.Equals(A, null))
720                    throw new Exception("parameter A must not be null");
721                if (object.Equals(Indices, null)) {
722                    return sort(A,dim,descending);
723                }
724                if (dim >= A.Size.NumberOfDimensions)
725                    throw new ILArgumentException("invalid dimension argument");
726                // early exit: scalar/ empty
727                if (A.IsEmpty) {
728                    Indices.a = empty<double>(ILSize.Empty00);
729                    return empty< Int32>(ILSize.Empty00);
730                }
731                if (A.IsScalar) {
732                    Indices.a = 0;
733                    return A.C;
734                }
735                if (dim < 0) {
736                    dim = A.S.WorkingDimension();
737                }
738                int[] tmpDims = A.Size.ToIntArray();
739                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
740                    if (i == dim)
741                        tmpDims[i] = A.Size[dim];
742                    else
743                        tmpDims[i] = 1;
744                }
745                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
746                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
747                tmpDims = A.Size.ToIntArray();
748                tmpDims[dim] = 1;
749                Indices.a = repmat(Indices, tmpDims);
750                //}
751                ILArray<Int32> ret = A.C;
752                int inc = ret.Size.SequentialIndexDistance(dim);
753                int dimLen = A.Size[dim];
754                int maxRuns = A.Size.NumberOfElements / dimLen;
755                int posInArr = 0;
756                if (descending) {
757                    if (maxRuns == 1) {
758                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
759                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
760                       Int32 [] retArr = ret.GetArrayForWrite();
761                        double[] indArr = Indices.GetArrayForRead();
762                        System.Threading.Tasks.Parallel.For(0, maxRuns,
763                            (c) => {
764                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
765                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
766                        });
767                    } else {
768                        for (int c = 0; c < maxRuns; c++) {
769                            if (posInArr >= A.Size.NumberOfElements)
770                                posInArr -= (A.Size.NumberOfElements - 1);
771                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
772                            posInArr += dimLen * inc;
773                        }
774                    }
775                } else {
776                    // ascending
777                    if (maxRuns == 1) {
778                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
779                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
780                       
781                        Int32[] retArr = ret.GetArrayForWrite();
782                        double[] indArr = Indices.GetArrayForRead();
783                        System.Threading.Tasks.Parallel.For(0, maxRuns,
784                            (c) => {
785                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
786                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
787                            });
788                    } else {
789                        for (int c = 0; c < maxRuns; c++) {
790                            if (posInArr >= A.Size.NumberOfElements)
791                                posInArr -= (A.Size.NumberOfElements - 1);
792                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
793                            posInArr += dimLen * inc;
794                        }
795                    }
796                }
797                return ret;
798            }
799        }
800        /// <summary>
801        /// Sort data in A along first non singleton dimension
802        /// </summary>
803        /// <param name="A">Input array, n-dimensional</param>
804        /// <returns>Sorted array of the same size as A</returns>
805        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm.
806        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
807        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
808        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
809        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
810        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
811        /// </remarks>
812        public static ILRetArray< float > sort (ILInArray< float > A) {
813            using (ILScope.Enter(A)) {
814                int fnsd = A.Size.WorkingDimension();
815                if (fnsd < 0) return A.C;
816                return sort(A, fnsd, false);
817            }
818        }
819        /// <summary>
820        /// Sort data in A along first non singleton dimension
821        /// </summary>
822        /// <param name="A">Input array, n-dimensional</param>
823        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
824        /// <returns>Sorted array of the same size as A</returns>
825        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data
826        /// along the first non singleton dimension will get sorted independently from data
827        /// in the next row/column.
828        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
829        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
830        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
831        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
832        /// </remarks>
833        public static ILRetArray< float > sort (ILInArray< float > A, bool descending) {
834            using (ILScope.Enter(A)) {
835                int fnsd = A.Size.WorkingDimension();
836                if (fnsd < 0) return A.C;
837                return sort(A, fnsd, descending);
838            }
839        }
840        /// <summary>
841        /// Sort data in A along dimension 'dim'
842        /// </summary>
843        /// <param name="A">Input array, n-dimensional</param>
844        /// <param name="descending">Direction of sorting</param>
845        /// <param name="dim">Dimension index to sort along</param>
846        /// <returns>Sorted array of the same size as A</returns>
847        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
848        /// algorithm. 
849        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
850        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
851        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
852        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
853        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
854        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
855        /// </remarks>
856        public static ILRetArray< float > sort (ILInArray< float > A, int dim, bool descending) {
857            if (object.Equals (A,null))
858                throw new Exception("parameter A must not be null");
859            using (ILScope.Enter(A)) {
860                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
861                    throw new ILArgumentException("invalid dimension argument");
862                if (dim >= A.Size.NumberOfDimensions)
863                    return A.C;
864                // early exit: scalar/ empty
865                if (A.IsEmpty || A.IsScalar)
866                    return A.C;
867                ILArray< float> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
868                int inc = ret.Size.SequentialIndexDistance(dim);
869                int dimLen = A.Size[dim];
870                int maxRuns = A.Size.NumberOfElements / dimLen;
871                int posInArr = 0;
872                if (descending) {
873                    if (maxRuns == 1) {
874                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
875                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
876                       
877                        float[] retArr = ret.GetArrayForWrite();
878                        System.Threading.Tasks.Parallel.For(0, maxRuns,
879                            (c) => {
880                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
881                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
882                            });
883                    } else {
884                       
885              float[] retArr = ret.GetArrayForWrite();
886                        for (int c = 0; c < maxRuns; c++) {
887                            if (posInArr >= A.Size.NumberOfElements)
888                                posInArr -= (A.Size.NumberOfElements - 1);
889                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
890                            posInArr += dimLen * inc;
891                        }
892                    }
893                } else {
894                    // ascending
895                    if (maxRuns == 1) {
896                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
897                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
898                       
899                        float[] retArr = ret.GetArrayForWrite();
900                        System.Threading.Tasks.Parallel.For(0, maxRuns,
901                            (c) => {
902                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
903                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
904                            });
905                    } else {
906                       
907                        float[] retArr = ret.GetArrayForWrite();
908                        for (int c = 0; c < maxRuns; c++) {
909                            if (posInArr >= A.Size.NumberOfElements)
910                                posInArr -= (A.Size.NumberOfElements - 1);
911                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
912                            posInArr += dimLen * inc;
913                        }
914                    }
915                }
916                //if (descending) {
917                //    for (int c = 0; c < maxRuns; c++) {
918                //        if (posInArr >= A.Dimensions.NumberOfElements)
919                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
920                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
921                //        posInArr += dimLen * inc;
922                //    }
923                //} else {
924                //    // ascending
925                //    for (int c = 0; c < maxRuns; c++) {
926                //        if (posInArr >= A.Dimensions.NumberOfElements)
927                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
928                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
929                //        posInArr += dimLen * inc;
930                //    }
931                //}
932                return ret;
933            }
934        }
935        /// <summary>
936        /// Sort data in A along dimension 'dim'
937        /// </summary>
938        /// <param name="A">Input array, n-dimensional</param>
939        /// <param name="descending">Direction of sorting</param>
940        /// <param name="dim">Dimension index to sort along</param>
941        /// <param name="Indices">[Output] Returns permutation matrix</param>
942        /// <returns>Sorted array of the same size as A</returns>
943        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
944        /// algorithm. 
945        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
946        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
947        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
948        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
949        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original
950        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
951        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5);
952        /// //A:
953        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
954        /// ILArray&lt;double&gt; I;
955        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
956        /// //R:
957        /// // 0.1231  0.1423  0.2991  0.4324  0.9231 
958        /// //I:
959        /// // 2  3  4  0  1
960        /// </code>
961        /// </example>
962        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
963        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
964        /// </remarks>
965        public static ILRetArray< float> sort( ILInArray< float> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
966            using (ILScope.Enter(A)) {
967                if (object.Equals(A, null))
968                    throw new Exception("parameter A must not be null");
969                if (object.Equals(Indices, null)) {
970                    return sort(A,dim,descending);
971                }
972                if (dim >= A.Size.NumberOfDimensions)
973                    throw new ILArgumentException("invalid dimension argument");
974                // early exit: scalar/ empty
975                if (A.IsEmpty) {
976                    Indices.a = empty<double>(ILSize.Empty00);
977                    return empty< float>(ILSize.Empty00);
978                }
979                if (A.IsScalar) {
980                    Indices.a = 0;
981                    return A.C;
982                }
983                if (dim < 0) {
984                    dim = A.S.WorkingDimension();
985                }
986                int[] tmpDims = A.Size.ToIntArray();
987                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
988                    if (i == dim)
989                        tmpDims[i] = A.Size[dim];
990                    else
991                        tmpDims[i] = 1;
992                }
993                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
994                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
995                tmpDims = A.Size.ToIntArray();
996                tmpDims[dim] = 1;
997                Indices.a = repmat(Indices, tmpDims);
998                //}
999                ILArray<float> ret = A.C;
1000                int inc = ret.Size.SequentialIndexDistance(dim);
1001                int dimLen = A.Size[dim];
1002                int maxRuns = A.Size.NumberOfElements / dimLen;
1003                int posInArr = 0;
1004                if (descending) {
1005                    if (maxRuns == 1) {
1006                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1007                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1008                       float [] retArr = ret.GetArrayForWrite();
1009                        double[] indArr = Indices.GetArrayForRead();
1010                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1011                            (c) => {
1012                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
1013                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
1014                        });
1015                    } else {
1016                        for (int c = 0; c < maxRuns; c++) {
1017                            if (posInArr >= A.Size.NumberOfElements)
1018                                posInArr -= (A.Size.NumberOfElements - 1);
1019                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1020                            posInArr += dimLen * inc;
1021                        }
1022                    }
1023                } else {
1024                    // ascending
1025                    if (maxRuns == 1) {
1026                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1027                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1028                       
1029                        float[] retArr = ret.GetArrayForWrite();
1030                        double[] indArr = Indices.GetArrayForRead();
1031                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1032                            (c) => {
1033                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
1034                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
1035                            });
1036                    } else {
1037                        for (int c = 0; c < maxRuns; c++) {
1038                            if (posInArr >= A.Size.NumberOfElements)
1039                                posInArr -= (A.Size.NumberOfElements - 1);
1040                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1041                            posInArr += dimLen * inc;
1042                        }
1043                    }
1044                }
1045                return ret;
1046            }
1047        }
1048        /// <summary>
1049        /// Sort data in A along first non singleton dimension
1050        /// </summary>
1051        /// <param name="A">Input array, n-dimensional</param>
1052        /// <returns>Sorted array of the same size as A</returns>
1053        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm.
1054        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
1055        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
1056        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
1057        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
1058        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
1059        /// </remarks>
1060        public static ILRetArray< fcomplex > sort (ILInArray< fcomplex > A) {
1061            using (ILScope.Enter(A)) {
1062                int fnsd = A.Size.WorkingDimension();
1063                if (fnsd < 0) return A.C;
1064                return sort(A, fnsd, false);
1065            }
1066        }
1067        /// <summary>
1068        /// Sort data in A along first non singleton dimension
1069        /// </summary>
1070        /// <param name="A">Input array, n-dimensional</param>
1071        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
1072        /// <returns>Sorted array of the same size as A</returns>
1073        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data
1074        /// along the first non singleton dimension will get sorted independently from data
1075        /// in the next row/column.
1076        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
1077        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
1078        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
1079        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
1080        /// </remarks>
1081        public static ILRetArray< fcomplex > sort (ILInArray< fcomplex > A, bool descending) {
1082            using (ILScope.Enter(A)) {
1083                int fnsd = A.Size.WorkingDimension();
1084                if (fnsd < 0) return A.C;
1085                return sort(A, fnsd, descending);
1086            }
1087        }
1088        /// <summary>
1089        /// Sort data in A along dimension 'dim'
1090        /// </summary>
1091        /// <param name="A">Input array, n-dimensional</param>
1092        /// <param name="descending">Direction of sorting</param>
1093        /// <param name="dim">Dimension index to sort along</param>
1094        /// <returns>Sorted array of the same size as A</returns>
1095        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
1096        /// algorithm. 
1097        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
1098        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
1099        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
1100        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
1101        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
1102        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
1103        /// </remarks>
1104        public static ILRetArray< fcomplex > sort (ILInArray< fcomplex > A, int dim, bool descending) {
1105            if (object.Equals (A,null))
1106                throw new Exception("parameter A must not be null");
1107            using (ILScope.Enter(A)) {
1108                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
1109                    throw new ILArgumentException("invalid dimension argument");
1110                if (dim >= A.Size.NumberOfDimensions)
1111                    return A.C;
1112                // early exit: scalar/ empty
1113                if (A.IsEmpty || A.IsScalar)
1114                    return A.C;
1115                ILArray< fcomplex> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
1116                int inc = ret.Size.SequentialIndexDistance(dim);
1117                int dimLen = A.Size[dim];
1118                int maxRuns = A.Size.NumberOfElements / dimLen;
1119                int posInArr = 0;
1120                if (descending) {
1121                    if (maxRuns == 1) {
1122                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1123                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1124                       
1125                        fcomplex[] retArr = ret.GetArrayForWrite();
1126                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1127                            (c) => {
1128                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
1129                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
1130                            });
1131                    } else {
1132                       
1133              fcomplex[] retArr = ret.GetArrayForWrite();
1134                        for (int c = 0; c < maxRuns; c++) {
1135                            if (posInArr >= A.Size.NumberOfElements)
1136                                posInArr -= (A.Size.NumberOfElements - 1);
1137                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
1138                            posInArr += dimLen * inc;
1139                        }
1140                    }
1141                } else {
1142                    // ascending
1143                    if (maxRuns == 1) {
1144                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1145                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1146                       
1147                        fcomplex[] retArr = ret.GetArrayForWrite();
1148                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1149                            (c) => {
1150                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
1151                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
1152                            });
1153                    } else {
1154                       
1155                        fcomplex[] retArr = ret.GetArrayForWrite();
1156                        for (int c = 0; c < maxRuns; c++) {
1157                            if (posInArr >= A.Size.NumberOfElements)
1158                                posInArr -= (A.Size.NumberOfElements - 1);
1159                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
1160                            posInArr += dimLen * inc;
1161                        }
1162                    }
1163                }
1164                //if (descending) {
1165                //    for (int c = 0; c < maxRuns; c++) {
1166                //        if (posInArr >= A.Dimensions.NumberOfElements)
1167                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
1168                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
1169                //        posInArr += dimLen * inc;
1170                //    }
1171                //} else {
1172                //    // ascending
1173                //    for (int c = 0; c < maxRuns; c++) {
1174                //        if (posInArr >= A.Dimensions.NumberOfElements)
1175                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
1176                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
1177                //        posInArr += dimLen * inc;
1178                //    }
1179                //}
1180                return ret;
1181            }
1182        }
1183        /// <summary>
1184        /// Sort data in A along dimension 'dim'
1185        /// </summary>
1186        /// <param name="A">Input array, n-dimensional</param>
1187        /// <param name="descending">Direction of sorting</param>
1188        /// <param name="dim">Dimension index to sort along</param>
1189        /// <param name="Indices">[Output] Returns permutation matrix</param>
1190        /// <returns>Sorted array of the same size as A</returns>
1191        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
1192        /// algorithm. 
1193        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
1194        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
1195        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
1196        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
1197        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original
1198        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
1199        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5);
1200        /// //A:
1201        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
1202        /// ILArray&lt;double&gt; I;
1203        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
1204        /// //R:
1205        /// // 0.1231  0.1423  0.2991  0.4324  0.9231 
1206        /// //I:
1207        /// // 2  3  4  0  1
1208        /// </code>
1209        /// </example>
1210        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
1211        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
1212        /// </remarks>
1213        public static ILRetArray< fcomplex> sort( ILInArray< fcomplex> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
1214            using (ILScope.Enter(A)) {
1215                if (object.Equals(A, null))
1216                    throw new Exception("parameter A must not be null");
1217                if (object.Equals(Indices, null)) {
1218                    return sort(A,dim,descending);
1219                }
1220                if (dim >= A.Size.NumberOfDimensions)
1221                    throw new ILArgumentException("invalid dimension argument");
1222                // early exit: scalar/ empty
1223                if (A.IsEmpty) {
1224                    Indices.a = empty<double>(ILSize.Empty00);
1225                    return empty< fcomplex>(ILSize.Empty00);
1226                }
1227                if (A.IsScalar) {
1228                    Indices.a = 0;
1229                    return A.C;
1230                }
1231                if (dim < 0) {
1232                    dim = A.S.WorkingDimension();
1233                }
1234                int[] tmpDims = A.Size.ToIntArray();
1235                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
1236                    if (i == dim)
1237                        tmpDims[i] = A.Size[dim];
1238                    else
1239                        tmpDims[i] = 1;
1240                }
1241                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
1242                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
1243                tmpDims = A.Size.ToIntArray();
1244                tmpDims[dim] = 1;
1245                Indices.a = repmat(Indices, tmpDims);
1246                //}
1247                ILArray<fcomplex> ret = A.C;
1248                int inc = ret.Size.SequentialIndexDistance(dim);
1249                int dimLen = A.Size[dim];
1250                int maxRuns = A.Size.NumberOfElements / dimLen;
1251                int posInArr = 0;
1252                if (descending) {
1253                    if (maxRuns == 1) {
1254                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1255                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1256                       fcomplex [] retArr = ret.GetArrayForWrite();
1257                        double[] indArr = Indices.GetArrayForRead();
1258                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1259                            (c) => {
1260                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
1261                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
1262                        });
1263                    } else {
1264                        for (int c = 0; c < maxRuns; c++) {
1265                            if (posInArr >= A.Size.NumberOfElements)
1266                                posInArr -= (A.Size.NumberOfElements - 1);
1267                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1268                            posInArr += dimLen * inc;
1269                        }
1270                    }
1271                } else {
1272                    // ascending
1273                    if (maxRuns == 1) {
1274                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1275                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1276                       
1277                        fcomplex[] retArr = ret.GetArrayForWrite();
1278                        double[] indArr = Indices.GetArrayForRead();
1279                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1280                            (c) => {
1281                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
1282                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
1283                            });
1284                    } else {
1285                        for (int c = 0; c < maxRuns; c++) {
1286                            if (posInArr >= A.Size.NumberOfElements)
1287                                posInArr -= (A.Size.NumberOfElements - 1);
1288                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1289                            posInArr += dimLen * inc;
1290                        }
1291                    }
1292                }
1293                return ret;
1294            }
1295        }
1296        /// <summary>
1297        /// Sort data in A along first non singleton dimension
1298        /// </summary>
1299        /// <param name="A">Input array, n-dimensional</param>
1300        /// <returns>Sorted array of the same size as A</returns>
1301        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm.
1302        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
1303        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
1304        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
1305        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
1306        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
1307        /// </remarks>
1308        public static ILRetArray< complex > sort (ILInArray< complex > A) {
1309            using (ILScope.Enter(A)) {
1310                int fnsd = A.Size.WorkingDimension();
1311                if (fnsd < 0) return A.C;
1312                return sort(A, fnsd, false);
1313            }
1314        }
1315        /// <summary>
1316        /// Sort data in A along first non singleton dimension
1317        /// </summary>
1318        /// <param name="A">Input array, n-dimensional</param>
1319        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
1320        /// <returns>Sorted array of the same size as A</returns>
1321        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data
1322        /// along the first non singleton dimension will get sorted independently from data
1323        /// in the next row/column.
1324        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
1325        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
1326        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
1327        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
1328        /// </remarks>
1329        public static ILRetArray< complex > sort (ILInArray< complex > A, bool descending) {
1330            using (ILScope.Enter(A)) {
1331                int fnsd = A.Size.WorkingDimension();
1332                if (fnsd < 0) return A.C;
1333                return sort(A, fnsd, descending);
1334            }
1335        }
1336        /// <summary>
1337        /// Sort data in A along dimension 'dim'
1338        /// </summary>
1339        /// <param name="A">Input array, n-dimensional</param>
1340        /// <param name="descending">Direction of sorting</param>
1341        /// <param name="dim">Dimension index to sort along</param>
1342        /// <returns>Sorted array of the same size as A</returns>
1343        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
1344        /// algorithm. 
1345        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
1346        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
1347        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
1348        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
1349        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
1350        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
1351        /// </remarks>
1352        public static ILRetArray< complex > sort (ILInArray< complex > A, int dim, bool descending) {
1353            if (object.Equals (A,null))
1354                throw new Exception("parameter A must not be null");
1355            using (ILScope.Enter(A)) {
1356                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
1357                    throw new ILArgumentException("invalid dimension argument");
1358                if (dim >= A.Size.NumberOfDimensions)
1359                    return A.C;
1360                // early exit: scalar/ empty
1361                if (A.IsEmpty || A.IsScalar)
1362                    return A.C;
1363                ILArray< complex> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
1364                int inc = ret.Size.SequentialIndexDistance(dim);
1365                int dimLen = A.Size[dim];
1366                int maxRuns = A.Size.NumberOfElements / dimLen;
1367                int posInArr = 0;
1368                if (descending) {
1369                    if (maxRuns == 1) {
1370                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1371                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1372                       
1373                        complex[] retArr = ret.GetArrayForWrite();
1374                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1375                            (c) => {
1376                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
1377                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
1378                            });
1379                    } else {
1380                       
1381              complex[] retArr = ret.GetArrayForWrite();
1382                        for (int c = 0; c < maxRuns; c++) {
1383                            if (posInArr >= A.Size.NumberOfElements)
1384                                posInArr -= (A.Size.NumberOfElements - 1);
1385                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
1386                            posInArr += dimLen * inc;
1387                        }
1388                    }
1389                } else {
1390                    // ascending
1391                    if (maxRuns == 1) {
1392                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1393                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1394                       
1395                        complex[] retArr = ret.GetArrayForWrite();
1396                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1397                            (c) => {
1398                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
1399                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
1400                            });
1401                    } else {
1402                       
1403                        complex[] retArr = ret.GetArrayForWrite();
1404                        for (int c = 0; c < maxRuns; c++) {
1405                            if (posInArr >= A.Size.NumberOfElements)
1406                                posInArr -= (A.Size.NumberOfElements - 1);
1407                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
1408                            posInArr += dimLen * inc;
1409                        }
1410                    }
1411                }
1412                //if (descending) {
1413                //    for (int c = 0; c < maxRuns; c++) {
1414                //        if (posInArr >= A.Dimensions.NumberOfElements)
1415                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
1416                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
1417                //        posInArr += dimLen * inc;
1418                //    }
1419                //} else {
1420                //    // ascending
1421                //    for (int c = 0; c < maxRuns; c++) {
1422                //        if (posInArr >= A.Dimensions.NumberOfElements)
1423                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
1424                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
1425                //        posInArr += dimLen * inc;
1426                //    }
1427                //}
1428                return ret;
1429            }
1430        }
1431        /// <summary>
1432        /// Sort data in A along dimension 'dim'
1433        /// </summary>
1434        /// <param name="A">Input array, n-dimensional</param>
1435        /// <param name="descending">Direction of sorting</param>
1436        /// <param name="dim">Dimension index to sort along</param>
1437        /// <param name="Indices">[Output] Returns permutation matrix</param>
1438        /// <returns>Sorted array of the same size as A</returns>
1439        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
1440        /// algorithm. 
1441        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
1442        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
1443        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
1444        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
1445        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original
1446        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
1447        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5);
1448        /// //A:
1449        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
1450        /// ILArray&lt;double&gt; I;
1451        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
1452        /// //R:
1453        /// // 0.1231  0.1423  0.2991  0.4324  0.9231 
1454        /// //I:
1455        /// // 2  3  4  0  1
1456        /// </code>
1457        /// </example>
1458        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
1459        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
1460        /// </remarks>
1461        public static ILRetArray< complex> sort( ILInArray< complex> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
1462            using (ILScope.Enter(A)) {
1463                if (object.Equals(A, null))
1464                    throw new Exception("parameter A must not be null");
1465                if (object.Equals(Indices, null)) {
1466                    return sort(A,dim,descending);
1467                }
1468                if (dim >= A.Size.NumberOfDimensions)
1469                    throw new ILArgumentException("invalid dimension argument");
1470                // early exit: scalar/ empty
1471                if (A.IsEmpty) {
1472                    Indices.a = empty<double>(ILSize.Empty00);
1473                    return empty< complex>(ILSize.Empty00);
1474                }
1475                if (A.IsScalar) {
1476                    Indices.a = 0;
1477                    return A.C;
1478                }
1479                if (dim < 0) {
1480                    dim = A.S.WorkingDimension();
1481                }
1482                int[] tmpDims = A.Size.ToIntArray();
1483                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
1484                    if (i == dim)
1485                        tmpDims[i] = A.Size[dim];
1486                    else
1487                        tmpDims[i] = 1;
1488                }
1489                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
1490                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
1491                tmpDims = A.Size.ToIntArray();
1492                tmpDims[dim] = 1;
1493                Indices.a = repmat(Indices, tmpDims);
1494                //}
1495                ILArray<complex> ret = A.C;
1496                int inc = ret.Size.SequentialIndexDistance(dim);
1497                int dimLen = A.Size[dim];
1498                int maxRuns = A.Size.NumberOfElements / dimLen;
1499                int posInArr = 0;
1500                if (descending) {
1501                    if (maxRuns == 1) {
1502                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1503                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1504                       complex [] retArr = ret.GetArrayForWrite();
1505                        double[] indArr = Indices.GetArrayForRead();
1506                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1507                            (c) => {
1508                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
1509                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
1510                        });
1511                    } else {
1512                        for (int c = 0; c < maxRuns; c++) {
1513                            if (posInArr >= A.Size.NumberOfElements)
1514                                posInArr -= (A.Size.NumberOfElements - 1);
1515                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1516                            posInArr += dimLen * inc;
1517                        }
1518                    }
1519                } else {
1520                    // ascending
1521                    if (maxRuns == 1) {
1522                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1523                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1524                       
1525                        complex[] retArr = ret.GetArrayForWrite();
1526                        double[] indArr = Indices.GetArrayForRead();
1527                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1528                            (c) => {
1529                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
1530                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
1531                            });
1532                    } else {
1533                        for (int c = 0; c < maxRuns; c++) {
1534                            if (posInArr >= A.Size.NumberOfElements)
1535                                posInArr -= (A.Size.NumberOfElements - 1);
1536                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1537                            posInArr += dimLen * inc;
1538                        }
1539                    }
1540                }
1541                return ret;
1542            }
1543        }
1544        /// <summary>
1545        /// Sort data in A along first non singleton dimension
1546        /// </summary>
1547        /// <param name="A">Input array, n-dimensional</param>
1548        /// <returns>Sorted array of the same size as A</returns>
1549        /// <remarks>The data in A will be sorted in ascending order using a non-recursive quick sort algorithm.
1550        /// Elements along the columns of A will get sorted independently from each other. A is not altered.
1551        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
1552        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
1553        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
1554        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
1555        /// </remarks>
1556        public static ILRetArray< byte > sort (ILInArray< byte > A) {
1557            using (ILScope.Enter(A)) {
1558                int fnsd = A.Size.WorkingDimension();
1559                if (fnsd < 0) return A.C;
1560                return sort(A, fnsd, false);
1561            }
1562        }
1563        /// <summary>
1564        /// Sort data in A along first non singleton dimension
1565        /// </summary>
1566        /// <param name="A">Input array, n-dimensional</param>
1567        /// <param name="descending">Determine the direction of sorting (ascending/ descending)</param>
1568        /// <returns>Sorted array of the same size as A</returns>
1569        /// <remarks>The data in A will be sorted using the quick sort algorithm. Data
1570        /// along the first non singleton dimension will get sorted independently from data
1571        /// in the next row/column.
1572        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
1573        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
1574        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
1575        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
1576        /// </remarks>
1577        public static ILRetArray< byte > sort (ILInArray< byte > A, bool descending) {
1578            using (ILScope.Enter(A)) {
1579                int fnsd = A.Size.WorkingDimension();
1580                if (fnsd < 0) return A.C;
1581                return sort(A, fnsd, descending);
1582            }
1583        }
1584        /// <summary>
1585        /// Sort data in A along dimension 'dim'
1586        /// </summary>
1587        /// <param name="A">Input array, n-dimensional</param>
1588        /// <param name="descending">Direction of sorting</param>
1589        /// <param name="dim">Dimension index to sort along</param>
1590        /// <returns>Sorted array of the same size as A</returns>
1591        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
1592        /// algorithm. 
1593        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
1594        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
1595        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
1596        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
1597        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
1598        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
1599        /// </remarks>
1600        public static ILRetArray< byte > sort (ILInArray< byte > A, int dim, bool descending) {
1601            if (object.Equals (A,null))
1602                throw new Exception("parameter A must not be null");
1603            using (ILScope.Enter(A)) {
1604                if (dim < 0) // || dim >= A.Dimensions.NumberOfDimensions)
1605                    throw new ILArgumentException("invalid dimension argument");
1606                if (dim >= A.Size.NumberOfDimensions)
1607                    return A.C;
1608                // early exit: scalar/ empty
1609                if (A.IsEmpty || A.IsScalar)
1610                    return A.C;
1611                ILArray< byte> ret = A.C; // new ILArray<double>(new Storage.ILDenseStorage<double>(ILMemoryPool.Pool.New<double>(A.Dimensions.NumberOfElements), A.Dimensions));
1612                int inc = ret.Size.SequentialIndexDistance(dim);
1613                int dimLen = A.Size[dim];
1614                int maxRuns = A.Size.NumberOfElements / dimLen;
1615                int posInArr = 0;
1616                if (descending) {
1617                    if (maxRuns == 1) {
1618                        ILQuickSort.QuickSortDescMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1619                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1620                       
1621                        byte[] retArr = ret.GetArrayForWrite();
1622                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1623                            (c) => {
1624                                int pos = (int)(((long)dimLen * c * inc) % (A.Size.NumberOfElements - 1));
1625                                ILQuickSort.QuickSortDescST(retArr, pos, pos + (dimLen - 1) * inc, inc);
1626                            });
1627                    } else {
1628                       
1629              byte[] retArr = ret.GetArrayForWrite();
1630                        for (int c = 0; c < maxRuns; c++) {
1631                            if (posInArr >= A.Size.NumberOfElements)
1632                                posInArr -= (A.Size.NumberOfElements - 1);
1633                            ILQuickSort.QuickSortDescST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
1634                            posInArr += dimLen * inc;
1635                        }
1636                    }
1637                } else {
1638                    // ascending
1639                    if (maxRuns == 1) {
1640                        ILQuickSort.QuickSortAscMT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1641                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1642                       
1643                        byte[] retArr = ret.GetArrayForWrite();
1644                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1645                            (c) => {
1646                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
1647                                ILQuickSort.QuickSortAscST(retArr, pos, pos + (dimLen - 1) * inc, inc);
1648                            });
1649                    } else {
1650                       
1651                        byte[] retArr = ret.GetArrayForWrite();
1652                        for (int c = 0; c < maxRuns; c++) {
1653                            if (posInArr >= A.Size.NumberOfElements)
1654                                posInArr -= (A.Size.NumberOfElements - 1);
1655                            ILQuickSort.QuickSortAscST(retArr, posInArr, posInArr + (dimLen - 1) * inc, inc);
1656                            posInArr += dimLen * inc;
1657                        }
1658                    }
1659                }
1660                //if (descending) {
1661                //    for (int c = 0; c < maxRuns; c++) {
1662                //        if (posInArr >= A.Dimensions.NumberOfElements)
1663                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
1664                //        ILQuickSort.QuickSortDescSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
1665                //        posInArr += dimLen * inc;
1666                //    }
1667                //} else {
1668                //    // ascending
1669                //    for (int c = 0; c < maxRuns; c++) {
1670                //        if (posInArr >= A.Dimensions.NumberOfElements)
1671                //            posInArr -= (A.Dimensions.NumberOfElements - 1);
1672                //        ILQuickSort.QuickSortAscSolid_IT(ret.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc, false);
1673                //        posInArr += dimLen * inc;
1674                //    }
1675                //}
1676                return ret;
1677            }
1678        }
1679        /// <summary>
1680        /// Sort data in A along dimension 'dim'
1681        /// </summary>
1682        /// <param name="A">Input array, n-dimensional</param>
1683        /// <param name="descending">Direction of sorting</param>
1684        /// <param name="dim">Dimension index to sort along</param>
1685        /// <param name="Indices">[Output] Returns permutation matrix</param>
1686        /// <returns>Sorted array of the same size as A</returns>
1687        /// <remarks>The data in A will be sorted along the dimension <paramref name="dim"/> using a non-recursive quicksort
1688        /// algorithm. 
1689        /// <para><b>Handling of NaN values (for double,float,complex or fcomplex arrays element datatypes only):</b>
1690        /// if the input array contains any NaN values, those elements will be sorted to the end of the array on output.</para>
1691        /// <para>Properties of sorting can be tuned by the settings of <see cref="ILNumerics.Settings.s_maxSafeQuicksortRecursionDepth"/>
1692        /// and <see cref="ILNumerics.Settings.s_minimumQuicksortLength"/>.</para>
1693        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original
1694        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
1695        /// <example><code>ILArray&lt;double&gt; A = ILMath.rand(1,5);
1696        /// //A:
1697        /// // 0.4324  0.9231  0.1231  0.1423  0.2991
1698        /// ILArray&lt;double&gt; I;
1699        /// ILArray&lt;double&gt; R = ILMath.sort(A, out I, 1, false);
1700        /// //R:
1701        /// // 0.1231  0.1423  0.2991  0.4324  0.9231 
1702        /// //I:
1703        /// // 2  3  4  0  1
1704        /// </code>
1705        /// </example>
1706        /// <para>The quicksort algorithm is an unstable algorithm. Therefore, if in the input array some elements have
1707        /// identical values, their relative order in the output vector is not garanteed to be unchanged.</para>
1708        /// </remarks>
1709        public static ILRetArray< byte> sort( ILInArray< byte> A, ILOutArray<double> Indices = null, int dim = -1, bool descending = false ) {
1710            using (ILScope.Enter(A)) {
1711                if (object.Equals(A, null))
1712                    throw new Exception("parameter A must not be null");
1713                if (object.Equals(Indices, null)) {
1714                    return sort(A,dim,descending);
1715                }
1716                if (dim >= A.Size.NumberOfDimensions)
1717                    throw new ILArgumentException("invalid dimension argument");
1718                // early exit: scalar/ empty
1719                if (A.IsEmpty) {
1720                    Indices.a = empty<double>(ILSize.Empty00);
1721                    return empty< byte>(ILSize.Empty00);
1722                }
1723                if (A.IsScalar) {
1724                    Indices.a = 0;
1725                    return A.C;
1726                }
1727                if (dim < 0) {
1728                    dim = A.S.WorkingDimension();
1729                }
1730                int[] tmpDims = A.Size.ToIntArray();
1731                for (int i = 0; i < A.Size.NumberOfDimensions; i++) {
1732                    if (i == dim)
1733                        tmpDims[i] = A.Size[dim];
1734                    else
1735                        tmpDims[i] = 1;
1736                }
1737                //if (Indices.IsEmpty || !Indices.D.IsSameSize(A.D)) {
1738                Indices.a = reshape(counter(0.0, 1.0, 1, A.Size[dim]), tmpDims);
1739                tmpDims = A.Size.ToIntArray();
1740                tmpDims[dim] = 1;
1741                Indices.a = repmat(Indices, tmpDims);
1742                //}
1743                ILArray<byte> ret = A.C;
1744                int inc = ret.Size.SequentialIndexDistance(dim);
1745                int dimLen = A.Size[dim];
1746                int maxRuns = A.Size.NumberOfElements / dimLen;
1747                int posInArr = 0;
1748                if (descending) {
1749                    if (maxRuns == 1) {
1750                        ILQuickSort.QuickSortDescIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1751                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1752                       byte [] retArr = ret.GetArrayForWrite();
1753                        double[] indArr = Indices.GetArrayForRead();
1754                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1755                            (c) => {
1756                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements-1);
1757                                ILQuickSort.QuickSortDescIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
1758                        });
1759                    } else {
1760                        for (int c = 0; c < maxRuns; c++) {
1761                            if (posInArr >= A.Size.NumberOfElements)
1762                                posInArr -= (A.Size.NumberOfElements - 1);
1763                            ILQuickSort.QuickSortDescIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1764                            posInArr += dimLen * inc;
1765                        }
1766                    }
1767                } else {
1768                    // ascending
1769                    if (maxRuns == 1) {
1770                        ILQuickSort.QuickSortAscIDXMT(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1771                    } else if (maxRuns >= 2 && dimLen >= ILNumerics.Settings.s_minParallelElement2Count) {
1772                       
1773                        byte[] retArr = ret.GetArrayForWrite();
1774                        double[] indArr = Indices.GetArrayForRead();
1775                        System.Threading.Tasks.Parallel.For(0, maxRuns,
1776                            (c) => {
1777                                int pos = (dimLen * c * inc) % (A.Size.NumberOfElements - 1);
1778                                ILQuickSort.QuickSortAscIDXST(retArr, indArr, pos, pos + (dimLen - 1) * inc, inc);
1779                            });
1780                    } else {
1781                        for (int c = 0; c < maxRuns; c++) {
1782                            if (posInArr >= A.Size.NumberOfElements)
1783                                posInArr -= (A.Size.NumberOfElements - 1);
1784                            ILQuickSort.QuickSortAscIDXST(ret.GetArrayForWrite(), Indices.GetArrayForWrite(), posInArr, posInArr + (dimLen - 1) * inc, inc);
1785                            posInArr += dimLen * inc;
1786                        }
1787                    }
1788                }
1789                return ret;
1790            }
1791        }
1792
1793#endregion HYCALPER AUTO GENERATED CODE
1794
1795#region bucket sort - string
1796        /// <summary>
1797        /// Sort strings in A along first non singleton dimension ascending
1798        /// </summary>
1799        /// <param name="A">Input array. A may be an empty, scalar, vector or matrix.</param>
1800        /// <returns>Sorted array of the same size/shape as A</returns>
1801        /// <remarks><para>The strings in A will be sorted lexicographically in ascending order using the bucket sort algorithm. Data
1802        /// along the first non singleton dimension will get sorted independently from data
1803        /// in the other rows/columns.</para>
1804        /// <para>The sorting order of strings is determined char-wise by comparing the ASCII codes of the characters.</para></remarks>
1805        public static ILRetArray<string> sort (ILInArray<string> A) {
1806            using (ILScope.Enter(A)) {
1807                int fnsd = A.Size.WorkingDimension();
1808                if (fnsd < 0) return A.C;
1809                return sort(A, fnsd, false);
1810            }
1811        }
1812        /// <summary>
1813        /// Sort strings in A along first non singleton dimension
1814        /// </summary>
1815        /// <param name="A">Input array. A may be an empty, scalar, vector or matrix.</param>
1816        /// <param name="descending">Specifies the direction of sorting: true: descending sort direction; false: ascending</param>
1817        /// <returns>Sorted array of the same size/shape as A</returns>
1818        /// <remarks><para>The strings in A will be sorted lexicographically in ascending order using the bucket sort algorithm. Data
1819        /// along the first non singleton dimension will get sorted independently from data
1820        /// in the other rows/columns.</para>
1821        /// <para>The sorting order of strings is determined char-wise by comparing the ASCII codes of the characters.</para></remarks>
1822        public static ILRetArray<string> sort (ILInArray<string> A, bool descending) {
1823            using (ILScope.Enter(A)) {
1824                int fnsd = A.Size.WorkingDimension();
1825                if (fnsd < 0) return A.C;
1826                return sort(A, fnsd, descending);
1827            }
1828        }
1829        /// <summary>
1830        /// Sort strings in A along dimension 'dim'
1831        /// </summary>
1832        /// <param name="A">Input array. A may be an empty, scalar, vector or matrix.</param>
1833        /// <param name="dim">Dimension to sort along</param>
1834        /// <param name="descending">Specifies the direction of sorting: true: descending sort direction; false: ascending</param>
1835        /// <returns>Sorted array of the same size/shape as A</returns>
1836        /// <remarks><para>The strings in A will be sorted lexicographically in ascending order using the bucket sort algorithm. Data
1837        /// along the first non singleton dimension will get sorted independently from data
1838        /// in the other rows/columns.</para>
1839        /// <para>The sorting order of strings is determined char-wise by comparing the ASCII codes of the characters.</para></remarks>
1840        public static ILRetArray<string> sort (ILInArray<string> A, int dim, bool descending) {
1841            if (object.Equals (A,null))
1842                throw new Exception("parameter A must not be null");
1843            using (ILScope.Enter(A)) {
1844                if (A.Size.NumberOfDimensions > 2)
1845                    throw new ILArgumentException("for element type string only matrices are supported!");
1846                if (dim < 0 || dim >= A.Size.NumberOfDimensions)
1847                    throw new ILArgumentException("invalid dimension argument");
1848                // early exit: scalar/ empty
1849                if (A.IsEmpty || A.IsScalar)
1850                    return A.C;
1851                ILArray<string> ret =zeros<string>(A.Size);
1852                int dim1 = dim % A.Size.NumberOfDimensions;
1853                int dim2 = (dim1 + 1) % A.Size.NumberOfDimensions;
1854                int maxRuns = A.Size[dim2];
1855                ILQueueList<string, byte> ql;
1856                ILArray<int>[] ind = new ILArray<int>[2];
1857                int[] indI = new int[2];
1858                ILASCIIKeyMapper km = new ILASCIIKeyMapper();
1859                for (int c = 0; c < maxRuns; c++) {
1860                    ind[dim2] = c;
1861                    ind[dim1] = null;
1862                    ql = ILBucketSort.BucketSort<string, char, byte>(A[ind], null, km, ILBucketSort.SortMethod.ConstantLength);
1863                    indI[dim2] = c;
1864                    if (descending) {
1865                        for (int i = ql.Count; i-- > 0; ) {
1866                            indI[dim1] = i;
1867                            ret.SetValue(ql.Dequeue().Data, indI);
1868                        }
1869                    } else {
1870                        for (int i = 0; ql.Count > 0; i++) {
1871                            indI[dim1] = i;
1872                            ret.SetValue(ql.Dequeue().Data, indI);
1873                        }
1874                    }
1875                }
1876                return ret;
1877            }
1878        }
1879        /// <summary>
1880        /// Sort data in A along dimension 'dim'
1881        /// </summary>
1882        /// <param name="A">Input array: empty, scalar, vector or matrix</param>
1883        /// <param name="descending">Specifies the direction of sorting</param>
1884        /// <param name="dim">Dimension to sort along</param>
1885        /// <param name="Indices">[Output] Returns permutation matrix also</param>
1886        /// <returns>Sorted array of the same size as A</returns>
1887        /// <remarks><para>The data in A will be sorted using the quick sort algorithm. Data
1888        /// along the dimension <paramref name="dim"/> will get sorted independently from data
1889        /// in the next row/column.</para>
1890        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original
1891        /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para>
1892        ///</remarks>
1893        public static ILRetArray<string> sort (ILInArray<string> A, ILOutArray<double> Indices, int dim, bool descending) {
1894            if (object.Equals (A,null))
1895                throw new Exception("parameter A must not be null");
1896            using (ILScope.Enter(A)) {
1897                if (A.Size.NumberOfDimensions > 2)
1898                    throw new ILArgumentException("for element type string only matrices are supported!");
1899                if (dim < 0 || dim >= A.Size.NumberOfDimensions)
1900                    throw new ILArgumentException("invalid dimension argument");
1901                // early exit: scalar/ empty
1902                if (A.IsEmpty || A.IsScalar) {
1903                    Indices.a = 0.0;
1904                    return A.C;
1905                }
1906                ILArray<string> ret = zeros<string>(A.Size);
1907                int dim1 = dim % A.Size.NumberOfDimensions;
1908                int dim2 = (dim1 + 1) % A.Size.NumberOfDimensions;
1909                int maxRuns = A.Size[dim2];
1910                ILQueueList<string, double> ql;
1911                ILBaseArray[] ind = new ILBaseArray[2];
1912                int[] indI = new int[2];
1913                ILASCIIKeyMapper km = new ILASCIIKeyMapper();
1914                Indices.a = ILMath.counter<double>(0.0, 1.0, A.Size);
1915                for (int c = 0; c < maxRuns; c++) {
1916                    ind[dim2] = (ILArray<int>)c;
1917                    ind[dim1] = ILMath.full;
1918                    ql = ILBucketSort.BucketSort<string, char, double>(A[ind], Indices[ind], km, ILBucketSort.SortMethod.ConstantLength);
1919                    indI[dim2] = c;
1920                    if (descending) {
1921                        for (int i = ql.Count; i-- > 0; ) {
1922                            indI[dim1] = i;
1923                            ILListItem<string, double> item = ql.Dequeue();
1924                            ret.SetValue(item.Data, indI);
1925                            Indices.SetValue(item.m_index, indI);
1926                        }
1927                    } else {
1928                        for (int i = 0; ql.Count > 0; i++) {
1929                            indI[dim1] = i;
1930                            ILListItem<string, double> item = ql.Dequeue();
1931                            ret.SetValue(item.Data, indI);
1932                            Indices.SetValue(item.m_index, indI);
1933                        }
1934                    }
1935                }
1936                return ret;
1937            }
1938        }
1939        /// <summary>
1940        /// Generic sort algorithm in A along dimension 'dim'
1941        /// </summary>
1942        /// <param name="A">Input array: empty, scalar, vector or matrix</param>
1943        /// <param name="descending">Specifies the direction of sorting</param>
1944        /// <param name="dim">Dimension to sort along</param>
1945        /// <param name="Indices">[Input/Output] The values in Indices will be returned in the same sorted order as the elements
1946        /// in A. This can be used to derive a permutation matrix of the sorting process.</param>
1947        /// <typeparam name="T">Element type of values of A</typeparam>
1948        /// <typeparam name="S">Subelement type. For element type of string this would be 'char'</typeparam>
1949        /// <typeparam name="I">Element type of indices</typeparam>
1950        /// <param name="keymapper">Instancce of an object of type ILKeyMapper. This object must
1951        /// be derived from ILKeyMapper&lt;T,SubelementType&gt; and match the generic argument <typeparamref name="T"/>. It will be
1952        /// used to split single elements into its subelements and map their content into bucket numbers. For all
1953        /// reference types except those of type string you will have to write your own ILKeyMapper class for that purpose.</param>
1954        /// <returns>Sorted array of the same size as A</returns>
1955        /// <remarks><para>The data in A will be sorted using the quick sort algorithm. Data
1956        /// along the dimension <paramref name="dim"/> will therefore get sorted independently from data
1957        /// in the next row/column.</para>
1958        /// <para>This overload also returns an array 'Indices' which will hold the indices into the original
1959        /// elements <b>after sorting</b>. Therefore, the unsorted indices must be provided by the user on entry. Indices must not be null.</para>
1960        /// <para>This generic version is able to sort arbitrary element types. Even user defined reference types can be sorted
1961        /// by specifying a user defined ILKeyMapper class instance. Also the type of Indices may be arbitrarily choosen. In difference
1962        /// to the regular sort function overload, Indices must manually be given to the function on entry. Elements in 'Indices'
1963        /// are sorted in the same order as the elements of A.</para>
1964        /// <para>By using this overload you may use the same permutation matrix several times to reflect the
1965        /// manipulations done to A due multiple sort processes. The Indices given will directly be used for the sorting
1966        /// disregarding initial order.</para>
1967        /// </remarks>
1968        internal static ILRetArray<T> sort<T, S, I>( ILInArray<T> A, ILOutArray<I> Indices, int dim, bool descending, ILKeyMapper<T, S> keymapper ) {
1969            if (object.Equals(A, null))
1970                throw new Exception("parameter A must not be null");
1971            if (object.Equals(Indices, null))
1972                throw new Exception("parameter 'Indices' must not be null");
1973            using (ILScope.Enter(A)) {
1974                if (!A.IsMatrix)
1975                    throw new ILArgumentException("for generic element type - only matrices are supported");
1976                if (dim < 0 || dim >= A.Size.NumberOfDimensions)
1977                    throw new ILArgumentException("invalid dimension argument");
1978                if (keymapper == null)
1979                    throw new ILArgumentException("the keymapper argument must not be null");
1980                if (object.Equals(Indices, null) || !Indices.Size.IsSameSize(A.Size))
1981                    throw new ILArgumentException("indices argument must have same size/shape as input A");
1982                // early exit: scalar/ empty
1983                if (A.IsEmpty || A.IsScalar) {
1984                    Indices.a = default(I);
1985                    return A.C;
1986                }
1987                ILArray<T> ret = zeros<T>(A.Size);
1988                int dim1 = dim % A.Size.NumberOfDimensions;
1989                int dim2 = (dim1 + 1) % A.Size.NumberOfDimensions;
1990                int maxRuns = A.Size[dim2];
1991                ILQueueList<T, I> ql;
1992                ILBaseArray[] ind = new ILBaseArray[2];
1993                int[] indI = new int[2];
1994                for (int c = 0; c < maxRuns; c++) {
1995                    ind[dim2] = (ILArray<int>)c;
1996                    ind[dim1] = full;
1997                    ql = ILBucketSort.BucketSort<T, S, I>(A[ind], Indices[ind], keymapper, ILBucketSort.SortMethod.ConstantLength);
1998                    indI[dim2] = c;
1999                    if (descending) {
2000                        for (int i = ql.Count; i-- > 0; ) {
2001                            indI[dim1] = i;
2002                            ILListItem<T, I> item = ql.Dequeue();
2003                            ret.SetValue(item.Data, indI);
2004                            Indices.SetValue(item.m_index, indI);
2005                        }
2006                    } else {
2007                        for (int i = 0; ql.Count > 0; i++) {
2008                            indI[dim1] = i;
2009                            ILListItem<T, I> item = ql.Dequeue();
2010                            ret.SetValue(item.Data, indI);
2011                            Indices.SetValue(item.m_index, indI);
2012                        }
2013                    }
2014                }
2015                return ret;
2016            }
2017        }
2018#endregion
2019
2020
2021        internal static bool IsSorted (double[] vec,int length, bool descending) {
2022            if (descending) {
2023                for (int i = 1; i < length; i++) {
2024                    if (vec[i] > vec[i-1])
2025                        return false;
2026                }
2027            } else {
2028                for (int i = 1; i < length; i++) {
2029                    if (vec[i] < vec[i-1])
2030                        return false;
2031                }
2032            }
2033            return true;
2034        }
2035
2036    }
2037}
Note: See TracBrowser for help on using the repository browser.