1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        arm_quick_sort_f32.c
4  * Description:  Floating point quick sort
5  *
6  * $Date:        23 April 2021
7  * $Revision:    V1.9.0
8  *
9  * Target Processor: Cortex-M and Cortex-A cores
10  * -------------------------------------------------------------------- */
11 /*
12  * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
13  *
14  * SPDX-License-Identifier: Apache-2.0
15  *
16  * Licensed under the Apache License, Version 2.0 (the License); you may
17  * not use this file except in compliance with the License.
18  * You may obtain a copy of the License at
19  *
20  * www.apache.org/licenses/LICENSE-2.0
21  *
22  * Unless required by applicable law or agreed to in writing, software
23  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
24  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25  * See the License for the specific language governing permissions and
26  * limitations under the License.
27  */
28 
29 #include "arm_sorting.h"
30 
arm_quick_sort_partition_f32(float32_t * pSrc,int32_t first,int32_t last,uint8_t dir)31 static uint32_t arm_quick_sort_partition_f32(float32_t *pSrc, int32_t first, int32_t last, uint8_t dir)
32 {
33     /* This function will be called */
34     int32_t i, j, pivot_index;
35     float32_t pivot;
36     float32_t temp;
37 
38     /* The first element is the pivot */
39     pivot_index = first;
40     pivot = pSrc[pivot_index];
41 
42     /* Initialize indices for do-while loops */
43     i = first - 1;
44     j = last + 1;
45 
46     while(i < j)
47     {
48         /* The loop will stop as soon as the indices i and j cross each other.
49          *
50          * This event will happen surely since the values of the indices are incremented and
51          * decrement in the do-while loops that are executed at least once.
52          * It is impossible to loop forever inside the do-while loops since the pivot is
53          * always an element of the array and the conditions cannot be always true (at least
54          * the i-th or the j-th element will be equal to the pivot-th element).
55          * For example, in the extreme case of an ordered array the do-while loop related to i will stop
56          * at the first iteration (because pSrc[i]=pSrc[pivot] already), and the loop related to j
57          * will stop after (last-first) iterations (when j=pivot=i=first). j is returned and
58          * j+1 is going to be used as pivot by other calls of the function, until j=pivot=last. */
59 
60         /* Move indices to the right and to the left */
61         if(dir)
62         {
63             /* Compare left elements with pivot */
64             do
65             {
66                 i++;
67             } while (pSrc[i] < pivot && i<last);
68 
69             /* Compare right elements with pivot */
70             do
71             {
72                 j--;
73             } while (pSrc[j] > pivot);
74         }
75         else
76         {
77             /* Compare left elements with pivot */
78             do
79             {
80                 i++;
81             } while (pSrc[i] > pivot && i<last);
82 
83             /* Compare right elements with pivot */
84             do
85             {
86                 j--;
87             } while (pSrc[j] < pivot);
88         }
89 
90         /* If the indices didn't cross each other */
91         if (i < j)
92         {
93             /* i and j are in the wrong position -> Swap */
94             temp=pSrc[i];
95             pSrc[i]=pSrc[j];
96             pSrc[j]=temp;
97         }
98     }
99 
100     return j;
101 }
102 
arm_quick_sort_core_f32(float32_t * pSrc,int32_t first,int32_t last,uint8_t dir)103 static void arm_quick_sort_core_f32(float32_t *pSrc, int32_t first, int32_t last, uint8_t dir)
104 {
105     /* If the array [first ... last] has more than one element */
106     if(first<last)
107     {
108         int32_t pivot;
109 
110         /* Compute pivot */
111         pivot = arm_quick_sort_partition_f32(pSrc, first, last, dir);
112 
113         /* Iterate algorithm with two sub-arrays [first ... pivot] and [pivot+1 ... last] */
114         arm_quick_sort_core_f32(pSrc, first,   pivot, dir);
115         arm_quick_sort_core_f32(pSrc, pivot+1, last,  dir);
116     }
117 }
118 
119 /**
120   @ingroup groupSupport
121  */
122 
123 /**
124   @addtogroup Sorting
125   @{
126  */
127 
128 /**
129    * @private
130    * @param[in]      S          points to an instance of the sorting structure.
131    * @param[in,out]  pSrc       points to the block of input data.
132    * @param[out]     pDst       points to the block of output data.
133    * @param[in]      blockSize  number of samples to process.
134    *
135    * @par        Algorithm
136    *                The quick sort algorithm is a comparison algorithm that
137    *                divides the input array into two smaller sub-arrays and
138    *                recursively sort them. An element of the array (the pivot)
139    *                is chosen, all the elements with values smaller than the
140    *                pivot are moved before the pivot, while all elements with
141    *                values greater than the pivot are moved after it (partition).
142    *
143    * @par
144    *                In this implementation the Hoare partition scheme has been
145    *                used [Hoare, C. A. R. (1 January 1962). "Quicksort". The Computer
146    *                Journal. 5 (1): 10...16.] The first element has always been chosen
147    *                as the pivot. The partition algorithm guarantees that the returned
148    *                pivot is never placed outside the vector, since it is returned only
149    *                when the pointers crossed each other. In this way it isn't
150    *                possible to obtain empty partitions and infinite recursion is avoided.
151    *
152    * @par
153    *                It's an in-place algorithm. In order to obtain an out-of-place
154    *                function, a memcpy of the source vector is performed.
155    */
156 
arm_quick_sort_f32(const arm_sort_instance_f32 * S,float32_t * pSrc,float32_t * pDst,uint32_t blockSize)157 void arm_quick_sort_f32(
158   const arm_sort_instance_f32 * S,
159         float32_t * pSrc,
160         float32_t * pDst,
161         uint32_t blockSize)
162 {
163     float32_t * pA;
164 
165     /* Out-of-place */
166     if(pSrc != pDst)
167     {
168         memcpy(pDst, pSrc, blockSize*sizeof(float32_t) );
169         pA = pDst;
170     }
171     else
172         pA = pSrc;
173 
174     arm_quick_sort_core_f32(pA, 0, blockSize-1, S->dir);
175     /* The previous function could be called recursively a maximum
176      * of (blockSize-1) times, generating a stack consumption of 4*(blockSize-1) bytes. */
177 }
178 
179 /**
180   @} end of Sorting group
181  */
182