public static uint[][] HistogramByteComponents(uint[] inArray, Int32 l, Int32 r) { const int numberOfBins = 256; const int numberOfDigits = sizeof(uint); uint[][] count = new uint[numberOfDigits][]; for (int i = 0; i < numberOfDigits; i++) { count[i] = new uint[numberOfBins]; } #if true var union = new UInt32ByteUnion(); for (int current = l; current <= r; current++) // Scan the array and count the number of times each digit value appears - i.e. size of each bin { union.integer = inArray[current]; count[0][union.byte0]++; count[1][union.byte1]++; count[2][union.byte2]++; count[3][union.byte3]++; } #else for (int current = l; current <= r; current++) // Scan the array and count the number of times each digit value appears - i.e. size of each bin { uint value = inArray[current]; count[0][value & 0xff]++; count[1][(value & 0xff00) >> 8]++; count[2][(value & 0xff0000) >> 16]++; count[3][(value & 0xff000000) >> 24]++; } #endif return(count); }
public static Tuple <uint[][], UInt32[]> HistogramByteComponentsAndKeyArray <T>(T[] inArray, Int32 l, Int32 r, Func <T, UInt32> getKey) { const int numberOfBins = 256; const int numberOfDigits = sizeof(UInt32); var inKeys = new UInt32[inArray.Length]; var count = new uint[numberOfDigits][]; for (int i = 0; i < numberOfDigits; i++) { count[i] = new uint[numberOfBins]; } #if true var union = new UInt32ByteUnion(); for (int current = l; current <= r; current++) // Scan the array and count the number of times each digit value appears - i.e. size of each bin { union.integer = getKey(inArray[current]); inKeys[current] = union.integer; count[0][union.byte0]++; count[1][union.byte1]++; count[2][union.byte2]++; count[3][union.byte3]++; } #else for (int current = l; current <= r; current++) // Scan the array and count the number of times each digit value appears - i.e. size of each bin { uint value = inArray[current]; count[0][value & 0xff]++; count[1][(value & 0xff00) >> 8]++; count[2][(value & 0xff0000) >> 16]++; count[3][(value & 0xff000000) >> 24]++; } #endif return(new Tuple <uint[][], UInt32[]>(count, inKeys)); }
public static uint[][] HistogramByteComponents <T>(T[] inArray, Int32 l, Int32 r, Func <T, UInt32> getKey) { const int numberOfBins = 256; const int numberOfDigits = sizeof(UInt32); uint[][] count = new uint[numberOfDigits][]; for (int i = 0; i < numberOfDigits; i++) { count[i] = new uint[numberOfBins]; } #if true var union = new UInt32ByteUnion(); for (int current = l; current <= r; current++) // Scan the array and count the number of times each digit value appears - i.e. size of each bin { union.integer = getKey(inArray[current]); count[0][union.byte0]++; count[1][union.byte1]++; count[2][union.byte2]++; count[3][union.byte3]++; } #else for (int current = l; current <= r; current++) // Scan the array and count the number of times each digit value appears - i.e. size of each bin { uint value = getKey(inArray[current]); count[0][(byte)value]++; count[1][(byte)(value >> 8)]++; count[2][(byte)(value >> 16)]++; count[3][(byte)(value >> 24)]++; } #endif return(count); }
public static uint[][][] HistogramByteComponentsAcrossWorkQuantas(uint[] inArray, uint workQuanta) { const int numberOfBins = 256; const int numberOfDigits = sizeof(uint); uint numberOfQuantas = (inArray.Length % workQuanta) == 0 ? (uint)(inArray.Length / workQuanta) : (uint)(inArray.Length / workQuanta + 1); Console.WriteLine("Histogram: inArray.Length = {0}, workQuanta = {1}, numberOfQuantas = {2}", inArray.Length, workQuanta, numberOfQuantas); uint[][][] count = new uint[numberOfQuantas][][]; // count for each parallel work item for (int i = 0; i < numberOfQuantas; i++) { count[i] = new uint[numberOfDigits][]; for (int d = 0; d < numberOfDigits; d++) { count[i][d] = new uint[numberOfBins]; } } uint numberOfFullQuantas = (uint)(inArray.Length / workQuanta); int currIndex = 0; var union = new UInt32ByteUnion(); uint q = 0; for (; q < numberOfFullQuantas; q++) { for (uint j = 0; j < workQuanta; j++) { union.integer = inArray[currIndex++]; count[q][0][union.byte0]++; count[q][1][union.byte1]++; count[q][2][union.byte2]++; count[q][3][union.byte3]++; } } // Last work quanta may be a partial one, whenever array length doesn't divide evenly by work quanta for (; currIndex < inArray.Length;) // Scan the array and count the number of times each digit value appears - i.e. size of each bin { union.integer = inArray[currIndex++]; count[q][0][union.byte0]++; count[q][1][union.byte1]++; count[q][2][union.byte2]++; count[q][3][union.byte3]++; } for (int d = 0; d < numberOfDigits; d++) { for (q = 0; q < numberOfQuantas; q++) { Console.WriteLine("h: q = {0} d = {1}", q, d); for (uint b = 0; b < numberOfBins; b++) { Console.Write("{0} ", count[q][d][b]); } Console.WriteLine(); } } return(count); }
private static uint[][] ByteCountInner(uint[] inArray, Int32 l, Int32 r, int numberOfDigits, int numberOfBins) { uint[][] countLeft = new uint[numberOfDigits][]; for (int i = 0; i < numberOfDigits; i++) { countLeft[i] = new uint[numberOfBins]; } if (l > r) // zero elements to compare { return(countLeft); } if ((r - l + 1) <= ThresholdByteCount) { var digits = new byte[4]; UInt32ByteUnion union = new UInt32ByteUnion(); for (int current = l; current <= r; current++) // Scan the array and count the number of times each digit value appears - i.e. size of each bin { union.integer = inArray[current]; countLeft[0][union.byte0]++; countLeft[1][union.byte1]++; countLeft[2][union.byte2]++; countLeft[3][union.byte3]++; } return(countLeft); } int m = (r + l) / 2; uint[][] countRight = new uint[numberOfDigits][]; for (int i = 0; i < numberOfDigits; i++) { countRight[i] = new uint[numberOfBins]; } Parallel.Invoke(() => { countLeft = ByteCountInner(inArray, l, m, numberOfDigits, numberOfBins); }, () => { countRight = ByteCountInner(inArray, m + 1, r, numberOfDigits, numberOfBins); } ); // Combine left and right results for (int i = 0; i < numberOfDigits; i++) { for (int j = 0; j < numberOfBins; j++) { countLeft[i][j] += countRight[i][j]; } } return(countLeft); }
// The idea of 1-D array is that the individual digit counts (256 per digit in case of 8-bit digits) don't interfere with each other in L1 cache // whereas with jagged array they may depending on how each row happens to be allocated on the heap public static uint[] HistogramByteComponents1D(uint[] inArray, Int32 l, Int32 r) { const int numberOfBins = 256; const int numberOfDigits = sizeof(uint); uint[] count = new uint[numberOfDigits * numberOfBins]; var union = new UInt32ByteUnion(); for (int current = l; current <= r; current++) { union.integer = inArray[current]; count[ union.byte0]++; count[256 + union.byte1]++; count[512 + union.byte2]++; count[768 + union.byte3]++; } return count; }
public static uint[][] HistogramNBitsPerComponents(uint[] inArray, Int32 l, Int32 r, int bitsPerComponent) { int numberOfBins = 1 << bitsPerComponent; int numberOfDigits = (sizeof(uint) * 8 + bitsPerComponent - 1) / bitsPerComponent; // round up //Console.WriteLine("HistogramNBitsPerComponents: NumberOfDigits = {0}", numberOfDigits); uint[][] countLeft = new uint[numberOfDigits][]; for (int i = 0; i < numberOfDigits; i++) { countLeft[i] = new uint[numberOfBins]; } if (bitsPerComponent == 8) { var union = new UInt32ByteUnion(); for (int current = l; current <= r; current++) // Scan the array and count the number of times each digit value appears - i.e. size of each bin { union.integer = inArray[current]; countLeft[0][union.byte0]++; countLeft[1][union.byte1]++; countLeft[2][union.byte2]++; countLeft[3][union.byte3]++; } } else if (bitsPerComponent == 9) { for (int current = l; current <= r; current++) { uint value = inArray[current]; countLeft[0][value & 0x1ff]++; countLeft[1][(value & 0x3fe00) >> 9]++; countLeft[2][(value & 0x7fc0000) >> 18]++; countLeft[3][(value & 0xf8000000) >> 27]++; } } else if (bitsPerComponent == 10) { for (int current = l; current <= r; current++) { uint value = inArray[current]; countLeft[0][value & 0x3ff]++; countLeft[1][(value & 0xffc00) >> 10]++; countLeft[2][(value & 0x3ff00000) >> 20]++; countLeft[3][(value & 0xc0000000) >> 30]++; } } else if (bitsPerComponent == 11) { for (int current = l; current <= r; current++) { uint value = inArray[current]; countLeft[0][value & 0x7ff]++; countLeft[1][(value & 0x3ff800) >> 11]++; countLeft[2][(value & 0xffc00000) >> 22]++; } } else if (bitsPerComponent == 12) { for (int current = l; current <= r; current++) { uint value = inArray[current]; countLeft[0][value & 0xfff]++; countLeft[1][(value & 0xfff000) >> 12]++; countLeft[2][(value & 0xff000000) >> 24]++; } } else if (bitsPerComponent == 13) { for (int current = l; current <= r; current++) { uint value = inArray[current]; countLeft[0][value & 0x1fff]++; countLeft[1][(value & 0x3ffe000) >> 13]++; countLeft[2][(value & 0xfc000000) >> 26]++; } } else if (bitsPerComponent == 16) { var union = new UInt32UShortUnion(); for (int current = l; current <= r; current++) { union.integer = inArray[current]; countLeft[0][union.ushort0]++; countLeft[1][union.ushort1]++; } } else { uint componentMask = (uint)numberOfBins - 1; for (int current = l; current <= r; current++) { uint value = inArray[current]; for (int i = 0; i < numberOfDigits; i++) { countLeft[i][value & componentMask]++; componentMask <<= bitsPerComponent; } } } return(countLeft); }
/// <summary> /// Sort an array of unsigned integers using Radix Sorting algorithm (least significant digit variation) /// </summary> /// <param name="inputArray"></param> /// <returns>array of unsigned integers</returns> public static uint[] SortRadixPar(this uint[] inputArray) { int numberOfBins = 256; int numberOfDigits = 4; int Log2ofPowerOfTwoRadix = 8; int d = 0; uint[] outputArray = new uint[inputArray.Length]; uint[][] count = new uint[numberOfDigits][]; for (int i = 0; i < numberOfDigits; i++) { count[i] = new uint[numberOfBins]; } uint[][] startOfBin = new uint[numberOfDigits][]; for (int i = 0; i < numberOfDigits; i++) { startOfBin[i] = new uint[numberOfBins]; } bool outputArrayHasResult = false; uint bitMask = 255; int shiftRightAmount = 0; //Stopwatch stopwatch = new Stopwatch(); //long frequency = Stopwatch.Frequency; ////Console.WriteLine(" Timer frequency in ticks per second = {0}", frequency); //long nanosecPerTick = (1000L * 1000L * 1000L) / frequency; //stopwatch.Restart(); #if false var digits = new byte[4]; UInt32ByteUnion union = new UInt32ByteUnion(); for (uint current = 0; current < inputArray.Length; current++) // Scan the array and count the number of times each digit value appears - i.e. size of each bin { union.integer = inputArray[current]; count[0][union.byte0]++; count[1][union.byte1]++; count[2][union.byte2]++; count[3][union.byte3]++; } #else count = ByteCountInner(inputArray, 0, inputArray.Length - 1, numberOfDigits, numberOfBins); #endif //stopwatch.Stop(); //double timeForCounting = stopwatch.ElapsedTicks * nanosecPerTick / 1000000000.0; //Console.WriteLine("Time for counting: {0}", timeForCounting); for (d = 0; d < numberOfDigits; d++) { startOfBin[d][0] = 0; for (uint i = 1; i < numberOfBins; i++) { startOfBin[d][i] = startOfBin[d][i - 1] + count[d][i - 1]; } } d = 0; while (bitMask != 0) // end processing digits when all the mask bits have been processed and shifted out, leaving no bits set in the bitMask { //stopwatch.Restart(); uint[] startOfBinLoc = startOfBin[d]; for (uint current = 0; current < inputArray.Length; current++) { //outputArray[startOfBinLoc[ExtractDigit(inputArray[current], bitMask, shiftRightAmount)]++] = inputArray[current]; outputArray[startOfBinLoc[(inputArray[current] & bitMask) >> shiftRightAmount]++] = inputArray[current]; } //stopwatch.Stop(); //double timeForPermuting = stopwatch.ElapsedTicks * nanosecPerTick / 1000000000.0; //Console.WriteLine("Time for permuting: {0}", timeForPermuting); bitMask <<= Log2ofPowerOfTwoRadix; shiftRightAmount += Log2ofPowerOfTwoRadix; outputArrayHasResult = !outputArrayHasResult; d++; uint[] tmp = inputArray; // swap input and output arrays inputArray = outputArray; outputArray = tmp; } if (outputArrayHasResult) { for (uint current = 0; current < inputArray.Length; current++) // copy from output array into the input array { inputArray[current] = outputArray[current]; } } return(inputArray); }