/**************************************************************

cholesky.c (C-Munipack project)
Copyright (C) 2003 David Motl, dmotl@volny.cz

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

**************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>

#include "filter.h"
#include "cmpack_common.h"

static int compare_fn(const void *a, const void *b)
{
	double ma = *((double*)a), mb = *((double*)b);
	return (ma < mb ? -1 : (ma > mb ? 1 : 0));
}

static double median(int length, double *data)
{
	if (length>1) {
		if (length>2) {
			if (length&1) {
				/* Odd length */
				qsort(data, length, sizeof(double), compare_fn);
				return data[length/2];
			} else {
				/* Even length */
				qsort(data, length, sizeof(double), compare_fn);
				return 0.5 * (data[(length-1)/2] + data[(length+1)/2]);
			}
		} else {
			/* Two items */
			return 0.5 * (data[0] + data[1]);
		}
	} else {
		/* One item */
		return data[0];
	}
}

int median_filter(int length, double *data, int *n)
{
	int i, j, count;
	double *buf;

	assert((length%2)==1);
	if ((*n) >= length) {
		buf = cmpack_malloc(length*sizeof(double));
		count = (*n)-(length-1);
		for (i=0; i<count; i++) {
			for (j=0; j<length; j++) 
				buf[j] = data[i+j];
			data[i] = median(length, buf);
		}
		cmpack_free(buf);
		*n = count;
		return count;
	}
	*n = 0;
	return 0;
}
