package net.sf.jasperreports.engine.fill;

class JRFloatVarianceIncrementer extends JRAbstractExtendedIncrementer {
  private static JRFloatVarianceIncrementer mainInstance = new JRFloatVarianceIncrementer();
  
  public static JRFloatVarianceIncrementer getInstance() {
    return mainInstance;
  }
  
  public Object increment(JRCalculable variable, Object expressionValue, AbstractValueProvider valueProvider) {
    Number value = (Number)variable.getIncrementedValue();
    Number newValue = (Number)expressionValue;
    if (newValue == null) {
      if (variable.isInitialized())
        return null; 
      return value;
    } 
    if (value == null || variable.isInitialized())
      return JRFloatIncrementerFactory.ZERO; 
    Number countValue = (Number)valueProvider.getValue(variable.getHelperVariable((byte)0));
    Number sumValue = (Number)valueProvider.getValue(variable.getHelperVariable((byte)1));
    return new Float((countValue.floatValue() - 1.0F) * value.floatValue() / countValue.floatValue() + (sumValue.floatValue() / countValue.floatValue() - newValue.floatValue()) * (sumValue.floatValue() / countValue.floatValue() - newValue.floatValue()) / (countValue.floatValue() - 1.0F));
  }
  
  public Object combine(JRCalculable calculable, JRCalculable calculableValue, AbstractValueProvider valueProvider) {
    Number value = (Number)calculable.getIncrementedValue();
    if (calculableValue.getValue() == null) {
      if (calculable.isInitialized())
        return null; 
      return value;
    } 
    if (value == null || calculable.isInitialized())
      return new Float(((Number)calculableValue.getIncrementedValue()).floatValue()); 
    float v1 = value.floatValue();
    float c1 = ((Number)valueProvider.getValue(calculable.getHelperVariable((byte)0))).floatValue();
    float s1 = ((Number)valueProvider.getValue(calculable.getHelperVariable((byte)1))).floatValue();
    float v2 = ((Number)calculableValue.getIncrementedValue()).floatValue();
    float c2 = ((Number)valueProvider.getValue(calculableValue.getHelperVariable((byte)0))).floatValue();
    float s2 = ((Number)valueProvider.getValue(calculableValue.getHelperVariable((byte)1))).floatValue();
    c1 -= c2;
    s1 -= s2;
    float c = c1 + c2;
    return new Float(c1 / c * v1 + c2 / c * v2 + c2 / c1 * s1 / c * s1 / c + c1 / c2 * s2 / c * s2 / c - 2.0F * s1 / c * s2 / c);
  }
  
  public Object initialValue() {
    return JRFloatIncrementerFactory.ZERO;
  }
}
