/// <summary> /// sort data in A along dimension 'dim' /// </summary> /// <param name="A">input array: empty, scalar, vector or matrix</param> /// <param name="descending">Specifies the direction of sorting</param> /// <param name="dim">dimension to sort along</param> /// <param name="Indices">output parameter: returns permutation matrix also</param> /// <returns>sorted array of the same size as A</returns> /// <remarks><para>The data in A will be sorted using the quick sort algorithm. Data /// along the dimension <paramref name="dim"/> will therefore get sorted independently from data /// in the next row/column.</para> /// <para>This overload also returns an array 'Indices' which will hold the indices into the original /// elements <b>after sorting</b>. Elements of 'Indices' are of type double.</para> ///</remarks> public static ILArray <string> sort(ILArray <string> A, out ILArray <double> Indices, int dim, bool descending) { if (object.Equals(A, null)) { throw new Exception("sort: parameter A must not be null"); } if (A.Dimensions.NumberOfDimensions > 2) { throw new ILArgumentException("sort: for element type string only matrices are supported!"); } if (dim < 0 || dim >= A.Dimensions.NumberOfDimensions) { throw new ILArgumentException("sort: invalid dimension argument"); } // early exit: scalar/ empty if (A.IsEmpty || A.IsScalar) { Indices = 0.0; return(A.C); } ILArray <string> ret = new ILArray <string>(new string[A.Dimensions.NumberOfElements], A.Dimensions); int dim1 = dim % A.Dimensions.NumberOfDimensions; int dim2 = (dim1 + 1) % A.Dimensions.NumberOfDimensions; int maxRuns = A.Dimensions[dim2]; ILQueueList <string, double> ql; ILArray <int>[] ind = new ILArray <int> [2]; int [] indI = new int[2]; ILASCIIKeyMapper km = new ILASCIIKeyMapper(); Indices = ILMath.counter(0.0, 1.0, A.Dimensions.ToIntArray()); for (int c = 0; c < maxRuns; c++) { ind[dim2] = c; ind[dim1] = null; ql = ILBucketSort.BucketSort <string, char, double>(A[ind].Values, Indices[ind].Values, km, ILBucketSort.SortMethod.ConstantLength); indI[dim2] = c; if (descending) { for (int i = ql.Count; i-- > 0;) { indI[dim1] = i; ILListItem <string, double> item = ql.Dequeue(); ret.SetValue(item.Data, indI); Indices.SetValue(item.m_index, indI); } } else { for (int i = 0; ql.Count > 0; i++) { indI[dim1] = i; ILListItem <string, double> item = ql.Dequeue(); ret.SetValue(item.Data, indI); Indices.SetValue(item.m_index, indI); } } } return(ret); }
private void TestBucketSort_Performance(string[] p) { int errCode = 0; try { // test constant length method System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); ILQueueList <string, byte> res1 = ILBucketSort.BucketSort <string, char, byte>(p, null, new ILASCIIKeyMapper(), ILBucketSort.SortMethod.ConstantLength); sw.Stop(); Info("sorting variable length: " + sw.ElapsedMilliseconds + " ms needed."); string [] res = res1.ToArray(); // test variable length method sw.Reset(); sw.Start(); ILQueueList <string, byte> res2 = ILBucketSort.BucketSort <string, char, byte>(p, null, new ILASCIIKeyMapper(), ILBucketSort.SortMethod.VariableLenth); sw.Stop(); if (!StringsEqual(res1.ToArray(), res2.ToArray())) { throw new Exception("different result for methods detected!"); } Success("Sorted " + p.Length + " strings."); } catch (Exception e) { Error(errCode, e.Message + "(" + PrintStrings(p) + ")"); } }
/// <summary> /// sort utilizing bucket sort /// </summary> /// <typeparam name="SubelementType">subelement type</typeparam> /// <param name="mapper">keymapper mapping subelement items to buckets</param> public void Sort <SubelementType>(ILKeyMapper <T1, SubelementType> mapper) { ILQueueList <T1, T2> ret = ILBucketSort.BucketSort <T1, SubelementType, T2>(this, null, mapper, ILBucketSort.SortMethod.ConstantLength); this.Head = ret.Head; this.Tail = ret.Tail; }
private void TestBucketSort(string[] p, string[] p_2) { int errCode = 0; try { ILQueueList <string, byte> res = ILBucketSort.BucketSort <string, char, byte>(p, null, new ILASCIIKeyMapper(), ILBucketSort.SortMethod.VariableLenth); if (!StringsEqual(p_2, res.ToArray())) { throw new Exception("invalid values detected!"); } Success(PrintStrings(p)); } catch (Exception e) { Error(errCode, e.Message + "(" + PrintStrings(p) + ")"); } }
/// <summary> /// generic sort algorithm in A along dimension 'dim' /// </summary> /// <param name="A">input array: empty, scalar, vector or matrix</param> /// <param name="descending">Specifies the direction of sorting</param> /// <param name="dim">dimension to sort along</param> /// <param name="Indices">input/output parameter: the values in Indices will be returned in the same sorted order as the elements in A. This can be used to derive a permutation matrix of the sorting process.</param> /// <param name="keymapper">Instancce of an object of type ILKeyMapper. This object must /// be derived ILKeyMapper<T,SubelementType> and match the generic argument <typeparamref name="T"/>. It will be /// used to split single elements into its subelements and map their content into bucket numbers. For all /// reference types except those of type string you will have to write your own ILKeyMapper class for that purpose.</param> /// <returns>sorted array of the same size as A</returns> /// <remarks><para>The data in A will be sorted using the quick sort algorithm. Data /// along the dimension <paramref name="dim"/> will therefore get sorted independently from data /// in the next row/column.</para> /// <para>This overload also returns an array 'Indices' which will hold the indices into the original /// elements <b>after sorting</b>. Elements of 'Indices' are always of type int.</para> /// <para>This generic version is able to sort arbitrary element types. Even user defined reference types can be sorted /// by specifying a user defined ILKeyMapper class instance. Also the type of Indices may be arbitrarily choosen. In difference /// to the regular sort function overload, Indices must manually given to the function on the beginning. The given array's /// elements will than be sorted in the same order as the input array A and returned.</para> /// <para>By using this overload you may use the same permutation matrix several times to reflect the /// manipulations done to A due multiple sort processes. The Indices given will directly get used for the current sorting /// without looking at their initial order.</para> /// </remarks> public static ILArray <T> sort <T, S, I> (ILArray <T> A, ref ILArray <I> Indices, int dim, bool descending, ILKeyMapper <T, S> keymapper) { if (object.Equals(A, null)) { throw new Exception("sort: parameter A must not be null"); } if (A.Dimensions.NumberOfDimensions > 2) { throw new ILArgumentException("sort: for generic element type - only matrices are supported!"); } if (dim < 0 || dim >= A.Dimensions.NumberOfDimensions) { throw new ILArgumentException("sort: invalid dimension argument"); } if (keymapper == null) { throw new ILArgumentException("sort: the keymapper argument must not be null"); } if (object.Equals(Indices, null) || !Indices.Dimensions.IsSameSize(A.Dimensions)) { throw new ILArgumentException("sort: Indices argument must have same size/shape as input A"); } // early exit: scalar/ empty if (A.IsEmpty || A.IsScalar) { Indices = default(I); return(A.C); } ILArray <T> ret = new ILArray <T>(new T[A.Dimensions.NumberOfElements], A.Dimensions); int dim1 = dim % A.Dimensions.NumberOfDimensions; int dim2 = (dim1 + 1) % A.Dimensions.NumberOfDimensions; int maxRuns = A.Dimensions[dim2]; ILQueueList <T, I> ql; ILArray <int>[] ind = new ILArray <int> [2]; int [] indI = new int[2]; for (int c = 0; c < maxRuns; c++) { ind[dim2] = c; ind[dim1] = null; ql = ILBucketSort.BucketSort <T, S, I>(A[ind].Values, Indices[ind].Values, keymapper, ILBucketSort.SortMethod.ConstantLength); indI[dim2] = c; if (descending) { for (int i = ql.Count; i-- > 0;) { indI[dim1] = i; ILListItem <T, I> item = ql.Dequeue(); ret.SetValue(item.Data, indI); Indices.SetValue(item.m_index, indI); } } else { for (int i = 0; ql.Count > 0; i++) { indI[dim1] = i; ILListItem <T, I> item = ql.Dequeue(); ret.SetValue(item.Data, indI); Indices.SetValue(item.m_index, indI); } } } return(ret); }