Sonar Fixes - type: bugs / severity: critical - mostly div by 0

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1870976 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2019-12-07 11:45:44 +00:00
parent 9f2f9dc793
commit b2a33515e9
9 changed files with 113 additions and 135 deletions

View File

@ -559,8 +559,8 @@ public class AddDimensionedImage {
// Next, from the columns width, calculate how many co-ordinate // Next, from the columns width, calculate how many co-ordinate
// positons there are per millimetre // positons there are per millimetre
coordinatePositionsPerMM = ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / coordinatePositionsPerMM = colWidthMM == 0 ? 0
colWidthMM; : ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / colWidthMM;
// From this figure, determine how many co-ordinat positions to // From this figure, determine how many co-ordinat positions to
// inset the left hand or bottom edge of the image. // inset the left hand or bottom edge of the image.
inset = (int)(coordinatePositionsPerMM * overlapMM); inset = (int)(coordinatePositionsPerMM * overlapMM);
@ -615,8 +615,7 @@ public class AddDimensionedImage {
row = sheet.createRow(toRow); row = sheet.createRow(toRow);
} }
// Get the row's height in millimetres and add to the running total. // Get the row's height in millimetres and add to the running total.
rowHeightMM = row.getHeightInPoints() / rowHeightMM = row.getHeightInPoints() / ConvertImageUnits.POINTS_PER_MILLIMETRE;
ConvertImageUnits.POINTS_PER_MILLIMETRE;
totalRowHeightMM += rowHeightMM; totalRowHeightMM += rowHeightMM;
toRow++; toRow++;
} }
@ -647,11 +646,10 @@ public class AddDimensionedImage {
overlapMM = 0.0D; overlapMM = 0.0D;
} }
rowCoordinatesPerMM = ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / rowCoordinatesPerMM = rowHeightMM == 0 ? 0
rowHeightMM; : ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / rowHeightMM;
inset = (int)(overlapMM * rowCoordinatesPerMM); inset = (int)(overlapMM * rowCoordinatesPerMM);
clientAnchorDetail = new ClientAnchorDetail(startingRow, clientAnchorDetail = new ClientAnchorDetail(startingRow, toRow, inset);
toRow, inset);
} }
return(clientAnchorDetail); return(clientAnchorDetail);
} }

View File

@ -460,8 +460,8 @@ public class AddDimensionedImage {
// is then instantiated. // is then instantiated.
if(sheet instanceof HSSFSheet) { if(sheet instanceof HSSFSheet) {
colWidthMM = reqImageWidthMM; colWidthMM = reqImageWidthMM;
colCoordinatesPerMM = ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / colCoordinatesPerMM = colWidthMM == 0 ? 0
colWidthMM; : ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / colWidthMM;
pictureWidthCoordinates = (int)(reqImageWidthMM * colCoordinatesPerMM); pictureWidthCoordinates = (int)(reqImageWidthMM * colCoordinatesPerMM);
} }
@ -553,8 +553,8 @@ public class AddDimensionedImage {
ConvertImageUnits.POINTS_PER_MILLIMETRE)); ConvertImageUnits.POINTS_PER_MILLIMETRE));
if(sheet instanceof HSSFSheet) { if(sheet instanceof HSSFSheet) {
rowHeightMM = reqImageHeightMM; rowHeightMM = reqImageHeightMM;
rowCoordinatesPerMM = ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / rowCoordinatesPerMM = rowHeightMM == 0 ? 0
rowHeightMM; : ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / rowHeightMM;
pictureHeightCoordinates = (int)(reqImageHeightMM * pictureHeightCoordinates = (int)(reqImageHeightMM *
rowCoordinatesPerMM); rowCoordinatesPerMM);
} }

View File

@ -78,6 +78,8 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public final class BigGridDemo { public final class BigGridDemo {
private static final String XML_ENCODING = "UTF-8"; private static final String XML_ENCODING = "UTF-8";
private static final Random rnd = new Random();
private BigGridDemo() {} private BigGridDemo() {}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
@ -153,7 +155,6 @@ public final class BigGridDemo {
private static void generate(Writer out, Map<String, XSSFCellStyle> styles) throws Exception { private static void generate(Writer out, Map<String, XSSFCellStyle> styles) throws Exception {
Random rnd = new Random();
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
SpreadsheetWriter sw = new SpreadsheetWriter(out); SpreadsheetWriter sw = new SpreadsheetWriter(out);

View File

@ -27,9 +27,9 @@ import org.apache.tools.ant.Task;
* Instances of this class are used to evaluate a single cell. This is usually * Instances of this class are used to evaluate a single cell. This is usually
* after some values have been set. The evaluation is actually performed * after some values have been set. The evaluation is actually performed
* by a WorkbookUtil instance. The evaluate() method of the WorkbookUtil * by a WorkbookUtil instance. The evaluate() method of the WorkbookUtil
* class returns an EvaluationResult which encapsulates the results and * class returns an EvaluationResult which encapsulates the results and
* information from the evaluation. * information from the evaluation.
* *
* @author Jon Svede ( jon [at] loquatic [dot] com ) * @author Jon Svede ( jon [at] loquatic [dot] com )
* @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov ) * @author Brian Bush ( brian [dot] bush [at] nrel [dot] gov )
@ -40,40 +40,39 @@ public class ExcelAntEvaluateCell extends Task {
private String cell ; private String cell ;
private double expectedValue ; private double expectedValue ;
private double precision ; private double precision ;
private double precisionToUse ;
private double globalPrecision ; private double globalPrecision ;
private boolean requiredToPass; private boolean requiredToPass;
private ExcelAntEvaluationResult result ; private ExcelAntEvaluationResult result ;
private ExcelAntWorkbookUtil wbUtil ; private ExcelAntWorkbookUtil wbUtil ;
private boolean showDelta; private boolean showDelta;
public ExcelAntEvaluateCell() {} public ExcelAntEvaluateCell() {}
protected void setWorkbookUtil( ExcelAntWorkbookUtil wb ) { protected void setWorkbookUtil( ExcelAntWorkbookUtil wb ) {
wbUtil = wb ; wbUtil = wb ;
} }
public void setShowDelta( boolean value ) { public void setShowDelta( boolean value ) {
showDelta = value ; showDelta = value ;
} }
protected boolean showDelta() { protected boolean showDelta() {
return showDelta ; return showDelta ;
} }
public void setCell(String cell) { public void setCell(String cell) {
this.cell = cell; this.cell = cell;
} }
public void setRequiredToPass( boolean val ) { public void setRequiredToPass( boolean val ) {
requiredToPass = val ; requiredToPass = val ;
} }
protected boolean requiredToPass() { protected boolean requiredToPass() {
return requiredToPass ; return requiredToPass ;
} }
@ -85,7 +84,7 @@ public class ExcelAntEvaluateCell extends Task {
public void setPrecision(double precision) { public void setPrecision(double precision) {
this.precision = precision; this.precision = precision;
} }
protected void setGlobalPrecision( double prec ) { protected void setGlobalPrecision( double prec ) {
globalPrecision = prec ; globalPrecision = prec ;
} }
@ -98,47 +97,44 @@ public class ExcelAntEvaluateCell extends Task {
return expectedValue; return expectedValue;
} }
@SuppressWarnings("squid:S4275")
protected double getPrecision() { protected double getPrecision() {
return precisionToUse;
}
@Override
public void execute() throws BuildException {
precisionToUse = 0 ;
// if there is a globalPrecision we will use it unless there is also // if there is a globalPrecision we will use it unless there is also
// precision set at the evaluate level, then we use that. If there // precision set at the evaluate level, then we use that. If there
// is not a globalPrecision, we will use the local precision. // is not a globalPrecision, we will use the local precision.
log( "test precision = " + precision + "\tglobal precision = " + globalPrecision, Project.MSG_VERBOSE ) ; log( "test precision = " + precision + "\tglobal precision = " + globalPrecision, Project.MSG_VERBOSE ) ;
if( globalPrecision > 0 ) { if( globalPrecision > 0 ) {
if( precision > 0 ) { if( precision > 0 ) {
precisionToUse = precision ;
log( "Using evaluate precision of " + precision + " over the " + log( "Using evaluate precision of " + precision + " over the " +
"global precision of " + globalPrecision, Project.MSG_VERBOSE ) ; "global precision of " + globalPrecision, Project.MSG_VERBOSE ) ;
return precision ;
} else { } else {
precisionToUse = globalPrecision ;
log( "Using global precision of " + globalPrecision, Project.MSG_VERBOSE ) ; log( "Using global precision of " + globalPrecision, Project.MSG_VERBOSE ) ;
return globalPrecision ;
} }
} else { } else {
precisionToUse = precision ;
log( "Using evaluate precision of " + precision, Project.MSG_VERBOSE ) ; log( "Using evaluate precision of " + precision, Project.MSG_VERBOSE ) ;
return precision ;
} }
result = wbUtil.evaluateCell(cell, expectedValue, precisionToUse ) ; }
@Override
public void execute() throws BuildException {
result = wbUtil.evaluateCell(cell, expectedValue, getPrecision() ) ;
StringBuilder sb = new StringBuilder() ; StringBuilder sb = new StringBuilder() ;
sb.append( "evaluation of cell " ) ; sb.append( "evaluation of cell " ) ;
sb.append( cell ) ; sb.append( cell ) ;
sb.append( " resulted in " ) ; sb.append( " resulted in " ) ;
sb.append( result.getReturnValue() ) ; sb.append( result.getReturnValue() ) ;
if(showDelta) { if(showDelta) {
sb.append(" with a delta of ").append(result.getDelta()); sb.append(" with a delta of ").append(result.getDelta());
} }
log( sb.toString(), Project.MSG_DEBUG) ; log( sb.toString(), Project.MSG_DEBUG) ;
} }
public ExcelAntEvaluationResult getResult() { public ExcelAntEvaluationResult getResult() {
return result ; return result ;
} }

View File

@ -19,16 +19,9 @@
package org.apache.poi.sl.draw.geom; package org.apache.poi.sl.draw.geom;
import static java.lang.Math.abs; import static java.lang.Math.*;
import static java.lang.Math.atan2;
import static java.lang.Math.cos; import java.util.regex.Pattern;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.sin;
import static java.lang.Math.sqrt;
import static java.lang.Math.tan;
import static java.lang.Math.toDegrees;
import static java.lang.Math.toRadians;
import org.apache.poi.sl.draw.binding.CTGeomGuide; import org.apache.poi.sl.draw.binding.CTGeomGuide;
@ -40,6 +33,9 @@ public class Guide implements Formula {
muldiv,addsub,adddiv,ifelse,val,abs,sqrt,max,min,at2,sin,cos,tan,cat2,sat2,pin,mod muldiv,addsub,adddiv,ifelse,val,abs,sqrt,max,min,at2,sin,cos,tan,cat2,sat2,pin,mod
} }
private static final Pattern WHITESPACE = Pattern.compile("\\s+");
@SuppressWarnings({"FieldCanBeLocal", "unused"})
private final String name, fmla; private final String name, fmla;
private final Op op; private final Op op;
private final String[] operands; private final String[] operands;
@ -52,18 +48,20 @@ public class Guide implements Formula {
public Guide(String nm, String fm){ public Guide(String nm, String fm){
name = nm; name = nm;
fmla = fm; fmla = fm;
operands = fm.split("\\s+"); operands = WHITESPACE.split(fm);
op = Op.valueOf(operands[0].replace("*", "mul").replace("/", "div").replace("+", "add").replace("-", "sub").replace("?:", "ifelse")); switch (operands[0]) {
case "*/": op = Op.muldiv; break;
case "+-": op = Op.addsub; break;
case "+/": op = Op.adddiv; break;
case "?:": op = Op.ifelse; break;
default: op = Op.valueOf(operands[0]); break;
}
} }
public String getName(){ public String getName(){
return name; return name;
} }
String getFormula(){
return fmla;
}
@Override @Override
public double evaluate(Context ctx) { public double evaluate(Context ctx) {
double x = (operands.length > 1) ? ctx.getValue(operands[1]) : 0; double x = (operands.length > 1) ? ctx.getValue(operands[1]) : 0;
@ -75,7 +73,7 @@ public class Guide implements Formula {
return abs(x); return abs(x);
case adddiv: case adddiv:
// Add Divide Formula // Add Divide Formula
return (x + y) / z; return (z == 0) ? 0 : (x + y) / z;
case addsub: case addsub:
// Add Subtract Formula // Add Subtract Formula
return (x + y) - z; return (x + y) - z;
@ -87,7 +85,7 @@ public class Guide implements Formula {
return x * cos(toRadians(y / OOXML_DEGREE)); return x * cos(toRadians(y / OOXML_DEGREE));
case cat2: case cat2:
// Cosine ArcTan Formula: "cat2 x y z" = (x * cos(arctan(z / y) )) = value of this guide // Cosine ArcTan Formula: "cat2 x y z" = (x * cos(arctan(z / y) )) = value of this guide
return x*cos(atan2(z, y)); return x * cos(atan2(z, y));
case ifelse: case ifelse:
// If Else Formula: "?: x y z" = if (x > 0), then y = value of this guide, // If Else Formula: "?: x y z" = if (x > 0), then y = value of this guide,
// else z = value of this guide // else z = value of this guide
@ -106,21 +104,15 @@ public class Guide implements Formula {
return sqrt(x*x + y*y + z*z); return sqrt(x*x + y*y + z*z);
case muldiv: case muldiv:
// Multiply Divide Formula // Multiply Divide Formula
return (x * y) / z; return (z == 0) ? 0 : (x * y) / z;
case pin: case pin:
// Pin To Formula: "pin x y z" = if (y < x), then x = value of this guide // Pin To Formula: "pin x y z" = if (y < x), then x = value of this guide
// else if (y > z), then z = value of this guide // else if (y > z), then z = value of this guide
// else y = value of this guide // else y = value of this guide
if(y < x) { return max(x, min(y, z));
return x;
} else if (y > z) {
return z;
} else {
return y;
}
case sat2: case sat2:
// Sine ArcTan Formula: "sat2 x y z" = (x*sin(arctan(z / y))) = value of this guide // Sine ArcTan Formula: "sat2 x y z" = (x*sin(arctan(z / y))) = value of this guide
return x*sin(atan2(z, y)); return x * sin(atan2(z, y));
case sin: case sin:
// Sine Formula: "sin x y" = (x * sin( y )) = value of this guide // Sine Formula: "sin x y" = (x * sin( y )) = value of this guide
return x * sin(toRadians(y / OOXML_DEGREE)); return x * sin(toRadians(y / OOXML_DEGREE));

View File

@ -22,6 +22,7 @@ import java.util.Calendar;
import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException; import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LocaleUtil; import org.apache.poi.util.LocaleUtil;
@ -30,6 +31,7 @@ import org.apache.poi.util.LocaleUtil;
* *
* Algorithm inspired by www.dwheeler.com/yearfrac * Algorithm inspired by www.dwheeler.com/yearfrac
*/ */
@Internal
final class YearFracCalculator { final class YearFracCalculator {
private static final int MS_PER_HOUR = 60 * 60 * 1000; private static final int MS_PER_HOUR = 60 * 60 * 1000;
private static final int MS_PER_DAY = 24 * MS_PER_HOUR; private static final int MS_PER_DAY = 24 * MS_PER_HOUR;
@ -86,7 +88,7 @@ final class YearFracCalculator {
* @param startDateVal assumed to be less than or equal to endDateVal * @param startDateVal assumed to be less than or equal to endDateVal
* @param endDateVal assumed to be greater than or equal to startDateVal * @param endDateVal assumed to be greater than or equal to startDateVal
*/ */
public static double basis0(int startDateVal, int endDateVal) { private static double basis0(int startDateVal, int endDateVal) {
SimpleDate startDate = createDate(startDateVal); SimpleDate startDate = createDate(startDateVal);
SimpleDate endDate = createDate(endDateVal); SimpleDate endDate = createDate(endDateVal);
int date1day = startDate.day; int date1day = startDate.day;
@ -116,12 +118,14 @@ final class YearFracCalculator {
* @param startDateVal assumed to be less than or equal to endDateVal * @param startDateVal assumed to be less than or equal to endDateVal
* @param endDateVal assumed to be greater than or equal to startDateVal * @param endDateVal assumed to be greater than or equal to startDateVal
*/ */
public static double basis1(int startDateVal, int endDateVal) { private static double basis1(int startDateVal, int endDateVal) {
assert(startDateVal <= endDateVal);
SimpleDate startDate = createDate(startDateVal); SimpleDate startDate = createDate(startDateVal);
SimpleDate endDate = createDate(endDateVal); SimpleDate endDate = createDate(endDateVal);
double yearLength; double yearLength;
if (isGreaterThanOneYear(startDate, endDate)) { if (isGreaterThanOneYear(startDate, endDate)) {
yearLength = averageYearLength(startDate.year, endDate.year); yearLength = averageYearLength(startDate.year, endDate.year);
assert(yearLength > 0);
} else if (shouldCountFeb29(startDate, endDate)) { } else if (shouldCountFeb29(startDate, endDate)) {
yearLength = DAYS_PER_LEAP_YEAR; yearLength = DAYS_PER_LEAP_YEAR;
} else { } else {
@ -134,21 +138,21 @@ final class YearFracCalculator {
* @param startDateVal assumed to be less than or equal to endDateVal * @param startDateVal assumed to be less than or equal to endDateVal
* @param endDateVal assumed to be greater than or equal to startDateVal * @param endDateVal assumed to be greater than or equal to startDateVal
*/ */
public static double basis2(int startDateVal, int endDateVal) { private static double basis2(int startDateVal, int endDateVal) {
return (endDateVal - startDateVal) / 360.0; return (endDateVal - startDateVal) / 360.0;
} }
/** /**
* @param startDateVal assumed to be less than or equal to endDateVal * @param startDateVal assumed to be less than or equal to endDateVal
* @param endDateVal assumed to be greater than or equal to startDateVal * @param endDateVal assumed to be greater than or equal to startDateVal
*/ */
public static double basis3(double startDateVal, double endDateVal) { private static double basis3(double startDateVal, double endDateVal) {
return (endDateVal - startDateVal) / 365.0; return (endDateVal - startDateVal) / 365.0;
} }
/** /**
* @param startDateVal assumed to be less than or equal to endDateVal * @param startDateVal assumed to be less than or equal to endDateVal
* @param endDateVal assumed to be greater than or equal to startDateVal * @param endDateVal assumed to be greater than or equal to startDateVal
*/ */
public static double basis4(int startDateVal, int endDateVal) { private static double basis4(int startDateVal, int endDateVal) {
SimpleDate startDate = createDate(startDateVal); SimpleDate startDate = createDate(startDateVal);
SimpleDate endDate = createDate(endDateVal); SimpleDate endDate = createDate(endDateVal);
int date1day = startDate.day; int date1day = startDate.day;
@ -261,12 +265,10 @@ final class YearFracCalculator {
} }
private static double averageYearLength(int startYear, int endYear) { private static double averageYearLength(int startYear, int endYear) {
assert(startYear <= endYear);
int dayCount = 0; int dayCount = 0;
for (int i=startYear; i<=endYear; i++) { for (int i=startYear; i<=endYear; i++) {
dayCount += DAYS_PER_NORMAL_YEAR; dayCount += isLeapYear(i) ? DAYS_PER_LEAP_YEAR : DAYS_PER_NORMAL_YEAR;
if (isLeapYear(i)) {
dayCount++;
}
} }
double numberOfYears = endYear-startYear+1; double numberOfYears = endYear-startYear+1;
return dayCount / numberOfYears; return dayCount / numberOfYears;
@ -282,13 +284,11 @@ final class YearFracCalculator {
return true; return true;
} }
// all other centuries are *not* leap years // all other centuries are *not* leap years
if (i % 100 == 0) { return i % 100 != 0;
return false;
}
return true;
} }
private static boolean isGreaterThanOneYear(SimpleDate start, SimpleDate end) { private static boolean isGreaterThanOneYear(SimpleDate start, SimpleDate end) {
assert(start.year <= end.year);
if (start.year == end.year) { if (start.year == end.year) {
return false; return false;
} }
@ -307,7 +307,7 @@ final class YearFracCalculator {
} }
private static SimpleDate createDate(int dayCount) { private static SimpleDate createDate(int dayCount) {
/** use UTC time-zone to avoid daylight savings issues */ /* use UTC time-zone to avoid daylight savings issues */
Calendar cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC); Calendar cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
DateUtil.setCalendar(cal, dayCount, 0, false, false); DateUtil.setCalendar(cal, dayCount, 0, false, false);
return new SimpleDate(cal); return new SimpleDate(cal);

View File

@ -17,7 +17,10 @@
package org.apache.poi.ss.formula.functions; package org.apache.poi.ss.formula.functions;
import org.apache.poi.ss.formula.eval.*; import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
/** /**
* Calculates the internal rate of return. * Calculates the internal rate of return.
@ -104,11 +107,17 @@ public final class Irr implements Function {
final double value = values[k]; final double value = values[k];
fValue += value / denominator; fValue += value / denominator;
denominator *= factor; denominator *= factor;
if (denominator == 0) {
return Double.NaN;
}
fDerivative -= k * value / denominator; fDerivative -= k * value / denominator;
} }
// the essense of the Newton-Raphson Method // the essence of the Newton-Raphson Method
x1 = x0 - fValue/fDerivative; if (fDerivative == 0) {
return Double.NaN;
}
x1 = x0 - fValue/fDerivative;
if (Math.abs(x1 - x0) <= absoluteAccuracy) { if (Math.abs(x1 - x0) <= absoluteAccuracy) {
return x1; return x1;

View File

@ -41,7 +41,7 @@ import org.apache.poi.ss.formula.functions.LookupUtils.ValueVector;
* @author Johan Karlsteen * @author Johan Karlsteen
*/ */
public final class LinearRegressionFunction extends Fixed2ArgFunction { public final class LinearRegressionFunction extends Fixed2ArgFunction {
private static abstract class ValueArray implements ValueVector { private static abstract class ValueArray implements ValueVector {
private final int _size; private final int _size;
protected ValueArray(int size) { protected ValueArray(int size) {
@ -84,7 +84,7 @@ public final class LinearRegressionFunction extends Fixed2ArgFunction {
} }
protected ValueEval getItemInternal(int index) { protected ValueEval getItemInternal(int index) {
int sIx = (index % _width) + _ref.getFirstSheetIndex(); int sIx = (index % _width) + _ref.getFirstSheetIndex();
return _ref.getInnerValueEval(sIx); return _ref.getInnerValueEval(sIx);
} }
} }
@ -108,11 +108,11 @@ public final class LinearRegressionFunction extends Fixed2ArgFunction {
public enum FUNCTION {INTERCEPT, SLOPE} public enum FUNCTION {INTERCEPT, SLOPE}
public FUNCTION function; public FUNCTION function;
public LinearRegressionFunction(FUNCTION function) { public LinearRegressionFunction(FUNCTION function) {
this.function = function; this.function = function;
} }
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, public ValueEval evaluate(int srcRowIndex, int srcColumnIndex,
ValueEval arg0, ValueEval arg1) { ValueEval arg0, ValueEval arg1) {
double result; double result;
@ -132,25 +132,21 @@ public final class LinearRegressionFunction extends Fixed2ArgFunction {
} }
return new NumberEval(result); return new NumberEval(result);
} }
private double evaluateInternal(ValueVector x, ValueVector y, int size) private double evaluateInternal(ValueVector x, ValueVector y, int size)
throws EvaluationException { throws EvaluationException {
// error handling is as if the x is fully evaluated before y // error handling is as if the x is fully evaluated before y
ErrorEval firstXerr = null;
ErrorEval firstYerr = null; ErrorEval firstYerr = null;
boolean accumlatedSome = false; boolean accumlatedSome = false;
// first pass: read in data, compute xbar and ybar // first pass: read in data, compute xbar and ybar
double sumx = 0.0, sumy = 0.0; double sumx = 0.0, sumy = 0.0;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
ValueEval vx = x.getItem(i); ValueEval vx = x.getItem(i);
ValueEval vy = y.getItem(i); ValueEval vy = y.getItem(i);
if (vx instanceof ErrorEval) { if (vx instanceof ErrorEval) {
if (firstXerr == null) { throw new EvaluationException((ErrorEval) vx);
firstXerr = (ErrorEval) vx;
continue;
}
} }
if (vy instanceof ErrorEval) { if (vy instanceof ErrorEval) {
if (firstYerr == null) { if (firstYerr == null) {
@ -159,66 +155,51 @@ public final class LinearRegressionFunction extends Fixed2ArgFunction {
} }
} }
// only count pairs if both elements are numbers // only count pairs if both elements are numbers
// all other combinations of value types are silently ignored
if (vx instanceof NumberEval && vy instanceof NumberEval) { if (vx instanceof NumberEval && vy instanceof NumberEval) {
accumlatedSome = true; accumlatedSome = true;
NumberEval nx = (NumberEval) vx; NumberEval nx = (NumberEval) vx;
NumberEval ny = (NumberEval) vy; NumberEval ny = (NumberEval) vy;
sumx += nx.getNumberValue(); sumx += nx.getNumberValue();
sumy += ny.getNumberValue(); sumy += ny.getNumberValue();
} else {
// all other combinations of value types are silently ignored
} }
} }
if (firstYerr != null) {
throw new EvaluationException(firstYerr);
}
if (!accumlatedSome) {
throw new EvaluationException(ErrorEval.DIV_ZERO);
}
double xbar = sumx / size; double xbar = sumx / size;
double ybar = sumy / size; double ybar = sumy / size;
// second pass: compute summary statistics // second pass: compute summary statistics
double xxbar = 0.0, xybar = 0.0; double xxbar = 0.0, xybar = 0.0;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
ValueEval vx = x.getItem(i); ValueEval vx = x.getItem(i);
ValueEval vy = y.getItem(i); ValueEval vy = y.getItem(i);
if (vx instanceof ErrorEval) {
if (firstXerr == null) {
firstXerr = (ErrorEval) vx;
continue;
}
}
if (vy instanceof ErrorEval) {
if (firstYerr == null) {
firstYerr = (ErrorEval) vy;
continue;
}
}
// only count pairs if both elements are numbers // only count pairs if both elements are numbers
// all other combinations of value types are silently ignored
if (vx instanceof NumberEval && vy instanceof NumberEval) { if (vx instanceof NumberEval && vy instanceof NumberEval) {
NumberEval nx = (NumberEval) vx; NumberEval nx = (NumberEval) vx;
NumberEval ny = (NumberEval) vy; NumberEval ny = (NumberEval) vy;
xxbar += (nx.getNumberValue() - xbar) * (nx.getNumberValue() - xbar); xxbar += (nx.getNumberValue() - xbar) * (nx.getNumberValue() - xbar);
xybar += (nx.getNumberValue() - xbar) * (ny.getNumberValue() - ybar); xybar += (nx.getNumberValue() - xbar) * (ny.getNumberValue() - ybar);
} else {
// all other combinations of value types are silently ignored
} }
} }
double beta1 = xybar / xxbar;
double beta0 = ybar - beta1 * xbar; if (xxbar == 0 ) {
if (firstXerr != null) {
throw new EvaluationException(firstXerr);
}
if (firstYerr != null) {
throw new EvaluationException(firstYerr);
}
if (!accumlatedSome) {
throw new EvaluationException(ErrorEval.DIV_ZERO); throw new EvaluationException(ErrorEval.DIV_ZERO);
} }
if(function == FUNCTION.INTERCEPT) { double beta1 = xybar / xxbar;
return beta0; double beta0 = ybar - beta1 * xbar;
} else {
return beta1; return (function == FUNCTION.INTERCEPT) ? beta0 : beta1;
}
} }
private static ValueVector createValueVector(ValueEval arg) throws EvaluationException { private static ValueVector createValueVector(ValueEval arg) throws EvaluationException {

View File

@ -213,6 +213,7 @@ public final class XMLHelper {
return XMLEventFactory.newInstance(); return XMLEventFactory.newInstance();
} }
@SuppressWarnings("squid:S4435")
public static TransformerFactory getTransformerFactory() { public static TransformerFactory getTransformerFactory() {
TransformerFactory factory = TransformerFactory.newInstance(); TransformerFactory factory = TransformerFactory.newInstance();
trySet(factory::setFeature, FEATURE_SECURE_PROCESSING, true); trySet(factory::setFeature, FEATURE_SECURE_PROCESSING, true);