/** * */ package net.varkhan.base.management.monitor.derived; import net.varkhan.base.management.monitor.primitive.MonitorDouble; import net.varkhan.base.management.monitor.primitive.MonitorLong; /** * @author varkhan * @date Jun 16, 2009 * @time 11:54:07 PM */ public class MonitorContinuousAverage extends MonitorAverage { private static final long serialVersionUID=1L; private final long halflife; private long lastupdt; public MonitorContinuousAverage(MonitorLong frame, MonitorDouble value, long halflife) { super(frame, value); this.halflife=halflife; } public void reset() { super.reset(); lastupdt=super.frame(); } /** * ******************************************************************************* * * Continuous update */ public void update() { super.update(); long frame=super.frame(); double value=super.value(); if(frame<=lastupdt) return; // Local averages are subject to an exponential attrition factor, dividing by two every half-life frames double oldf=decay(frame-lastupdt, halflife); double newf=1.0-oldf; locmin=(float) (oldf*locmin+newf*locavg); locmax=(float) (oldf*locmax+newf*locavg); locavg=(float) (oldf*locavg+newf*value); locvar=(float) (oldf*locvar+newf*(value*value-locavg*locavg)); if(locmin>value) locmin=(float) value; if(locmax<value) locmax=(float) value; if(glbmin>value) glbmin=(float) value; if(glbmax<value) glbmax=(float) value; // Global averages only depend on elapsed frames double dlframes=frame-lastupdt; double dlavg=value-glbavg; double dlvar=value*value-glbvar; glbavg+=dlavg*dlframes/frame; glbvar+=(dlvar-(dlavg*dlavg*dlframes/frame))*dlframes/frame; lastupdt=frame; } /** * ******************************************************************************* * * Static math helper methods */ private static final float FP_Ln2 =(float) Math.log(2.0); private static final int valscale=10; private static final int valcount=1<<valscale; private static final float[] expvals =new float[valcount+1]; static { double c=1.0f/valcount; double f=0.0f; for(int i=0;i<=valcount;i++) { expvals[i]=(float) Math.exp(f*FP_Ln2); f-=c; } } private static double decay(long d, long h) { int x=(int) (d/h); int f=(int) ((d-x*h)*valcount/h); return Math.scalb(expvals[f], -x); } }