SAF
Loading...
Searching...
No Matches
saf_utility_misc.c
Go to the documentation of this file.
1/*
2 * Copyright 2020 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#include "saf_externals.h"
29
33static const long double factorials_21[21] =
34{1.0, 1.0, 2.0, 6.0, 24.0, 120.0, 720.0, 5040.0, 40320.0, 362880.0, 3628800.0, 39916800.0, 479001600.0, 6.2270208e9, 8.71782891e10, 1.307674368000000e12, 2.092278988800000e13, 3.556874280960000e14, 6.402373705728000e15, 1.216451004088320e17, 2.432902008176640e18};
35
37static void combinationUtil(int* arr, int* data, int start, int end, int index, int r, int** comb, int* nComb) {
38 if (index == r) {
39 (*nComb)++;
40 (*comb) = realloc1d( (*comb), (*nComb)*r*sizeof(int));
41 for (int j=0; j<r; j++)
42 (*comb)[((*nComb)-1)*r+j] = data[j];
43 return;
44 }
45 for (int i=start; i<=end && end-i+1 >= r-index; i++) {
46 data[index] = arr[i];
47 combinationUtil(arr, data, i+1, end, index+1, r, comb, nComb);
48 }
49}
50
52(
53 float* dirs_deg,
54 int nDirs
55)
56{
57 int i;
58 for(i=0; i<nDirs; i++){
59 if(dirs_deg[i*2]>180.0f)
60 dirs_deg[i*2] = -360.0f + dirs_deg[i*2];
61 }
62}
63
65(
66 int numsamp
67)
68{
69 int npts_max;
70
71 if (numsamp > INT_MAX)
72 return 0;
73 npts_max = 1;
74 while( 1 ){
75 npts_max *= 2;
76 if (npts_max >= numsamp)
77 return npts_max;
78 }
79}
80
82(
83 int N,
84 float* x,
85 int len_x,
86 float* weights
87)
88{
89 int k, i, l;
90
91 for(l=0; l<len_x; l++){
92 for (k=0; k<=N; k++)
93 weights[k*len_x+l] = 1.0f;
94 for (k=0; k<=N; k++){
95 for(i=0; i<=N; i++)
96 if(k!=i)
97 weights[i*len_x+l] *= ((x[l]-(float)k) / (float)(i-k));
98 }
99 }
100}
101
103(
104 float* centerFreq,
105 int nBands,
106 float maxFreqLim,
107 int** erb_idx,
108 float** erb_freqs,
109 int* nERBBands
110)
111{
112 int i, band, counter, next_erb_idx;
113 float band_centreFreq, erb, erb_centre, tmp;
114
115 saf_assert(centerFreq[nBands-1]>maxFreqLim, "maxFreqLim must be set to be lower than Nyquist...");
116
117 band_centreFreq = (powf(2.0f, 1.0f/3.0f)+1.0f)/2.0f;
118 free(*erb_idx);
119 free(*erb_freqs);
120 (*erb_idx) = malloc1d(sizeof(int));
121 (*erb_freqs) = malloc1d(sizeof(float));
122 (*erb_idx)[0] = 1;
123 (*erb_freqs)[0] = centerFreq[0];
124 counter = 0;
125 next_erb_idx = 0;
126 while((*erb_freqs)[counter]<maxFreqLim){
127 erb = 24.7f + 0.108f * (*erb_freqs)[counter] * band_centreFreq;
128 (*erb_idx) = realloc1d((*erb_idx), (counter+2)*sizeof(int));
129 (*erb_freqs) = realloc1d((*erb_freqs), (counter+2)*sizeof(float));
130 (*erb_freqs)[counter+1] = (*erb_freqs)[counter] + erb;
131 erb_centre = FLT_MAX;
132 /* find closest band frequency as upper partition limit */
133 for(band=0; band<nBands; band++){
134 tmp =fabsf((*erb_freqs)[counter+1] - centerFreq[band]);
135 if(tmp <erb_centre){
136 erb_centre = tmp;
137 next_erb_idx = band;
138 }
139 }
140 (*erb_idx)[counter+1] = next_erb_idx + 1;
141 if((*erb_idx)[counter+1] == (*erb_idx)[counter])
142 (*erb_idx)[counter+1] = (*erb_idx)[counter+1]+1;
143 (*erb_freqs)[counter+1] = centerFreq[(*erb_idx)[counter+1]-1];
144 counter++;
145 }
146 /* last limit set at last band */
147 (*erb_idx) = realloc1d((*erb_idx), (counter + 2) * sizeof(int));
148 (*erb_freqs) = realloc1d((*erb_freqs), (counter + 2) * sizeof(float));
149 (*erb_idx)[counter+1] = nBands;
150 (*erb_freqs)[counter+1] = centerFreq[nBands-1];
151 (*nERBBands) = counter+2;
152
153 /* subtract 1 from the indices (the above is a direct port from Matlab...) */
154 for(i=0; i<(*nERBBands); i++)
155 (*erb_idx)[i] = (*erb_idx)[i] - 1;
156}
157
159(
160 int len,
161 int* randperm
162)
163{
164 int i, j, tmp;
165
166 for (i = 0; i < len; i++)
167 randperm[i] = i;
168 for (i = 0; i < len; i++) {
169 j = rand() % (len-i) + i;
170 tmp = randperm[j];
171 randperm[j] = randperm[i];
172 randperm[i] = tmp;
173 }
174}
175
176long double factorial(int n)
177{
178 int i;
179 long double ff;
180 if(n<21)
181 return factorials_21[n];
182 else{
183 ff = 1.0;
184 for(i = 1; i<=n; i++)
185 ff *= (long double)i;
186 return ff;
187 }
188}
189
190float matlab_fmodf(float x, float y) {
191 float tmp = fmodf(x, y);
192 return tmp >= 0 ? tmp : tmp + y;
193}
194
196(
197 float* a,
198 float* b,
199 float* x_ab,
200 size_t la,
201 size_t lb
202)
203{
204 int m, n, negFLAG, arg, len, lim;
205
206 len = (int)(la + lb) - 1;
207 memset(x_ab, 0, len*sizeof(float));
208 for(m=1; m<=len; m++){
209 arg = m-(int)la;
210 if(arg<0){
211 negFLAG = 1;
212 lim = (int)la + arg;
213 }
214 else{
215 negFLAG = 0;
216 lim = (int)la - arg;
217 }
218 for(n=1; n<=lim; n++){
219 if(negFLAG == 0)
220 x_ab[m-1] += (a[arg+n-1] * b[n-1]);
221 else
222 x_ab[m-1] += (a[n-1] * b[n-arg-1]);
223 }
224 }
225}
226
228(
229 float* vector,
230 int length
231)
232{
233 int i;
234 for(i=0; i<length; i++)
235 vector[i] = (2.0f*rand()/(float)RAND_MAX)-1.0f;
236}
237
239(
240 float_complex* vector,
241 int length
242)
243{
244 int i;
245 for(i=0; i<length; i++)
246 vector[i] = cmplxf((2.0f*rand()/(float)RAND_MAX)-1.0f, (2.0f*rand()/(float)RAND_MAX)-1.0f);
247}
248
250(
251 float* vector,
252 int length
253)
254{
255 int i;
256 for(i=0; i<length; i++)
257 vector[i] = rand()/(float)RAND_MAX;
258}
259
261(
262 double* x,
263 double* h,
264 int len_x,
265 int len_h,
266 double* y
267)
268{
269 int i, j, h_start, x_start, x_end, len_y;
270
271 len_y = len_h+len_x-1;
272 memset(y, 0, len_y*sizeof(double));
273 for (i=0; i<len_y; i++) {
274 x_start = SAF_MAX(0,i-len_h+1);
275 x_end = SAF_MIN(i+1,len_x);
276 h_start = SAF_MIN(i,len_h-1);
277 for(j=x_start; j<x_end; j++)
278 y[i] += h[h_start--]*x[j];
279 }
280}
281
283(
284 double_complex* x,
285 double_complex* h,
286 int len_x,
287 int len_h,
288 double_complex* y
289)
290{
291 int i, j, h_start, x_start, x_end, len_y;
292
293 len_y = len_h+len_x-1;
294 memset(y, 0, len_y*sizeof(double_complex));
295 for (i=0; i<len_y; i++) {
296 x_start = SAF_MAX(0,i-len_h+1);
297 x_end = SAF_MIN(i+1,len_x);
298 h_start = SAF_MIN(i,len_h-1);
299 for(j=x_start; j<x_end; j++)
300 y[i] = ccadd(y[i], ccmul(h[h_start--], x[j]));
301 }
302}
303
305(
306 double* x,
307 double* poly,
308 int len_x
309)
310{
311 int j,i;
312
313 memset(poly, 0, (len_x+1)*sizeof(double));
314 poly[0] = 1.0;
315 for (j=0; j<len_x; j++){
316 for(i=j+1; i>0; i--){
317 poly[i] = poly[i] - x[j] * (poly[i-1]);
318 }
319 }
320}
321
323(
324 double_complex* x,
325 double_complex* poly,
326 int len_x
327)
328{
329 int j,i;
330
331 memset(poly, 0, (len_x+1)*sizeof(double_complex));
332 poly[0] = cmplx(1.0, 0.0);
333 for (j=0; j<len_x; j++){
334 for(i=j+1; i>0; i--){
335 poly[i] = ccsub(poly[i], ccmul(x[j], poly[i-1]));
336 }
337 }
338}
339
341(
342 double* X,
343 double_complex* poly,
344 int size_x
345)
346{
347 int j,i;
348 double_complex* Xcmplx, *e;
349
350 /* Characteristic polynomial */
351 Xcmplx = malloc1d(size_x*size_x*sizeof(double_complex));
352 e = malloc1d(size_x*sizeof(double_complex));
353 for(i=0; i<size_x*size_x; i++)
354 Xcmplx[i] = cmplx(X[i], 0.0);
355 utility_zeig(NULL, Xcmplx, size_x, NULL, NULL, NULL, e);
356
357 /* recursion formula */
358 memset(poly, 0, (size_x+1)*sizeof(double_complex));
359 poly[0] = cmplx(1.0, 0.0);
360 for (j=0; j<size_x; j++){
361 for(i=j+1; i>0; i--){
362 poly[i] = ccsub(poly[i], ccmul(e[j], poly[i-1]));
363 }
364 }
365
366 /* clean-up */
367 free(Xcmplx);
368 free(e);
369}
370
371float sumf
372(
373 float* values,
374 int nValues
375)
376{
377 float sum;
378#if defined(SAF_USE_INTEL_IPP)
379 ippsSum_32f((Ipp32f*)values, nValues, &sum, ippAlgHintNone);
380#else
381 int i;
382 sum = 0.0f;
383 for(i=0; i<nValues; i++)
384 sum += values[i];
385#endif
386 return sum;
387}
388
390(
391 float* values,
392 int nValues,
393 float threshold
394)
395{
396 int i;
397 for(i=0; i<nValues; i++)
398 if(values[i]<threshold)
399 return 1;
400 return 0;
401}
402
404(
405 int* input,
406 int nInputs,
407 int** uniqueVals,
408 int** uniqueInds,
409 int* nUnique
410)
411{
412 int i, j, k, nDups, foundDups, foundNewDup;
413 int* dups, *nDuplicates_perInput;
414
415 /* If only 1 input... */
416 if(nInputs == 1){
417 (*nUnique) = 1;
418 if(uniqueVals!=NULL){
419 (*uniqueVals) = malloc1d((*nUnique)*sizeof(int));
420 (*uniqueVals)[0] = input[0];
421 }
422 if(uniqueInds!=NULL){
423 (*uniqueInds) = malloc1d((*nUnique)*sizeof(int));
424 (*uniqueInds)[0] = 0;
425 }
426 }
427
428 /* prep */
429 dups = malloc1d(nInputs*sizeof(int));
430 nDuplicates_perInput = calloc1d(nInputs, sizeof(int));
431 (*nUnique) = nInputs;
432
433 /* Find duplicates */
434 nDups = 0;
435 for(i=0; i<nInputs; i++) {
436 foundDups = 0;
437 for(j=i+1; j<nInputs; j++) {
438 if(input[i] == input[j]) {
439 foundNewDup = 1;
440 for(k=0; k<nDups; k++)
441 if(input[i]==dups[k])
442 foundNewDup = 0;
443
444 /* input value is repeated: */
445 nDuplicates_perInput[i]++;
446 if(foundNewDup){
447 (*nUnique)--; /* one less unique value... */
448 foundDups = 1;
449 }
450 }
451 }
452 /* Store repeated value, so "nUnique" is not decreased more than once for it */
453 if(foundDups){
454 dups[nDups] = input[i];
455 nDups++;
456 }
457 }
458 saf_assert((*nUnique)>-1, "Something very bad happened");
459 free(dups);
460
461 /* If no unique values were found */
462 if((*nUnique)==0){
463 (*uniqueVals) = NULL;
464 (*uniqueInds) = NULL;
465 (*nUnique) = 0;
466 free(nDuplicates_perInput);
467 return;
468 }
469
470 /* Save unique values and/or their indices */
471 j=0;
472 if(uniqueVals!=NULL)
473 (*uniqueVals) = malloc1d((*nUnique)*sizeof(int));
474 if(uniqueInds!=NULL)
475 (*uniqueInds) = malloc1d((*nUnique)*sizeof(int));
476 for(i=0; i<nInputs; i++) {
477 if(nDuplicates_perInput[i] == 0) {
478 /* If no duplicate exists, append... */
479 if(uniqueVals!=NULL)
480 (*uniqueVals)[j] = input[i];
481 if(uniqueInds!=NULL)
482 (*uniqueInds)[j] = i;
483 j++;
484 }
485 }
486
487 /* clean-up */
488 free(nDuplicates_perInput);
489}
490
492(
493 int* arrValues,
494 int nValues,
495 int nElements,
496 int** comb,
497 int* nComb
498)
499{
500 int* data;
501 data = malloc1d(nElements*sizeof(int));
502 saf_assert(*comb==NULL, "comb must be empty and NULL prior to calling findCombinations()");
503 (*nComb) = 0;
504 combinationUtil(arrValues, data, 0, nValues-1, 0, nElements, comb, nComb);
505 free(data);
506}
507
508/* Based heavily on the Matlab script found here:
509 * https://se.mathworks.com/matlabcentral/fileexchange/50413-generalized-matrix-exponential
510 * Copyright (c) 2015, Kenneth Johnson (BSD-3-clause license) */
512(
513 float* D,
514 int sizeD,
515 int m1,
516 float* Y
517)
518{
519 int i, j, k;
520 float tol, s, h2, h, hh, hhh, two;
521 float** D_2, **D_3, **D_4, **D_5, **Dh, **Ym1, **Ym2;
522
523 tol = FLT_EPSILON;
524
525 /* Calculate Y = expm(D), Ym1 = Y-I.
526 *
527 * Scale and square: Y = expm(D/n)^n; n = 2^s (non-negative integer s)
528 *
529 * Pade approximation: expm(D/n) = R
530 * = (I-Dh+(2/5)*Dh^2-(1/15)*Dh^3)\‍(I+Dh+(2/5)*Dh^2+(1/15)*Dh^3)
531 * where Dh = D*h; h = 1/(2*n) (h = integration half-step)
532 *
533 * Pade approximation error: R-expm(D/n) = (-2/1575)*(Dh)^7
534 *
535 * Set Y = R^n. Approximate absolute error:
536 * Y-expm(D) = R^n-expm(D/n)^n = n*R^(n-1)*(R-expm(D/n))
537 * = n*Y*R^(-1)*(-2/1575)*(Dh)^7
538 * R^(-1) is close to I, so
539 * Y-expm(D) = n*Y*(-2/1575)*(Dh)^7 (approx)
540 *
541 * Large D (|D|>=1): Bound the relative error magnitude by tol,
542 * n*(2/1575)*|(Dh)^7| <= tol
543 *
544 * Small D (|D|<1): |Y-I| is of order 1 or less; the absolute error
545 * Y-expm(D) is of order n*(-2/1575)*(Dh)^7. Bound the error magnitude
546 * by tol*|D| to preserve relative accuracy of Ym1:
547 * n*(2/1575)*|(Dh)^7| <= tol*|D|
548 *
549 * Combine large/small Dh conditions conjunctively:
550 * n*(2/1575)*|(Dh)^7| <= tol*min(1,|D|)
551 *
552 * Substitute h = 1/(2*n):
553 * (2*n)^6 >= |D^7|/(1575*tol*min(1,|D|))
554 * Substitute n = 2^s:
555 * s >= log2(|D^7|/(1575*tol*min(1,|D|)))/6-1
556 * (Use the Frobenius norm for |...| to preserve symmetry of expm under
557 * matrix transposition.)
558 */
559 D_2 = (float**)malloc2d(sizeD, sizeD, sizeof(float));
560 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, sizeD, sizeD, sizeD, 1.0f,
561 D, sizeD,
562 D, sizeD, 0.0f,
563 FLATTEN2D(D_2), sizeD);
564 D_3 = (float**)malloc2d(sizeD, sizeD, sizeof(float));
565 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, sizeD, sizeD, sizeD, 1.0f,
566 FLATTEN2D(D_2), sizeD,
567 D, sizeD, 0.0f,
568 FLATTEN2D(D_3), sizeD);
569 D_4 = (float**)malloc2d(sizeD, sizeD, sizeof(float));
570 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, sizeD, sizeD, sizeD, 1.0f,
571 FLATTEN2D(D_3), sizeD,
572 FLATTEN2D(D_3), sizeD, 0.0f,
573 FLATTEN2D(D_4), sizeD);
574 D_5 = (float**)malloc2d(sizeD, sizeD, sizeof(float));
575 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, sizeD, sizeD, sizeD, 1.0f,
576 FLATTEN2D(D_4), sizeD,
577 D, sizeD, 0.0f,
578 FLATTEN2D(D_5), sizeD);
579 s = ceilf(log2f(Frob_norm(FLATTEN2D(D_5), sizeD, sizeD)/
580 (1575.0f*tol*SAF_MIN(1.0f,Frob_norm(D, sizeD, sizeD))))/6.0f-1.0f);
581 s = SAF_MAX(s, 0.0f);
582
583 /* Get Pade approximation for expm(D*h2) = Y =
584 * (I-Dh+(2/5)*Dh^2-(1/15)*Dh^3)\‍(I+Dh+(2/5)*Dh^2+(1/15)*Dh^3)
585 * Ym1 = Y-I =
586 * (I-Dh+(2/5)*Dh^2-(1/15)*Dh^3)\‍(2*(Dh+(1/15)*Dh^3))
587 * (Calculate Ym1, not Y, to avoid precision loss from dominant I
588 * terms when Dh is small.) */
589 h2 = powf(2.0f,-s);
590 h = h2/2.0f;
591 hh = h*h;
592 hhh = hh*h;
593 Dh = (float**)malloc2d(sizeD, sizeD, sizeof(float));
594 memcpy(FLATTEN2D(Dh), D, sizeD*sizeD*sizeof(float));
595 utility_svsmul(FLATTEN2D(Dh), &h, sizeD*sizeD, NULL);
596 utility_svsmul(FLATTEN2D(D_2), &hh, sizeD*sizeD, NULL);
597 utility_svsmul(FLATTEN2D(D_3), &hhh, sizeD*sizeD, NULL);
598 Ym1 = (float**)malloc2d(sizeD, sizeD, sizeof(float));
599 for(i=0; i<sizeD; i++)
600 for(j=0; j<sizeD; j++)
601 Ym1[i][j] = Dh[i][j] + (1.0f/15.0f)*D_3[i][j];
602 Ym2 = (float**)malloc2d(sizeD, sizeD, sizeof(float));
603 for(i=0; i<sizeD; i++){
604 for(j=0; j<sizeD; j++){
605 Ym2[i][j] = (2.0f/5.0f)*D_2[i][j]-Ym1[i][j];
606 if(i==j)
607 Ym2[i][j] += 1.0f;
608 }
609 }
610 two = 2.0f;
611 utility_svsmul(FLATTEN2D(Ym1), &two, sizeD*sizeD, NULL);
612 utility_sglslv(NULL, FLATTEN2D(Ym2), sizeD, FLATTEN2D(Ym1), sizeD, FLATTEN2D(Ym1));
613
614 /* Y = Ym1+I = expm(D)
615 * Square Y (i.e., Y <-- Y*Y) s times to get Y = expm(D*2^s). */
616 for (k = 0; k<(int)s; k++){
617 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, sizeD, sizeD, sizeD, 1.0f,
618 FLATTEN2D(Ym1), sizeD,
619 FLATTEN2D(Ym1), sizeD, 0.0f,
620 FLATTEN2D(Ym2), sizeD);
621 for(i=0; i<sizeD; i++)
622 for(j=0; j<sizeD; j++)
623 Ym1[i][j] = Ym2[i][j] + 2.0f*Ym1[i][j]; /* (Ym1+I) <-- (Ym1+I)*(Ym1+I) */
624 }
625 memcpy(Y, FLATTEN2D(Ym1), sizeD*sizeD*sizeof(float));
626 if (m1){}
627 else{
628 for(i=0; i<sizeD; i++)
629 for(j=0; j<sizeD; j++)
630 if(i==j)
631 Y[i*sizeD+j] += 1.0f;
632 }
633
634 /* clean-up */
635 free(D_2);
636 free(D_3);
637 free(D_4);
638 free(D_5);
639 free(Dh);
640 free(Ym1);
641 free(Ym2);
642}
#define saf_assert(x, message)
Macro to make an assertion, along with a string explaining its purpose.
void findCombinations(int *arrValues, int nValues, int nElements, int **comb, int *nComb)
Given an array of values, find all the possible combinations (nCr) for subgroups of "nElements"; deri...
#define SAF_MAX(a, b)
Returns the maximum of the two values.
void findERBpartitions(float *centerFreq, int nBands, float maxFreqLim, int **erb_idx, float **erb_freqs, int *nERBBands)
This function takes a frequency vector and groups its frequencies into critical bands [Equivalent-Rec...
void convert_0_360To_m180_180(float *dirs_deg, int nDirs)
Wraps around any angles exeeding 180 degrees (e.g., 200-> -160)
float matlab_fmodf(float x, float y)
C fmodf function, except it behaves like 'mod' in Matlab (i.e.
void unique_i(int *input, int nInputs, int **uniqueVals, int **uniqueInds, int *nUnique)
Finds the unique values (and their indices) of the input vector.
void cxcorr(float *a, float *b, float *x_ab, size_t la, size_t lb)
Calculates the cross correlation between two vectors.
void rand_0_1(float *vector, int length)
Generates random numbers between 0 and 1 and stores them in the input vector.
void utility_sglslv(void *const hWork, const float *A, const int dim, float *B, int nCol, float *X)
General linear solver: single precision, i.e.
void randperm(int len, int *randperm)
Returns the indices required to randomly permute a vector of length 'len'.
void rand_cmplx_m1_1(float_complex *vector, int length)
Generates random numbers between -1 and 1 and stores them in the input vector for both the real and i...
void gexpm(float *D, int sizeD, int m1, float *Y)
Numerically solves first-order, linear, homogeneous differential equation systems,...
void polyd_m(double *X, double_complex *poly, int size_x)
Convert roots of a matrix to polynomial (real double precision)
#define SAF_MIN(a, b)
Returns the minimum of the two values.
void utility_zeig(void *const hWork, const double_complex *A, const int dim, double_complex *VL, double_complex *VR, double_complex *D, double_complex *eig)
Eigenvalue decomposition of a NON-SYMMETRIC matrix: double precision complex, i.e.
long double factorial(int n)
Factorial, accurate up to n<=25.
float Frob_norm(float *M, int lenX, int lenY)
Returns the Frobenius Norm of a matrix M, of dimensions: lenX x lenY.
float sumf(float *values, int nValues)
Returns the sum of all values.
void convd(double *x, double *h, int len_x, int len_h, double *y)
Basic 1-D direct convolution in the time-domain (real double precision)
int nextpow2(int numsamp)
A simple function which returns the next power of 2.
void polyd_v(double *x, double *poly, int len_x)
Convert roots of a vector to polynomial (real double precision)
void polyz_v(double_complex *x, double_complex *poly, int len_x)
Convert roots of a vector to polynomial (complex double precision)
void lagrangeWeights(int N, float *x, int len_x, float *weights)
Computes Lagrange interpolation weights of order 'N' for value 'x'.
int anyLessThanf(float *values, int nValues, float threshold)
Returns 1, if any value in 'values' (nValues x 1) is less than 'threshold', otherwise,...
void convz(double_complex *x, double_complex *h, int len_x, int len_h, double_complex *y)
Basic 1-D direct convolution in the time-domain (complex double precision)
void utility_svsmul(float *a, const float *s, const int len, float *c)
Single-precision, multiplies each element in vector 'a' with a scalar 's', i.e.
void rand_m1_1(float *vector, int length)
Generates random numbers between -1 and 1 and stores them in the input vector.
void ** malloc2d(size_t dim1, size_t dim2, size_t data_size)
2-D malloc (contiguously allocated, so use free() as usual to deallocate)
Definition md_malloc.c:89
void * malloc1d(size_t dim1_data_size)
1-D malloc (same as malloc, but with error checking)
Definition md_malloc.c:59
void * calloc1d(size_t dim1, size_t data_size)
1-D calloc (same as calloc, but with error checking)
Definition md_malloc.c:69
void * realloc1d(void *ptr, size_t dim1_data_size)
1-D realloc (same as realloc, but with error checking)
Definition md_malloc.c:79
#define FLATTEN2D(A)
Use this macro when passing a 2-D dynamic multi-dimensional array to memset, memcpy or any other func...
Definition md_malloc.h:65
Include header for SAF externals.
static tick_t start
Start time for whole test program.
Definition saf_test.c:54
Main header for the utilities module (SAF_UTILITIES_MODULE)
static const long double factorials_21[21]
Precomputed factorials for up to !21 (i.e.
static void combinationUtil(int *arr, int *data, int start, int end, int index, int r, int **comb, int *nComb)
Helper function for findCombinations()