Program: 75957
Project: 75957
Buggy source:
/** 
 * @param xs
 * @param ax
 * @param dsi
 * @param iType
 * @param dStart
 * @param dEnd
 * @param scModel
 * @param fs
 * @param rtc
 * @param direction
 * @param zoomFactor 1 is default factor
 * @param iMarginPercent the percentage of margin area for display some charts, such as bubble. 0 means no margin
 * @return AutoScale instance
 * @throws ChartException
 */
static final AutoScale computeScale(IDisplayServer xs,OneAxis ax,DataSetIterator dsi,int iType,double dStart,double dEnd,Scale scModel,FormatSpecifier fs,RunTimeContext rtc,int direction,double zoomFactor,int iMarginPercent) throws ChartException {
  final Label la=ax.getLabel();
  final int iLabelLocation=ax.getLabelPosition();
  final int iOrientation=ax.getOrientation();
  final DataElement oMinimum=scModel.getMin();
  final DataElement oMaximum=scModel.getMax();
  final Double oStep=scModel.isSetStep() ? new Double(scModel.getStep()) : null;
  final Integer oStepNumber=scModel.isSetStepNumber() ? new Integer(scModel.getStepNumber()) : null;
  AutoScale sc=null;
  AutoScale scCloned=null;
  final Object oMinValue, oMaxValue;
  if ((iType & TEXT) == TEXT || ax.isCategoryScale()) {
    sc=new AutoScale(iType);
    sc.fs=fs;
    sc.rtc=rtc;
    sc.bCategoryScale=true;
    sc.bAxisLabelStaggered=ax.isAxisLabelStaggered();
    sc.iLabelShowingInterval=ax.getLableShowingInterval();
    sc.bTickBetweenCategories=ax.isTickBwtweenCategories();
    sc.dZoomFactor=zoomFactor;
    sc.iMarginPercent=iMarginPercent;
    sc.setData(dsi);
    sc.setDirection(direction);
    sc.computeTicks(xs,ax.getLabel(),iLabelLocation,iOrientation,dStart,dEnd,false,null);
    oMinValue=null;
    oMaxValue=null;
  }
 else   if ((iType & LINEAR) == LINEAR) {
    Object oValue;
    double dValue, dMinValue=Double.MAX_VALUE, dMaxValue=-Double.MAX_VALUE;
    dsi.reset();
    double dPrecision=0;
    while (dsi.hasNext()) {
      oValue=dsi.next();
      if (oValue == null) {
        continue;
      }
      dValue=((Double)oValue).doubleValue();
      if (dValue < dMinValue)       dMinValue=dValue;
      if (dValue > dMaxValue)       dMaxValue=dValue;
      dPrecision=getPrecision(dPrecision,dValue);
    }
    final double dAbsMax=Math.abs(dMaxValue);
    final double dAbsMin=Math.abs(dMinValue);
    double dStep=Math.max(dAbsMax,dAbsMin);
    double dDelta=dMaxValue - dMinValue;
    if (dDelta == 0) {
      dStep=dPrecision;
    }
 else {
      dStep=Math.floor(Math.log(dDelta) / LOG_10);
      dStep=Math.pow(10,dStep);
      if (dStep < dPrecision) {
        dStep=dPrecision;
      }
    }
    sc=new AutoScale(iType,new Double(0),new Double(0));
    sc.oStep=new Double(dStep);
    sc.oStepNumber=oStepNumber;
    sc.setData(dsi);
    sc.setDirection(direction);
    sc.fs=fs;
    sc.rtc=rtc;
    sc.bAxisLabelStaggered=ax.isAxisLabelStaggered();
    sc.iLabelShowingInterval=ax.getLableShowingInterval();
    sc.bTickBetweenCategories=ax.isTickBwtweenCategories();
    sc.dZoomFactor=zoomFactor;
    sc.dPrecision=dPrecision;
    sc.iMarginPercent=iMarginPercent;
    setNumberMinMaxToScale(sc,oMinimum,oMaximum,rtc,ax);
    setStepToScale(sc,oStep,oStepNumber,rtc);
    oMinValue=new Double(dMinValue);
    oMaxValue=new Double(dMaxValue);
    sc.updateAxisMinMax(oMinValue,oMaxValue);
  }
 else   if ((iType & LOGARITHMIC) == LOGARITHMIC) {
    Object oValue;
    double dValue, dMinValue=Double.MAX_VALUE, dMaxValue=-Double.MAX_VALUE;
    if ((iType & PERCENT) == PERCENT) {
      dMinValue=0;
      dMaxValue=100;
    }
 else {
      dsi.reset();
      while (dsi.hasNext()) {
        oValue=dsi.next();
        if (oValue == null) {
          continue;
        }
        dValue=((Double)oValue).doubleValue();
        if (dValue < dMinValue)         dMinValue=dValue;
        if (dValue > dMaxValue)         dMaxValue=dValue;
      }
      if (dMinValue == 0) {
        dMinValue=dMaxValue > 0 ? 1 : -1;
      }
    }
    sc=new AutoScale(iType,new Double(0),new Double(0));
    sc.oStep=new Double(10);
    sc.oStepNumber=oStepNumber;
    sc.fs=fs;
    sc.rtc=rtc;
    sc.bAxisLabelStaggered=ax.isAxisLabelStaggered();
    sc.iLabelShowingInterval=ax.getLableShowingInterval();
    sc.bTickBetweenCategories=ax.isTickBwtweenCategories();
    sc.dZoomFactor=zoomFactor;
    sc.iMarginPercent=iMarginPercent;
    sc.setData(dsi);
    sc.setDirection(direction);
    setNumberMinMaxToScale(sc,oMinimum,oMaximum,rtc,ax);
    setStepToScale(sc,oStep,oStepNumber,rtc);
    oMinValue=new Double(dMinValue);
    oMaxValue=new Double(dMaxValue);
    sc.updateAxisMinMax(oMinValue,oMaxValue);
    if ((iType & PERCENT) == PERCENT) {
      sc.bStepFixed=true;
      sc.bMaximumFixed=true;
      sc.bMinimumFixed=true;
      sc.computeTicks(xs,ax.getLabel(),iLabelLocation,iOrientation,dStart,dEnd,false,null);
      return sc;
    }
  }
 else   if ((iType & DATE_TIME) == DATE_TIME) {
    Calendar cValue;
    Calendar caMin=null, caMax=null;
    dsi.reset();
    while (dsi.hasNext()) {
      cValue=(Calendar)dsi.next();
      if (cValue == null) {
        continue;
      }
      if (caMin == null) {
        caMin=cValue;
      }
      if (caMax == null) {
        caMax=cValue;
      }
      if (cValue.before(caMin))       caMin=cValue;
 else       if (cValue.after(caMax))       caMax=cValue;
    }
    oMinValue=new CDateTime(caMin);
    oMaxValue=new CDateTime(caMax);
    int iUnit;
    if (oStep != null || oStepNumber != null) {
      iUnit=ChartUtil.convertUnitTypeToCalendarConstant(scModel.getUnit());
    }
 else {
      iUnit=CDateTime.getPreferredUnit((CDateTime)oMinValue,(CDateTime)oMaxValue);
    }
    if (iUnit == 0)     iUnit=CDateTime.SECOND;
    CDateTime cdtMinAxis=((CDateTime)oMinValue).backward(iUnit,1);
    CDateTime cdtMaxAxis=((CDateTime)oMaxValue).forward(iUnit,1);
    cdtMinAxis.clearBelow(iUnit);
    cdtMaxAxis.clearBelow(iUnit);
    sc=new AutoScale(DATE_TIME,cdtMinAxis,cdtMaxAxis);
    sc.oStep=new Integer(1);
    sc.oStepNumber=oStepNumber;
    sc.oUnit=new Integer(iUnit);
    sc.setDirection(direction);
    sc.fs=fs;
    sc.rtc=rtc;
    sc.bAxisLabelStaggered=ax.isAxisLabelStaggered();
    sc.iLabelShowingInterval=ax.getLableShowingInterval();
    sc.bTickBetweenCategories=ax.isTickBwtweenCategories();
    sc.dZoomFactor=zoomFactor;
    sc.iMarginPercent=iMarginPercent;
    if (oMinimum != null) {
      if (oMinimum instanceof DateTimeDataElement) {
        sc.oMinimum=((DateTimeDataElement)oMinimum).getValueAsCDateTime();
      }
 else {
        throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",new Object[]{oMinimum,ax.getModelAxis().getType().getName()},Messages.getResourceBundle(rtc.getULocale()));
      }
      sc.bMinimumFixed=true;
    }
    if (oMaximum != null) {
      if (oMaximum instanceof DateTimeDataElement) {
        sc.oMaximum=((DateTimeDataElement)oMaximum).getValueAsCDateTime();
      }
 else {
        throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",new Object[]{sc.oMaximum,ax.getModelAxis().getType().getName()},Messages.getResourceBundle(rtc.getULocale()));
      }
      sc.bMaximumFixed=true;
    }
    if (sc.bMaximumFixed && sc.bMinimumFixed) {
      if (((CDateTime)sc.oMinimum).after(sc.oMaximum)) {
        throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",new Object[]{sc.oMinimum,sc.oMaximum},Messages.getResourceBundle(rtc.getULocale()));
      }
    }
    setStepToScale(sc,oStep,oStepNumber,rtc);
  }
 else {
    oMinValue=null;
    oMaxValue=null;
  }
  if ((iType & TEXT) != TEXT && !ax.isCategoryScale()) {
    sc.computeTicks(xs,la,iLabelLocation,iOrientation,dStart,dEnd,false,null);
    dStart=sc.dStart;
    dEnd=sc.dEnd;
    boolean bFirstFit=sc.checkFit(xs,la,iLabelLocation);
    boolean bFits=bFirstFit;
    boolean bZoomSuccess=false;
    for (int i=0; bFits == bFirstFit && i < 50; i++) {
      bZoomSuccess=true;
      scCloned=(AutoScale)sc.clone();
      if (sc.bStepFixed) {
        break;
      }
      if (bFirstFit) {
        if (!bFits) {
          break;
        }
        bZoomSuccess=sc.zoomIn();
      }
 else {
        if (!bFits && sc.getTickCordinates().length == 2) {
          break;
        }
        bZoomSuccess=sc.zoomOut();
      }
      if (!bZoomSuccess)       break;
      sc.updateAxisMinMax(oMinValue,oMaxValue);
      sc.computeTicks(xs,la,iLabelLocation,iOrientation,dStart,dEnd,false,null);
      bFits=sc.checkFit(xs,la,iLabelLocation);
      if (!bFits && sc.getTickCordinates().length == 2) {
        sc=scCloned;
        break;
      }
    }
    if (scCloned != null && bFirstFit && bZoomSuccess) {
      sc=scCloned;
    }
  }
  sc.setData(dsi);
  return sc;
}

Fixed version (ground truth):
/** 
 * @param xs
 * @param ax
 * @param dsi
 * @param iType
 * @param dStart
 * @param dEnd
 * @param scModel
 * @param fs
 * @param rtc
 * @param direction
 * @param zoomFactor 1 is default factor
 * @param iMarginPercent the percentage of margin area for display some charts, such as bubble. 0 means no margin
 * @return AutoScale instance
 * @throws ChartException
 */
static final AutoScale computeScale(IDisplayServer xs,OneAxis ax,DataSetIterator dsi,int iType,double dStart,double dEnd,Scale scModel,FormatSpecifier fs,RunTimeContext rtc,int direction,double zoomFactor,int iMarginPercent) throws ChartException {
  final Label la=ax.getLabel();
  final int iLabelLocation=ax.getLabelPosition();
  final int iOrientation=ax.getOrientation();
  final DataElement oMinimum=scModel.getMin();
  final DataElement oMaximum=scModel.getMax();
  final Double oStep=scModel.isSetStep() ? new Double(scModel.getStep()) : null;
  final Integer oStepNumber=scModel.isSetStepNumber() ? new Integer(scModel.getStepNumber()) : null;
  AutoScale sc=null;
  AutoScale scCloned=null;
  final Object oMinValue, oMaxValue;
  if ((iType & TEXT) == TEXT || ax.isCategoryScale()) {
    sc=new AutoScale(iType);
    sc.fs=fs;
    sc.rtc=rtc;
    sc.bCategoryScale=true;
    sc.bAxisLabelStaggered=ax.isAxisLabelStaggered();
    sc.iLabelShowingInterval=ax.getLableShowingInterval();
    sc.bTickBetweenCategories=ax.isTickBwtweenCategories();
    sc.dZoomFactor=zoomFactor;
    sc.iMarginPercent=iMarginPercent;
    sc.setData(dsi);
    sc.setDirection(direction);
    sc.computeTicks(xs,ax.getLabel(),iLabelLocation,iOrientation,dStart,dEnd,false,null);
    oMinValue=null;
    oMaxValue=null;
  }
 else   if ((iType & LINEAR) == LINEAR) {
    Object oValue;
    double dValue, dMinValue=Double.MAX_VALUE, dMaxValue=-Double.MAX_VALUE;
    dsi.reset();
    double dPrecision=0;
    while (dsi.hasNext()) {
      oValue=dsi.next();
      if (oValue == null) {
        continue;
      }
      dValue=((Double)oValue).doubleValue();
      if (dValue < dMinValue)       dMinValue=dValue;
      if (dValue > dMaxValue)       dMaxValue=dValue;
      dPrecision=getPrecision(dPrecision,dValue,fs,rtc.getULocale());
    }
    final double dAbsMax=Math.abs(dMaxValue);
    final double dAbsMin=Math.abs(dMinValue);
    double dStep=Math.max(dAbsMax,dAbsMin);
    double dDelta=dMaxValue - dMinValue;
    if (dDelta == 0) {
      dStep=dPrecision;
    }
 else {
      dStep=Math.floor(Math.log(dDelta) / LOG_10);
      dStep=Math.pow(10,dStep);
      if (dStep < dPrecision) {
        dStep=dPrecision;
      }
    }
    sc=new AutoScale(iType,new Double(0),new Double(0));
    sc.oStep=new Double(dStep);
    sc.oStepNumber=oStepNumber;
    sc.setData(dsi);
    sc.setDirection(direction);
    sc.fs=fs;
    sc.rtc=rtc;
    sc.bAxisLabelStaggered=ax.isAxisLabelStaggered();
    sc.iLabelShowingInterval=ax.getLableShowingInterval();
    sc.bTickBetweenCategories=ax.isTickBwtweenCategories();
    sc.dZoomFactor=zoomFactor;
    sc.dPrecision=dPrecision;
    sc.iMarginPercent=iMarginPercent;
    setNumberMinMaxToScale(sc,oMinimum,oMaximum,rtc,ax);
    setStepToScale(sc,oStep,oStepNumber,rtc);
    oMinValue=new Double(dMinValue);
    oMaxValue=new Double(dMaxValue);
    sc.updateAxisMinMax(oMinValue,oMaxValue);
  }
 else   if ((iType & LOGARITHMIC) == LOGARITHMIC) {
    Object oValue;
    double dValue, dMinValue=Double.MAX_VALUE, dMaxValue=-Double.MAX_VALUE;
    if ((iType & PERCENT) == PERCENT) {
      dMinValue=0;
      dMaxValue=100;
    }
 else {
      dsi.reset();
      while (dsi.hasNext()) {
        oValue=dsi.next();
        if (oValue == null) {
          continue;
        }
        dValue=((Double)oValue).doubleValue();
        if (dValue < dMinValue)         dMinValue=dValue;
        if (dValue > dMaxValue)         dMaxValue=dValue;
      }
      if (dMinValue == 0) {
        dMinValue=dMaxValue > 0 ? 1 : -1;
      }
    }
    sc=new AutoScale(iType,new Double(0),new Double(0));
    sc.oStep=new Double(10);
    sc.oStepNumber=oStepNumber;
    sc.fs=fs;
    sc.rtc=rtc;
    sc.bAxisLabelStaggered=ax.isAxisLabelStaggered();
    sc.iLabelShowingInterval=ax.getLableShowingInterval();
    sc.bTickBetweenCategories=ax.isTickBwtweenCategories();
    sc.dZoomFactor=zoomFactor;
    sc.iMarginPercent=iMarginPercent;
    sc.setData(dsi);
    sc.setDirection(direction);
    setNumberMinMaxToScale(sc,oMinimum,oMaximum,rtc,ax);
    setStepToScale(sc,oStep,oStepNumber,rtc);
    oMinValue=new Double(dMinValue);
    oMaxValue=new Double(dMaxValue);
    sc.updateAxisMinMax(oMinValue,oMaxValue);
    if ((iType & PERCENT) == PERCENT) {
      sc.bStepFixed=true;
      sc.bMaximumFixed=true;
      sc.bMinimumFixed=true;
      sc.computeTicks(xs,ax.getLabel(),iLabelLocation,iOrientation,dStart,dEnd,false,null);
      return sc;
    }
  }
 else   if ((iType & DATE_TIME) == DATE_TIME) {
    Calendar cValue;
    Calendar caMin=null, caMax=null;
    dsi.reset();
    while (dsi.hasNext()) {
      cValue=(Calendar)dsi.next();
      if (cValue == null) {
        continue;
      }
      if (caMin == null) {
        caMin=cValue;
      }
      if (caMax == null) {
        caMax=cValue;
      }
      if (cValue.before(caMin))       caMin=cValue;
 else       if (cValue.after(caMax))       caMax=cValue;
    }
    oMinValue=new CDateTime(caMin);
    oMaxValue=new CDateTime(caMax);
    int iUnit;
    if (oStep != null || oStepNumber != null) {
      iUnit=ChartUtil.convertUnitTypeToCalendarConstant(scModel.getUnit());
    }
 else {
      iUnit=CDateTime.getPreferredUnit((CDateTime)oMinValue,(CDateTime)oMaxValue);
    }
    if (iUnit == 0)     iUnit=CDateTime.SECOND;
    CDateTime cdtMinAxis=((CDateTime)oMinValue).backward(iUnit,1);
    CDateTime cdtMaxAxis=((CDateTime)oMaxValue).forward(iUnit,1);
    cdtMinAxis.clearBelow(iUnit);
    cdtMaxAxis.clearBelow(iUnit);
    sc=new AutoScale(DATE_TIME,cdtMinAxis,cdtMaxAxis);
    sc.oStep=new Integer(1);
    sc.oStepNumber=oStepNumber;
    sc.oUnit=new Integer(iUnit);
    sc.setDirection(direction);
    sc.fs=fs;
    sc.rtc=rtc;
    sc.bAxisLabelStaggered=ax.isAxisLabelStaggered();
    sc.iLabelShowingInterval=ax.getLableShowingInterval();
    sc.bTickBetweenCategories=ax.isTickBwtweenCategories();
    sc.dZoomFactor=zoomFactor;
    sc.iMarginPercent=iMarginPercent;
    if (oMinimum != null) {
      if (oMinimum instanceof DateTimeDataElement) {
        sc.oMinimum=((DateTimeDataElement)oMinimum).getValueAsCDateTime();
      }
 else {
        throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",new Object[]{oMinimum,ax.getModelAxis().getType().getName()},Messages.getResourceBundle(rtc.getULocale()));
      }
      sc.bMinimumFixed=true;
    }
    if (oMaximum != null) {
      if (oMaximum instanceof DateTimeDataElement) {
        sc.oMaximum=((DateTimeDataElement)oMaximum).getValueAsCDateTime();
      }
 else {
        throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",new Object[]{sc.oMaximum,ax.getModelAxis().getType().getName()},Messages.getResourceBundle(rtc.getULocale()));
      }
      sc.bMaximumFixed=true;
    }
    if (sc.bMaximumFixed && sc.bMinimumFixed) {
      if (((CDateTime)sc.oMinimum).after(sc.oMaximum)) {
        throw new ChartException(ChartEnginePlugin.ID,ChartException.GENERATION,"String_Node_Str",new Object[]{sc.oMinimum,sc.oMaximum},Messages.getResourceBundle(rtc.getULocale()));
      }
    }
    setStepToScale(sc,oStep,oStepNumber,rtc);
  }
 else {
    oMinValue=null;
    oMaxValue=null;
  }
  if ((iType & TEXT) != TEXT && !ax.isCategoryScale()) {
    sc.computeTicks(xs,la,iLabelLocation,iOrientation,dStart,dEnd,false,null);
    dStart=sc.dStart;
    dEnd=sc.dEnd;
    boolean bFirstFit=sc.checkFit(xs,la,iLabelLocation);
    boolean bFits=bFirstFit;
    boolean bZoomSuccess=false;
    for (int i=0; bFits == bFirstFit && i < 50; i++) {
      bZoomSuccess=true;
      scCloned=(AutoScale)sc.clone();
      if (sc.bStepFixed) {
        break;
      }
      if (bFirstFit) {
        if (!bFits) {
          break;
        }
        bZoomSuccess=sc.zoomIn();
      }
 else {
        if (!bFits && sc.getTickCordinates().length == 2) {
          break;
        }
        bZoomSuccess=sc.zoomOut();
      }
      if (!bZoomSuccess)       break;
      sc.updateAxisMinMax(oMinValue,oMaxValue);
      sc.computeTicks(xs,la,iLabelLocation,iOrientation,dStart,dEnd,false,null);
      bFits=sc.checkFit(xs,la,iLabelLocation);
      if (!bFits && sc.getTickCordinates().length == 2) {
        sc=scCloned;
        break;
      }
    }
    if (scCloned != null && bFirstFit && bZoomSuccess) {
      sc=scCloned;
    }
  }
  sc.setData(dsi);
  return sc;
}