21 * handle the case where data is filling the window
23 * find the biggest window
27 #define BIG_TS (99999999999999999.99)
32 * state record for median and trimmed median
38 double M_array[MAX_MED_SIZE];
39 double M_ts[MAX_MED_SIZE];
47 * state record for adjusted median and adjusted mean
49 struct ad_median_state
53 double M_array[MAX_MED_SIZE];
54 double M_ts[MAX_MED_SIZE];
65 MSort(double *M_value, double *M_ts, double value, double ts, int size)
73 double min_ts = BIG_TS;
76 * list is sorted from smallest to biggest -- find the
79 for(i=0; i < size; i++)
89 * overwrite the slot with the new value and
92 M_value[l_index] = value;
96 * bump the value into the right place in the list
104 if(next > (size - 1))
107 * while the value is not in the right spot
109 while(!((M_value[curr] >= M_value[prev]) &&
110 (M_value[curr] <= M_value[next])))
113 * if it is too big, shift up
115 if(M_value[curr] < M_value[prev])
117 temp = M_value[prev];
118 M_value[prev] = M_value[curr];
119 M_value[curr] = temp;
122 M_ts[prev] = M_ts[curr];
127 else /* shift down */
129 temp = M_value[next];
130 M_value[next] = M_value[curr];
131 M_value[curr] = temp;
134 M_ts[next] = M_ts[curr];
145 if(next > (size - 1))
150 * new list should be sorted
158 * these next two routines can do windowed medians for different
159 * window sizes. We put them in for the Adjusted versions but
160 * all medians should use them
163 FindMedian(double *sorted_list,
179 return(sorted_list[0]);
183 * sweep through sorted list counting only those that are
184 * within a win_size of now. stop when we have win_size/2
187 for(i=0; i < list_size; i++)
189 if(sorted_ts[i] > (now - win_size))
193 * need to remember this one for the even case
195 if(count == (win_size / 2))
201 if(count == ((win_size / 2) + 1))
206 * i should now be the index of middle element -- almost
212 if(win_size == (temp * 2))
214 val = (sorted_list[last_i] + sorted_list[i]) / 2.0;
218 val = sorted_list[i];
225 FindTrimMedian(double *sorted_list,
238 return(sorted_list[0]);
242 * sweep through sorted list counting only those that are
243 * within a win_size of now. stop when we have win_size/2
245 T = alpha * win_size;
248 for(i=0; i < win_size ; i++)
250 if((sorted_ts[i] > (now - win_size + T)) &&
251 (sorted_ts[i] < (now - T)))
253 val += sorted_list[i];
272 InitMedian(fbuff series, fbuff time_stamps, char *params)
274 struct median_state *state;
279 state = (struct median_state *)malloc(sizeof(struct median_state));
286 memset((void *)state,0,sizeof(struct median_state));
292 * first parameter is siaze of median window
295 M_size = (int)strtod(p_str,&p_str);
296 state->M_size = M_size;
300 state->M_size = MAX_MED_SIZE;
304 * init M_ts to all SMALL_TS so that MSort will build sorted
307 for(i=0; i < MAX_MED_SIZE; i++)
309 state->M_ts[i] = SMALL_TS;
311 state->artificial_time = 0;
312 state->series = series;
313 state->time_stamps = time_stamps;
316 return((char *)state);
320 FreeMedian(char *state)
327 UpdateMedian(char *state,
331 struct median_state *s = (struct median_state *)state;
335 curr_size = F_COUNT(s->series);
337 if(curr_size > s->M_size)
339 s->M_count = curr_size = s->M_size;
343 s->M_count = curr_size;
347 * update the sorted list
351 * increment the artificial time stamp
353 s->artificial_time = s->artificial_time + 1;
356 * use artificial time stamp instead of real one to
357 * keep things in terms of entries instead of seconds
359 MSort(s->M_array,s->M_ts,value,s->artificial_time,curr_size);
366 ForcMedian(char *state, double *forecast)
368 struct median_state *s = (struct median_state *)state;
377 l_index = s->M_count/2;
382 if(s->M_count == (2 * l_index))
384 val = (s->M_array[l_index-1] + s->M_array[l_index]) / 2.0;
388 val = s->M_array[l_index];
395 char *InitTrimMedian(fbuff series, fbuff time_stamps, char *params)
397 struct median_state *state;
403 state = (struct median_state *)malloc(sizeof(struct median_state));
410 memset((void *)state,0,sizeof(struct median_state));
416 * first parameter is size of median window
419 M_size = (int)strtod(p_str,&p_str);
420 state->M_size = M_size;
423 * second parameter is the alpha trim value
425 alpha = strtod(p_str, &p_str);
430 state->M_size = MAX_MED_SIZE;
435 * init M_ts to all SMALL_TS so that MSort will build sorted
438 for(i=0; i < MAX_MED_SIZE; i++)
440 state->M_ts[i] = SMALL_TS;
442 state->artificial_time = 0;
443 state->series = series;
444 state->time_stamps = time_stamps;
447 return((char *)state);
451 FreeTrimMedian(char *state)
458 UpdateTrimMedian(char *state, double ts, double value)
460 UpdateMedian(state,ts,value);
467 * page 264 in DSP book
470 ForcTrimMedian(char *state, double *forecast)
472 struct median_state *s = (struct median_state *)state;
483 T = (int)(s->trim * s->M_count);
486 for(l_index = T; l_index < (s->M_count - T); l_index++)
488 val += s->M_array[l_index];
491 val = val / (double)(s->M_count - 2*T);
501 char *InitAdMedian(fbuff series, fbuff time_stamps, char *params)
503 struct ad_median_state *state;
511 state = (struct ad_median_state *)
512 malloc(sizeof(struct ad_median_state));
519 memset((void *)state,0,sizeof(struct median_state));
525 * first parameter is initial target size of median window
528 win = (int)strtod(p_str,&p_str);
539 * second parameter is the min window value
541 min_win = strtod(p_str, &p_str);
544 * third parameter is the max window value
546 max_win = strtod(p_str, &p_str);
549 * fourth parameter is the offset value to use
550 * when calculating alternative window sizes
552 offset = strtod(p_str, &p_str);
553 state->offset = (int)offset;
561 if((win - state->offset) < 0)
564 if(min_win > (win - state->offset))
565 min_win = win - state->offset;
567 if(max_win < (win + state->offset))
568 max_win = win + state->offset;
570 state->min = (int)min_win;
571 state->max = (int)max_win;
575 state->min = state->max = state->win = MAX_MED_SIZE;
580 * init M_ts to all SMALL_TS so that MSort will build sorted
583 for(i=0; i < MAX_MED_SIZE; i++)
585 state->M_ts[i] = SMALL_TS;
587 state->artificial_time = 0;
588 state->series = series;
589 state->time_stamps = time_stamps;
591 state->artificial_time = 1;
593 return((char *)state);
597 FreeAdMedian(char *state)
604 UpdateAdMedian(char *state, double ts, double value)
606 struct ad_median_state *s = (struct ad_median_state *)state;
619 curr_size = F_COUNT(s->series);
622 * M_size is the current window size, and M_count is the
623 * current amount of data in the median buffer
626 if(curr_size > s->max)
628 s->M_count = curr_size = s->max;
632 s->M_count = curr_size;
636 * update the sorted list
640 * increment the artificial time stamp
642 s->artificial_time = s->artificial_time + 1;
645 * use artificial time stamp instead of real one to
646 * keep things in terms of entries instead of seconds
648 MSort(s->M_array,s->M_ts,value,s->artificial_time,curr_size);
652 * calculate the window based on how much data there is
654 if(curr_size > s->win)
663 * find the median using the current
666 eq_val = FindMedian(s->M_array,
673 * we want to wait until there is enough data before we start
674 * to adapt. We don't start to adjust s->win until there is
675 * enough data to get out to the max window size
677 if(curr_size < s->max)
682 if((win - s->offset) < 0)
688 lo_offset = s->offset;
691 if((win + s->offset) > s->M_count)
693 hi_offset = s->M_count - win - 1;
697 hi_offset = s->offset;
701 * find the median for a smaller window -- offset
702 * controls how much smaller or bigger the window should be
705 less_val = FindMedian(s->M_array,
712 * find the median for a bigger window -- offset
713 * controls how much smaller or bigger the window should be
716 more_val = FindMedian(s->M_array,
723 * now, calculate the errors
725 less_err = (value - less_val) * (value - less_val);
726 more_err = (value - more_val) * (value - more_val);
727 eq_err = (value - eq_val) * (value - eq_val);
730 * adapt the window according to the direction giving us the
733 if(less_err < eq_err)
735 if(less_err < more_err)
739 else if(more_err < eq_err)
744 else if(more_err < eq_err)
746 if(more_err < less_err)
750 else if(less_err < eq_err)
763 ForcAdMedian(char *state, double *forecast)
765 struct ad_median_state *s = (struct ad_median_state *)state;
773 if(s->M_count < s->max)
775 forc = FindMedian(s->M_array,
783 forc = FindMedian(s->M_array,
806 AdjustedMedian(tp,pred,min,max)
807 struct thruput_pred *tp;
819 struct value_el *data = tp->data;
820 int prev = MODMINUS(tp->head,1,HISTORYSIZE);
822 double value = tp->data[head].value;
823 double predictor = PRED(pred,data[prev]);
827 win = MedWIN(pred,data[prev]);
828 if(MODMINUS(head,tp->tail,HISTORYSIZE) < 3)
830 PRED(pred,data[head]) = value;
831 MedWIN(pred,data[head]) = win;
836 val1 = Median(tp,win-1);
837 val2 = Median(tp,win+1);
838 val3 = Median(tp,win);
840 err1 = (value - val1) * (value - val1);
841 err2 = (value - val2) * (value - val2);
842 err3 = (value - val3) * (value - val3);
879 out_val = Median(tp,min);
885 out_val = Median(tp,max);
888 MedWIN(pred,data[head]) = out_win;
889 PRED(pred,data[head]) = out_val;
892 AdjustedMean(tp,pred,min,max)
893 struct thruput_pred *tp;
905 struct value_el *data = tp->data;
906 int prev = MODMINUS(tp->head,1,HISTORYSIZE);
908 double value = tp->data[head].value;
909 double predictor = PRED(pred,data[prev]);
913 win = MeanWIN(pred,data[prev]);
914 if(MODMINUS(head,tp->tail,HISTORYSIZE) < 3)
916 PRED(pred,data[head]) = value;
917 MeanWIN(pred,data[head]) = WIN_INIT;
922 val1 = TrimmedMedian(tp,win-1,0.0);
923 val2 = TrimmedMedian(tp,win+1,0.0);
924 val3 = TrimmedMedian(tp,win,0.0);
926 err1 = (value - val1) * (value - val1);
927 err2 = (value - val2) * (value - val2);
928 err3 = (value - val3) * (value - val3);
965 out_val = TrimmedMedian(tp,min,0.0);
971 out_val = TrimmedMedian(tp,max,0.0);
974 MeanWIN(pred,data[head]) = out_win;
975 PRED(pred,data[head]) = out_val;