Signed-off-by: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com --- src/include/sof/math/numbers.h | 23 ++++++++++ src/math/numbers.c | 96 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+)
diff --git a/src/include/sof/math/numbers.h b/src/include/sof/math/numbers.h index 927d39c..7b57d13 100644 --- a/src/include/sof/math/numbers.h +++ b/src/include/sof/math/numbers.h @@ -33,6 +33,29 @@ #ifndef NUMBERS_H #define NUMBERS_H
+#include <stdint.h> + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + int gcd(int a, int b); /* Calculate greatest common divisor for a and b */
+/* Divide function that returns ceil() of quotient */ +int ceil_divide(int a, int b); + +/* Find indices of equal values in a vector of integer values */ +int find_equal_int16(int16_t idx[], int16_t vec[], int n, int vec_length, + int max_results); + +/* Return the smallest value found in a vector */ +int16_t find_min_int16(int16_t vec[], int vec_length); + +/* Return the largest absolute value found in a vector */ +int32_t find_max_abs_int32(int32_t vec[], int vec_length); + +/* Count the left shift amount to normalize a 32 bit signed integer value + * without causing overflow. Input value 0 will result to 31. + */ +int norm_int32(int32_t val); + #endif /* NUMBERS_H */ diff --git a/src/math/numbers.c b/src/math/numbers.c index d7a1717..7e39ac8 100644 --- a/src/math/numbers.c +++ b/src/math/numbers.c @@ -36,6 +36,7 @@ */
#include <sof/math/numbers.h> +#include <sof/audio/format.h>
int gcd(int a, int b) { @@ -47,3 +48,98 @@ int gcd(int a, int b) } return a; } + +/* This is a divide function that returns ceil of the quotient. + * E.g. ceil_divide(9, 3) returns 3, ceil_divide(10, 3) returns 4. + */ +int ceil_divide(int a, int b) +{ + int c; + + c = a / b; + if (c * b < a) + c++; + + return c; +} + +/* This function searches from vec[] (of length vec_length) integer values + * of n. The indexes to equal values is returned in idx[]. The function + * returns the number of found matches. The max_results should be set to + * 0 (or negative) or vec_length get all the matches. The max_result can be set + * to 1 to receive only the first match in ascending order. It avoids need + * for an array for idx. + */ +int find_equal_int16(int16_t idx[], int16_t vec[], int n, int vec_length, + int max_results) +{ + int nresults = 0; + int i; + + for (i = 0; i < vec_length; i++) { + if (vec[i] == n) { + idx[nresults++] = i; + if (nresults == max_results) + break; + } + } + + return nresults; +} + +/* Return the smallest value found in the vector */ +int16_t find_min_int16(int16_t vec[], int vec_length) +{ + int i; + int min = vec[0]; + + for (i = 1; i < vec_length; i++) + min = (vec[i] < min) ? vec[i] : min; + + return min; +} + +/* Return the largest absolute value found in the vector. Note that + * smallest negative value need to be saturated to preset as int32_t. + */ +int32_t find_max_abs_int32(int32_t vec[], int vec_length) +{ + int i; + int64_t amax = (vec[0] > 0) ? vec[0] : -vec[0]; + + for (i = 1; i < vec_length; i++) { + amax = (vec[i] > amax) ? vec[i] : amax; + amax = (-vec[i] > amax) ? -vec[i] : amax; + } + + return SATP_INT32(amax); /* Amax is always a positive value */ +} + +/* Count the left shift amount to normalize a 32 bit signed integer value + * without causing overflow. Input value 0 will result to 31. + */ +int norm_int32(int32_t val) +{ + int s; + int32_t n; + + if (!val) + return 31; + + if (val > 0) { + n = val << 1; + s = 0; + while (n > 0) { + n = n << 1; + s++; + } + } else { + n = val << 1; + s = 0; + while (n < 0) { + n = n << 1; + s++; + } + } + return s; +}