Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a good radixsort-implementation for floats in C#

I have a datastructure with a field of the float-type. A collection of these structures needs to be sorted by the value of the float. Is there a radix-sort implementation for this.

If there isn't, is there a fast way to access the exponent, the sign and the mantissa. Because if you sort the floats first on mantissa, exponent, and on exponent the last time. You sort floats in O(n).

like image 353
Willem Van Onsem Avatar asked Apr 21 '10 17:04

Willem Van Onsem


People also ask

What are the advantages of radix sort?

Now, sort the elements based on digits at tens place. Finally, sort the elements based on the digits at hundreds place. Since radix sort is a non-comparative algorithm, it has advantages over comparative sorting algorithms.

How to sort an array according to radix sort?

Let the initial array be [121, 432, 564, 23, 1, 45, 788]. It is sorted according to radix sort as shown in the figure below. Please go through the counting sort before reading this article because counting sort is used as an intermediate sort in radix sort. Find the largest element in the array, i.e. max. Let X be the number of digits in max.

What is the time complexity of radix sort?

Radix Sort Complexity Since radix sort is a non-comparative algorithm, it has advantages over comparative sorting algorithms. For the radix sort that uses counting sort as an intermediate stable sort, the time complexity is O (d (n+k)). Here, d is the number cycle and O (n+k) is the time complexity of counting sort.

How to compare two floating point numbers in C?

In C# this can be done by implementing the interface. methods of the integer and fractional parts. By specification, in fact, must return 0 if two numbers are equal. variables, we are able to perform comparisons with other floating-point types as well. This is because we have instructed the compiler that s. s are the same.


2 Answers

There's a nice explanation of how to perform radix sort on floats here: http://www.codercorner.com/RadixSortRevisited.htm

If all your values are positive, you can get away with using the binary representation; the link explains how to handle negative values.

like image 128
celion Avatar answered Sep 24 '22 23:09

celion


By doing some fancy casting and swapping arrays instead of copying this version is 2x faster for 10M numbers as Philip Daubmeiers original with grouplength set to 8. It is 3x faster as Array.Sort for that arraysize.

 static public void RadixSortFloat(this float[] array, int arrayLen = -1)
        {
            // Some use cases have an array that is longer as the filled part which we want to sort
            if (arrayLen < 0) arrayLen = array.Length;
            // Cast our original array as long
            Span<float> asFloat = array;
            Span<int> a = MemoryMarshal.Cast<float, int>(asFloat);
            // Create a temp array
            Span<int> t = new Span<int>(new int[arrayLen]);

            // set the group length to 1, 2, 4, 8 or 16 and see which one is quicker
            int groupLength = 8;
            int bitLength = 32;

            // counting and prefix arrays
            // (dimension is 2^r, the number of possible values of a r-bit number) 
            var dim = 1 << groupLength;
            int groups = bitLength / groupLength;
            if (groups % 2 != 0) throw new Exception("groups must be even so data is in original array at end");
            var count = new int[dim];
            var pref = new int[dim];
            int mask = (dim) - 1;
            int negatives = 0, positives = 0;

            // counting elements of the 1st group incuding negative/positive
            for (int i = 0; i < arrayLen; i++)
            {
                if (a[i] < 0) negatives++;
                count[(a[i] >> 0) & mask]++;
            }
            positives = arrayLen - negatives;

            int c;
            int shift;
            for (c = 0, shift = 0; c < groups - 1; c++, shift += groupLength)
            {
                CalcPrefixes();
                var nextShift = shift + groupLength;
                //
                for (var i = 0; i < arrayLen; i++)
                {
                    var ai = a[i];
                    // Get the right index to sort the number in
                    int index = pref[( ai >> shift) & mask]++;
                    count[( ai>> nextShift) & mask]++;
                    t[index] =  ai;
                }

                // swap the arrays and start again until the last group 
                var temp = a;
                a = t;
                t = temp;
            }

            // Last round
            CalcPrefixes();
            for (var i = 0; i < arrayLen; i++)
            {
                var ai = a[i];
                // Get the right index to sort the number in
                int index = pref[( ai >> shift) & mask]++;
                // We're in the last (most significant) group, if the
                // number is negative, order them inversely in front
                // of the array, pushing positive ones back.
                if ( ai < 0) index = positives - (index - negatives) - 1; else index += negatives;
                //
                t[index] =  ai;
            }

            void CalcPrefixes()
            {
                pref[0] = 0;
                for (int i = 1; i < dim; i++)
                {
                    pref[i] = pref[i - 1] + count[i - 1];
                    count[i - 1] = 0;
                }
            }
        }
like image 27
IvoTops Avatar answered Sep 24 '22 23:09

IvoTops