/// <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); }
bucketSort_constantLength <ElementType, SubelementType, IndexType>( IEnumerable <ElementType> input, IEnumerable <IndexType> indices, ILKeyMapper <ElementType, SubelementType> mapper) { int m = mapper.NumberOfKeys; int tmp = 0; ILQueueList <ElementType, IndexType>[] buckets = new ILQueueList <ElementType, IndexType> [m]; ILQueueList <ElementType, IndexType> Q = new ILQueueList <ElementType, IndexType>(); // find longest element int maxLen = 0; foreach (ElementType elem in input) { tmp = mapper.SubelementsCount(elem); if (tmp > maxLen) { maxLen = tmp; } } // sort into buckets IEnumerator <IndexType> indIt = indices.GetEnumerator(); indIt.MoveNext(); for (int k = maxLen; k-- > 0;) { // walk along the input if (k == maxLen - 1) { foreach (ElementType elem in input) { // put current into bucket int bpos = mapper.Map(elem, k, 0); if (buckets[bpos] == null) { // must create list first buckets[bpos] = new ILQueueList <ElementType, IndexType>(); } // append to list buckets[bpos].Enqueue(elem, indIt.Current); indIt.MoveNext(); } } else { while (Q.Count > 0) { // put current into bucket ILListItem <ElementType, IndexType> elem = Q.Dequeue(); int bpos = mapper.Map(elem.Data, k, 0); if (buckets[bpos] == null) { // must create list first buckets[bpos] = new ILQueueList <ElementType, IndexType>(); } // append to list buckets[bpos].Enqueue(elem); } } // concatenate all buckets for (int i = 0; i < buckets.Length; i++) { if (buckets[i] != null && buckets[i].Count > 0) { Q.Enqueue(buckets[i]); buckets[i].Clear(); } } // goto previous position in strings } return(Q); }
/// <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); }