SAF
Loading...
Searching...
No Matches
saf_utility_sort.c
Go to the documentation of this file.
1/*
2 * Copyright 2016-2018 Leo McCormack
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
27#include "saf_utilities.h"
28
30typedef struct saf_sort_int {
31 int val;
32 int idx;
35
37typedef struct saf_sort_float {
38 float val;
39 int idx;
42
44typedef struct saf_sort_double {
45 double val;
46 int idx;
49
54static int cmp_asc_int(const void *a,const void *b) {
55 struct saf_sort_int *a1 = (struct saf_sort_int*)a;
56 struct saf_sort_int *a2 = (struct saf_sort_int*)b;
57 if((*a1).val<(*a2).val)return -1;
58 else if((*a1).val>(*a2).val)return 1;
59 else return 0;
60}
61
66static int cmp_desc_int(const void *a,const void *b) {
67 struct saf_sort_int *a1 = (struct saf_sort_int*)a;
68 struct saf_sort_int *a2 = (struct saf_sort_int*)b;
69 if((*a1).val>(*a2).val)return -1;
70 else if((*a1).val<(*a2).val)return 1;
71 else return 0;
72}
73
78static int cmp_asc_float(const void *a,const void *b) {
79 struct saf_sort_float *a1 = (struct saf_sort_float*)a;
80 struct saf_sort_float *a2 = (struct saf_sort_float*)b;
81 if((*a1).val<(*a2).val)return -1;
82 else if((*a1).val>(*a2).val)return 1;
83 else return 0;
84}
85
90static int cmp_desc_float(const void *a,const void *b) {
91 struct saf_sort_float *a1 = (struct saf_sort_float*)a;
92 struct saf_sort_float *a2 = (struct saf_sort_float*)b;
93 if((*a1).val>(*a2).val)return -1;
94 else if((*a1).val<(*a2).val)return 1;
95 else return 0;
96}
97
102static int cmp_asc_double(const void *a,const void *b) {
103 struct saf_sort_double *a1 = (struct saf_sort_double*)a;
104 struct saf_sort_double *a2 = (struct saf_sort_double*)b;
105 if((*a1).val<(*a2).val)return -1;
106 else if((*a1).val>(*a2).val)return 1;
107 else return 0;
108}
109
114static int cmp_desc_double(const void *a,const void *b) {
115 struct saf_sort_double *a1 = (struct saf_sort_double*)a;
116 struct saf_sort_double *a2 = (struct saf_sort_double*)b;
117 if((*a1).val>(*a2).val)return -1;
118 else if((*a1).val<(*a2).val)return 1;
119 else return 0;
120}
121
123(
124 int* in_vec,
125 int* out_vec,
126 int* new_idices,
127 int len,
128 int descendFLAG
129)
130{
131 int i;
132 struct saf_sort_int *data;
133
134 data = malloc1d(len*sizeof(saf_sort_int));
135 for(i=0;i<len;i++) {
136 data[i].val=in_vec[i];
137 data[i].idx=i;
138 }
139 if(descendFLAG)
140 qsort(data,len,sizeof(data[0]),cmp_desc_int);
141 else
142 qsort(data,len,sizeof(data[0]),cmp_asc_int);
143 for(i=0;i<len;i++){
144 if (out_vec!=NULL)
145 out_vec[i] = data[i].val;
146 if(new_idices!=NULL)
147 new_idices[i] = data[i].idx;
148 }
149 free(data);
150}
151
153(
154 float* in_vec,
155 float* out_vec,
156 int* new_idices,
157 int len,
158 int descendFLAG
159)
160{
161 int i;
162 struct saf_sort_float *data;
163
164 data = malloc1d(len*sizeof(saf_sort_float));
165 for(i=0;i<len;i++) {
166 data[i].val=in_vec[i];
167 data[i].idx=i;
168 }
169 if(descendFLAG)
170 qsort(data,len,sizeof(saf_sort_float),cmp_desc_float);
171 else
172 qsort(data,len,sizeof(saf_sort_float),cmp_asc_float);
173 for(i=0;i<len;i++){
174 if (out_vec!=NULL)
175 out_vec[i] = data[i].val;
176 if(new_idices!=NULL)
177 new_idices[i] = data[i].idx;
178 }
179 free(data);
180}
181
183(
184 double* in_vec,
185 double* out_vec,
186 int* new_idices,
187 int len,
188 int descendFLAG
189)
190{
191 int i;
192 struct saf_sort_double *data;
193
194 data = malloc1d(len*sizeof(saf_sort_double));
195 for(i=0;i<len;i++) {
196 data[i].val=in_vec[i];
197 data[i].idx=i;
198 }
199 if(descendFLAG)
200 qsort(data,len,sizeof(data[0]),cmp_desc_double);
201 else
202 qsort(data,len,sizeof(data[0]),cmp_asc_double);
203 for(i=0;i<len;i++){
204 if (out_vec!=NULL)
205 out_vec[i] = data[i].val;
206 if(new_idices!=NULL)
207 new_idices[i] = data[i].idx;
208 }
209 free(data);
210}
211
213(
214 float_complex* in_vec,
215 float_complex* out_vec,
216 int len,
217 int descendFLAG
218)
219{
220 int i, start_idx, end_idx, sFlag, eFlag;
221 int* ind;
222 const float tol = 0.0001f;
223 float* vec_real, *vec_imag;
224
225 ind = malloc1d(len*sizeof(int));
226
227 /* First sort in_vec based on its real part */
228 vec_real = malloc1d(len*sizeof(float));
229 vec_imag = malloc1d(len*sizeof(float));
230 for(i=0; i<len; i++)
231 vec_real[i] = crealf(in_vec[i]);
232 sortf(vec_real, vec_real, ind, len, descendFLAG); /* real parts sorted based on the real parts */
233 for(i=0; i<len; i++)
234 vec_imag[i] = cimagf(in_vec[ind[i]]); /* imaginary parts sorted based on the real parts */
235
236 /* Then take the values of in_vec that have identical real parts (given some
237 * tolerance), and sort them based on their imaginary parts */
238 sFlag = eFlag = 0;
239 start_idx = end_idx = -1;
240 for(i=0; i<len-1; i++){
241 /* Find duplicate real values (given some tolerance) */
242 if(fabsf(vec_real[i]-vec_real[i+1])<tol){
243 if(!sFlag){
244 start_idx = i;
245 sFlag = 1;
246 }
247 }
248 else if (sFlag){
249 end_idx = i;
250 eFlag = 1;
251 }
252
253 /* Special case for last one */
254 if(sFlag && i==len-2){
255 end_idx = len-1;
256 eFlag = 1;
257 }
258
259 /* Sort imaginary parts */
260 if( (sFlag) && (eFlag) ){
261 sortf(&vec_imag[start_idx], &vec_imag[start_idx], NULL, end_idx-start_idx+1, descendFLAG);
262 sFlag = 0; eFlag = 0;
263 }
264 }
265
266 /* output */
267 for(i=0; i<len; i++)
268 out_vec[i] = cmplxf(vec_real[i], vec_imag[i]);
269
270 /* clean-up */
271 free(ind);
272 free(vec_real);
273 free(vec_imag);
274}
275
277(
278 double_complex* in_vec,
279 double_complex* out_vec,
280 int len,
281 int descendFLAG
282)
283{
284 int i, start_idx, end_idx, sFlag, eFlag;
285 int* ind;
286 const double tol = 0.00001;
287 double* vec_real, *vec_imag;
288
289 ind = malloc1d(len*sizeof(int));
290
291 /* First sort in_vec based on its real part */
292 vec_real = malloc1d(len*sizeof(double));
293 vec_imag = malloc1d(len*sizeof(double));
294 for(i=0; i<len; i++)
295 vec_real[i] = creal(in_vec[i]);
296 sortd(vec_real, vec_real, ind, len, descendFLAG); /* real parts sorted based on the real parts */
297 for(i=0; i<len; i++)
298 vec_imag[i] = cimag(in_vec[ind[i]]); /* imaginary parts sorted based on the real parts */
299
300 /* Then take the values of in_vec that have identical real parts (given some
301 * tolerance), and sort them based on their imaginary parts */
302 sFlag = eFlag = 0;
303 start_idx = end_idx = -1;
304 for(i=0; i<len-1; i++){
305 /* Find duplicate real values (given some tolerance) */
306 if(fabs(vec_real[i]-vec_real[i+1])<tol){
307 if(!sFlag){
308 start_idx = i;
309 sFlag = 1;
310 }
311 }
312 else if (sFlag){
313 end_idx = i;
314 eFlag = 1;
315 }
316
317 /* Special case for last one */
318 if(sFlag && i==len-2){
319 end_idx = len-1;
320 eFlag = 1;
321 }
322
323 /* Sort imaginary parts */
324 if( (sFlag) && (eFlag) ){
325 sortd(&vec_imag[start_idx], &vec_imag[start_idx], NULL, end_idx-start_idx+1, descendFLAG);
326 sFlag = 0; eFlag = 0;
327 }
328 }
329
330 /* output */
331 for(i=0; i<len; i++)
332 out_vec[i] = cmplx(vec_real[i], vec_imag[i]);
333
334 /* clean-up */
335 free(ind);
336 free(vec_real);
337 free(vec_imag);
338}
339
341(
342 double_complex* in_vec,
343 double_complex* out_vec,
344 int len
345)
346{
347 int i, realCount;
348 double_complex tmp;
349
350 /* First sort input vector in ascending order. The complex conjugate pairs
351 * are now in the correct order. */
352 sortz(in_vec, out_vec, len, 0);
353
354 /* Now identify any purely real values, and push them to the end of the
355 * vector */
356 realCount = 0;
357 for(i=0; i<len-1-realCount; i++){
358 if(fabs(cimag(out_vec[i])) < 0.00001 ){
359 tmp = out_vec[i];
360 /* Push this value to the end */
361 memmove(&out_vec[i], &out_vec[i+1], (len-i-1)*sizeof(double_complex));
362 out_vec[len-1] = tmp;
363 realCount++;
364 }
365 }
366}
367
369(
370 float* grid_dirs,
371 int nGrid,
372 float* target_dirs,
373 int nTarget,
374 int degFLAG,
375 int* idx_closest,
376 float* dirs_closest,
377 float* angle_diff
378)
379{
380 int i, j;
381 float* grid_xyz, *target_xyz;
382 float rcoselev, max_val, current_val;
383
384 /* convert sph coords into Cartesian coords */
385 grid_xyz = malloc1d(nGrid*3*sizeof(float));
386 target_xyz = malloc1d(nTarget*3*sizeof(float));
387 if(degFLAG){
388 for(i=0; i<nGrid; i++){
389 grid_xyz[i*3+2] = sinf(grid_dirs[i*2+1]* SAF_PI/180.0f);
390 rcoselev = cosf( grid_dirs[i*2+1]* SAF_PI/180.0f);
391 grid_xyz[i*3] = rcoselev * cosf(grid_dirs[i*2]* SAF_PI/180.0f);
392 grid_xyz[i*3+1] = rcoselev * sinf(grid_dirs[i*2]* SAF_PI/180.0f);
393 }
394 for(i=0; i<nTarget; i++){
395 target_xyz[i*3+2] = sinf(target_dirs[i*2+1]* SAF_PI/180.0f);
396 rcoselev = cosf(target_dirs[i*2+1]* SAF_PI/180.0f);
397 target_xyz[i*3] = rcoselev * cosf(target_dirs[i*2]* SAF_PI/180.0f);
398 target_xyz[i*3+1] = rcoselev * sinf(target_dirs[i*2]* SAF_PI/180.0f);
399 }
400 }
401 else{
402 for(i=0; i<nGrid; i++){
403 grid_xyz[i*3+2] = sinf(grid_dirs[i*2+1]);
404 rcoselev = cosf(grid_dirs[i*2+1]);
405 grid_xyz[i*3] = rcoselev * cosf(grid_dirs[i*2]);
406 grid_xyz[i*3+1] = rcoselev * sinf(grid_dirs[i*2]);
407 }
408 for(i=0; i<nTarget; i++){
409 target_xyz[i*3+2] = sinf(target_dirs[i*2+1]);
410 rcoselev = cosf(target_dirs[i*2+1]);
411 target_xyz[i*3] = rcoselev * cosf(target_dirs[i*2]);
412 target_xyz[i*3+1] = rcoselev * sinf(target_dirs[i*2]);
413 }
414 }
415
416 /* determine which 'grid_dirs' indices are the closest to 'target_dirs' */
417 for(i=0; i<nTarget; i++){
418 max_val = -2.23e10f;
419 for(j=0; j<nGrid; j++){
420 current_val = grid_xyz[j*3] * target_xyz[i*3] +
421 grid_xyz[j*3+1] * target_xyz[i*3+1] +
422 grid_xyz[j*3+2] * target_xyz[i*3+2];
423 if(current_val > max_val)
424 idx_closest[i] = j;
425 if(current_val>max_val){
426 idx_closest[i] = j;
427 max_val = current_val;
428 if(angle_diff!=NULL)
429 angle_diff[i] = acosf(max_val);
430 }
431 }
432 }
433
434 /* optional output of directions */
435 if(dirs_closest!=NULL){
436 for(i=0; i<nTarget; i++){
437 dirs_closest[i*2] = grid_dirs[idx_closest[i]*2];
438 dirs_closest[i*2+1] = grid_dirs[idx_closest[i]*2+1];
439 }
440 }
441
442 free(grid_xyz);
443 free(target_xyz);
444}
445
447(
448 float* grid_dirs_xyz,
449 int nGrid,
450 float* target_dirs_xyz,
451 int nTarget,
452 int* idx_closest,
453 float* dirs_xyz_closest,
454 float* angle_diff
455)
456{
457 int i, j;
458 float max_val, current_val;
459
460 /* determine which 'grid_xyz_dirs' indices are the closest to 'target_xyz_dirs' */
461 for(i=0; i<nTarget; i++){
462 max_val = -2.23e10f;
463 for(j=0; j<nGrid; j++){
464 current_val = grid_dirs_xyz[j*3] * target_dirs_xyz[i*3] +
465 grid_dirs_xyz[j*3+1] * target_dirs_xyz[i*3+1] +
466 grid_dirs_xyz[j*3+2] * target_dirs_xyz[i*3+2];
467 if(current_val > max_val)
468 idx_closest[i] = j;
469 if(current_val>max_val){
470 idx_closest[i] = j;
471 max_val = current_val;
472 if(angle_diff!=NULL)
473 angle_diff[i] = acosf(max_val);
474 }
475 }
476 }
477
478 /* optional output of directions */
479 if(dirs_xyz_closest!=NULL){
480 for(i=0; i<nTarget; i++){
481 dirs_xyz_closest[i*3] = grid_dirs_xyz[idx_closest[i]*3];
482 dirs_xyz_closest[i*3+1] = grid_dirs_xyz[idx_closest[i]*3+1];
483 dirs_xyz_closest[i*3+2] = grid_dirs_xyz[idx_closest[i]*3+2];
484 }
485 }
486}
#define SAF_PI
pi constant (single precision)
void sortf(float *in_vec, float *out_vec, int *new_idices, int len, int descendFLAG)
Sort a vector of floating-point values into ascending/decending order (optionally returning the new i...
void cmplxPairUp(double_complex *in_vec, double_complex *out_vec, int len)
Pairs up complex numbers and sorts them in ascending order based on their real parts first,...
void sortd(double *in_vec, double *out_vec, int *new_idices, int len, int descendFLAG)
Sort a vector of double floating-point values into ascending/decending order (optionally returning th...
void sortc(float_complex *in_vec, float_complex *out_vec, int len, int descendFLAG)
Sort a vector of complex floating-point values into ascending/decending order.
void sortz(double_complex *in_vec, double_complex *out_vec, int len, int descendFLAG)
Sort a vector of complex double floating-point values into ascending/ decending order.
void sorti(int *in_vec, int *out_vec, int *new_idices, int len, int descendFLAG)
Sort a vector of integer values into ascending/decending order (optionally returning the new indices ...
void findClosestGridPointsCartesian(float *grid_dirs_xyz, int nGrid, float *target_dirs_xyz, int nTarget, int *idx_closest, float *dirs_xyz_closest, float *angle_diff)
Finds indicies into "grid_dirs_xyz" that are the closest to "target dirs_xyz".
void findClosestGridPoints(float *grid_dirs, int nGrid, float *target_dirs, int nTarget, int degFLAG, int *idx_closest, float *dirs_closest, float *angle_diff)
Finds indicies into "grid_dirs" that are the closest to "target dirs".
void * malloc1d(size_t dim1_data_size)
1-D malloc (same as malloc, but with error checking)
Definition md_malloc.c:59
Main header for the utilities module (SAF_UTILITIES_MODULE)
static int cmp_desc_float(const void *a, const void *b)
Helper function for a sorting vector of floats using 'qsort' in decending order.
static int cmp_asc_int(const void *a, const void *b)
Helper function for sorting a vector of integers using 'qsort' in ascending order.
static int cmp_desc_int(const void *a, const void *b)
Helper function for a sorting vector of integers using 'qsort' in decending order.
static int cmp_asc_double(const void *a, const void *b)
Helper function for a sorting vector of doubles using 'qsort' in ascending order.
static int cmp_desc_double(const void *a, const void *b)
Helper function for a sorting vector of doubles using 'qsort' in decending order.
static int cmp_asc_float(const void *a, const void *b)
Helper function for a sorting vector of floats using 'qsort' in ascending order.
Helper struct for sorting a vector of doubles using 'qsort'.
int idx
corresponding index, so that the sorting functions may also return the sorted indexes if required
Helper struct for sorting a vector of floats using 'qsort'.
int idx
corresponding index, so that the sorting functions may also return the sorted indexes if required
Helper struct for sorting a vector of integers using 'qsort'.
int idx
corresponding index, so that the sorting functions may also return the sorted indexes if required