//\r
// Math Services\r
//\r
+/**\r
+ Prototype for comparison function for any two element types.\r
+\r
+ @param[in] Buffer1 The pointer to first buffer.\r
+ @param[in] Buffer2 The pointer to second buffer.\r
+\r
+ @retval 0 Buffer1 equal to Buffer2.\r
+ @return <0 Buffer1 is less than Buffer2.\r
+ @return >0 Buffer1 is greater than Buffer2.\r
+**/\r
+typedef\r
+INTN\r
+(EFIAPI *BASE_SORT_COMPARE)(\r
+ IN CONST VOID *Buffer1,\r
+ IN CONST VOID *Buffer2\r
+ );\r
+\r
+/**\r
+ This function is identical to perform QuickSort,\r
+ except that is uses the pre-allocated buffer so the in place sorting does not need to\r
+ allocate and free buffers constantly.\r
+\r
+ Each element must be equal sized.\r
+\r
+ if BufferToSort is NULL, then ASSERT.\r
+ if CompareFunction is NULL, then ASSERT.\r
+ if BufferOneElement is NULL, then ASSERT.\r
+ if ElementSize is < 1, then ASSERT.\r
+\r
+ if Count is < 2 then perform no action.\r
+\r
+ @param[in, out] BufferToSort on call a Buffer of (possibly sorted) elements\r
+ on return a buffer of sorted elements\r
+ @param[in] Count the number of elements in the buffer to sort\r
+ @param[in] ElementSize Size of an element in bytes\r
+ @param[in] CompareFunction The function to call to perform the comparison\r
+ of any 2 elements\r
+ @param[out] BufferOneElement Caller provided buffer whose size equals to ElementSize.\r
+ It's used by QuickSort() for swapping in sorting.\r
+**/\r
+VOID\r
+EFIAPI\r
+QuickSort (\r
+ IN OUT VOID *BufferToSort,\r
+ IN CONST UINTN Count,\r
+ IN CONST UINTN ElementSize,\r
+ IN BASE_SORT_COMPARE CompareFunction,\r
+ OUT VOID *BufferOneElement\r
+ );\r
\r
/**\r
Shifts a 64-bit integer left between 0 and 63 bits. The low bits are filled\r
--- /dev/null
+/** @file\r
+ Math worker functions.\r
+\r
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "BaseLibInternals.h"\r
+\r
+/**\r
+ This function is identical to perform QuickSort,\r
+ except that is uses the pre-allocated buffer so the in place sorting does not need to\r
+ allocate and free buffers constantly.\r
+\r
+ Each element must be equal sized.\r
+\r
+ if BufferToSort is NULL, then ASSERT.\r
+ if CompareFunction is NULL, then ASSERT.\r
+ if BufferOneElement is NULL, then ASSERT.\r
+ if ElementSize is < 1, then ASSERT.\r
+\r
+ if Count is < 2 then perform no action.\r
+\r
+ @param[in, out] BufferToSort on call a Buffer of (possibly sorted) elements\r
+ on return a buffer of sorted elements\r
+ @param[in] Count the number of elements in the buffer to sort\r
+ @param[in] ElementSize Size of an element in bytes\r
+ @param[in] CompareFunction The function to call to perform the comparison\r
+ of any 2 elements\r
+ @param[out] BufferOneElement Caller provided buffer whose size equals to ElementSize.\r
+ It's used by QuickSort() for swapping in sorting.\r
+**/\r
+VOID\r
+EFIAPI\r
+QuickSort (\r
+ IN OUT VOID *BufferToSort,\r
+ IN CONST UINTN Count,\r
+ IN CONST UINTN ElementSize,\r
+ IN BASE_SORT_COMPARE CompareFunction,\r
+ OUT VOID *BufferOneElement\r
+ )\r
+{\r
+ VOID *Pivot;\r
+ UINTN LoopCount;\r
+ UINTN NextSwapLocation;\r
+\r
+ ASSERT (BufferToSort != NULL);\r
+ ASSERT (CompareFunction != NULL);\r
+ ASSERT (BufferOneElement != NULL);\r
+ ASSERT (ElementSize >= 1);\r
+\r
+ if (Count < 2) {\r
+ return;\r
+ }\r
+\r
+ NextSwapLocation = 0;\r
+\r
+ //\r
+ // pick a pivot (we choose last element)\r
+ //\r
+ Pivot = ((UINT8*) BufferToSort + ((Count - 1) * ElementSize));\r
+\r
+ //\r
+ // Now get the pivot such that all on "left" are below it\r
+ // and everything "right" are above it\r
+ //\r
+ for (LoopCount = 0; LoopCount < Count -1; LoopCount++) {\r
+ //\r
+ // if the element is less than or equal to the pivot\r
+ //\r
+ if (CompareFunction ((VOID*) ((UINT8*) BufferToSort + ((LoopCount) * ElementSize)), Pivot) <= 0){\r
+ //\r
+ // swap\r
+ //\r
+ CopyMem (BufferOneElement, (UINT8*) BufferToSort + (NextSwapLocation * ElementSize), ElementSize);\r
+ CopyMem ((UINT8*) BufferToSort + (NextSwapLocation * ElementSize), (UINT8*) BufferToSort + ((LoopCount) * ElementSize), ElementSize);\r
+ CopyMem ((UINT8*) BufferToSort + ((LoopCount)*ElementSize), BufferOneElement, ElementSize);\r
+\r
+ //\r
+ // increment NextSwapLocation\r
+ //\r
+ NextSwapLocation++;\r
+ }\r
+ }\r
+ //\r
+ // swap pivot to it's final position (NextSwapLocation)\r
+ //\r
+ CopyMem (BufferOneElement, Pivot, ElementSize);\r
+ CopyMem (Pivot, (UINT8*) BufferToSort + (NextSwapLocation * ElementSize), ElementSize);\r
+ CopyMem ((UINT8*) BufferToSort + (NextSwapLocation * ElementSize), BufferOneElement, ElementSize);\r
+\r
+ //\r
+ // Now recurse on 2 partial lists. neither of these will have the 'pivot' element\r
+ // IE list is sorted left half, pivot element, sorted right half...\r
+ //\r
+ if (NextSwapLocation >= 2) {\r
+ QuickSort (\r
+ BufferToSort,\r
+ NextSwapLocation,\r
+ ElementSize,\r
+ CompareFunction,\r
+ BufferOneElement\r
+ );\r
+ }\r
+\r
+ if ((Count - NextSwapLocation - 1) >= 2) {\r
+ QuickSort (\r
+ (UINT8 *)BufferToSort + (NextSwapLocation + 1) * ElementSize,\r
+ Count - NextSwapLocation - 1,\r
+ ElementSize,\r
+ CompareFunction,\r
+ BufferOneElement\r
+ );\r
+ }\r
+}\r