Embedded Software – Microcontroller – Outlier Removal Average Filtering Algorithm C Program

/**

* @brief Comparison function for qsort to sort double arrays

*/

static int double_cmp(const void *a, const void *b) {

double val_a = *(const double *)a;

double val_b = *(const double *)b;

if (val_a < val_b) return -1;

if (val_a > val_b) return 1;

return 0;

}

/**

* @brief Filters NAN/INF, removes the maximum and minimum values, and calculates the average

* @param input Input array

* @param input_len Length of the input array

* @param avg_result Output: calculated average value

* @return 0: success, -1: failure (e.g., insufficient elements after filtering, invalid parameters)

*/

int calc_avg_filtered(double *input, int input_len, double *avg_result) {

// 1. Check the validity of input parameters

if (input == NULL || avg_result == NULL || input_len <= 0) {

fprintf(stderr, “Invalid input parameters\n”);

errno = EINVAL;

return -1;

}

// 2. Step one: Filter NAN and INF, store in a temporary array

double *filtered = (double *)malloc(input_len * sizeof(double));

if (filtered == NULL) {

fprintf(stderr, “Malloc failed: %m\n”);

errno = ENOMEM;

return -1;

}

int filtered_len = 0;

for (int i = 0; i < input_len; i++) {

// Filter NAN (isnan) and INF (isinf)

if (!isnan(input[i]) && !isinf(input[i])) {

filtered[filtered_len++] = input[i];

}

}

// 3. Boundary condition: insufficient elements after filtering (cannot remove max + min)

if (filtered_len < 3) {

fprintf(stderr, “Filtered elements count(%d) < 3, can’t remove max/min\n”, filtered_len);

free(filtered);

errno = EINVAL;

return -1;

}

// 4. Sort the filtered array (to easily get max/min values)

qsort(filtered, filtered_len, sizeof(double), double_cmp);

// 5. Remove the first (minimum) and last (maximum) values, calculate the sum of the remaining elements

double sum = 0.0;

int valid_len = filtered_len – 2; // Number of elements after removing max + min

for (int i = 1; i < filtered_len – 1; i++) {

sum += filtered[i];

}

// 6. Calculate the average

*avg_result = sum / valid_len;

// 7. Free resources

free(filtered);

return 0;

}

// Test main function

int main() {

// Test array (contains NAN, INF, normal values)

double test_data[] = {9.9, 9.1199, NAN, INFINITY, -INFINITY, 8.5, 10.2, 7.8, 9.0};

int data_len = sizeof(test_data) / sizeof(test_data[0]);

double avg;

// Call the calculation function

int ret = calc_avg_filtered(test_data, data_len, &avg);

if (ret == 0) {

printf(“Average after filtering NAN/INF and removing max/min: %.4f\n”, avg);

} else {

printf(“Calculation failed, error code: %d\n”, errno);

}

return 0;

}

// Compile with LINUX GCC as follows

gcc -o avg_filter avg_filter.c -lm./avg_filter

Leave a Comment