in commons-numbers-core/src/main/java/org/apache/commons/numbers/core/Norm.java [399:482]
private static double euclidean(final double[] v) {
// sum of big, normal and small numbers
double s1 = 0;
double s2 = 0;
double s3 = 0;
// sum compensation values
double c1 = 0;
double c2 = 0;
double c3 = 0;
for (int i = 0; i < v.length; ++i) {
final double x = Math.abs(v[i]);
if (!Double.isFinite(x)) {
// not finite; determine whether to return NaN or positive infinity
return euclideanNormSpecial(v, i);
} else if (x > LARGE_THRESH) {
// scale down
final double sx = x * SCALE_DOWN;
// compute the product and product compensation
final double p = sx * sx;
final double cp = DD.twoSquareLow(sx, p);
// compute the running sum and sum compensation
final double s = s1 + p;
final double cs = DD.twoSumLow(s1, p, s);
// update running totals
c1 += cp + cs;
s1 = s;
} else if (x < SMALL_THRESH) {
// scale up
final double sx = x * SCALE_UP;
// compute the product and product compensation
final double p = sx * sx;
final double cp = DD.twoSquareLow(sx, p);
// compute the running sum and sum compensation
final double s = s3 + p;
final double cs = DD.twoSumLow(s3, p, s);
// update running totals
c3 += cp + cs;
s3 = s;
} else {
// no scaling
// compute the product and product compensation
final double p = x * x;
final double cp = DD.twoSquareLow(x, p);
// compute the running sum and sum compensation
final double s = s2 + p;
final double cs = DD.twoSumLow(s2, p, s);
// update running totals
c2 += cp + cs;
s2 = s;
}
}
// The highest sum is the significant component. Add the next significant.
// Note that the "x * SCALE_DOWN * SCALE_DOWN" expressions must be executed
// in the order given. If the two scale factors are multiplied together first,
// they will underflow to zero.
if (s1 != 0) {
// add s1, s2, c1, c2
final double s2Adj = s2 * SCALE_DOWN * SCALE_DOWN;
final double sum = s1 + s2Adj;
final double comp = DD.twoSumLow(s1, s2Adj, sum) +
c1 + (c2 * SCALE_DOWN * SCALE_DOWN);
return Math.sqrt(sum + comp) * SCALE_UP;
} else if (s2 != 0) {
// add s2, s3, c2, c3
final double s3Adj = s3 * SCALE_DOWN * SCALE_DOWN;
final double sum = s2 + s3Adj;
final double comp = DD.twoSumLow(s2, s3Adj, sum) +
c2 + (c3 * SCALE_DOWN * SCALE_DOWN);
return Math.sqrt(sum + comp);
}
// add s3, c3
return Math.sqrt(s3 + c3) * SCALE_DOWN;
}