/*
* Copyright (c) 2016 Vivid Solutions.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
*
* http://www.eclipse.org/org/documents/edl-v10.php.
*/
package org.locationtech.jts.algorithm;
import org.locationtech.jts.geom.Coordinate;
/**
* This implementation is a port of Shewchuks original implementation in c
* which is placed in the public domain:
*
* [...]
* Placed in the public domain by
* Jonathan Richard Shewchuk
* School of Computer Science
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, Pennsylvania 15213-3891
* jrs@cs.cmu.edu
* [...]
*
* See http://www.cs.cmu.edu/~quake/robust.html for information about the original implementation
*
* The strategy used during porting has been to resemble the original as much as possible in order to
* be able to proofread the result. This strategy has not been followed in the following cases:
*
* - function "exactinit" has been replaced by a static block, in order to ensure that the code is only
* executed once.
*
* - The main part of the so called "tail" functions has been removed in favor to "head" functions. This means
* that all calls to such a main functions has been replaced with on call to the head function and one call
* to the tail function. The rationale for this is that the corresponding source macros has multiple output parameters
* which is not supported in Java. Using objects to pass the results to the caller was not considered for performance
* reasons. It is assumed that the extra allocations of memory would affect performance negatively.
*
* - The porting of the two_two_diff methods and the other methods involved was tricky since the original macros
* had lots of output parameters. These methods has the highest probability of bugs as a result of the porting
* operation. Each original function(macro) has been replaced with one method for each output parameter. They are
* named as *__x0, *__x2 etc. where the postfix is named after the original output parameter in the SOURCE CODE.
* The rational for the naming has been to facilitate proofreading. Each of these methods has an annotation above
* it that shows the original macro.
*
* - One bug has been found in the original source. The use of the prefix incrementation operator in
* fast_expansion_sum_zeroelim caused the code to access memory outside of the array boundary. This is not
* allowed in Java which is the reason why this bug was discovered. It is unclear if the code worked correctly
* as a compiled c-program. It has been confirmed by valgrind that this actually happens in the original code.
* The author of the original code has been contacted, and we are waiting for an answer. All occurrences of the
* prefix incrementation operator in that function have been replaced with the postfix version. This change looks
* reasonable by a quick look at the code, but this needs to be more thoroughly analyzed.
*
* - Function orientationIndex is new and its contract is copied from
* com.vividsolutions.jts.algorithm.CGAlgorithms.orientationIndex so that the current implementation of that method
* can be easily replaced.
*
* Some relevant comments in the original code has been kept untouched in its entirety. For more in-depth information
* refer to the original source.
*/
/*****************************************************************************/
/* */
/* Routines for Arbitrary Precision Floating-point Arithmetic */
/* and Fast Robust Geometric Predicates */
/* (predicates.c) */
/* */
/* May 18, 1996 */
/* */
/* Placed in the public domain by */
/* Jonathan Richard Shewchuk */
/* School of Computer Science */
/* Carnegie Mellon University */
/* 5000 Forbes Avenue */
/* Pittsburgh, Pennsylvania 15213-3891 */
/* jrs@cs.cmu.edu */
/* */
/* This file contains C implementation of algorithms for exact addition */
/* and multiplication of floating-point numbers, and predicates for */
/* robustly performing the orientation and incircle tests used in */
/* computational geometry. The algorithms and underlying theory are */
/* described in Jonathan Richard Shewchuk. "Adaptive Precision Floating- */
/* Point Arithmetic and Fast Robust Geometric Predicates." Technical */
/* Report CMU-CS-96-140, School of Computer Science, Carnegie Mellon */
/* University, Pittsburgh, Pennsylvania, May 1996. (Submitted to */
/* Discrete & Computational Geometry.) */
/* */
/* This file, the paper listed above, and other information are available */
/* from the Web page http://www.cs.cmu.edu/~quake/robust.html . */
/* */
/*****************************************************************************/
/*****************************************************************************/
/* */
/* Using this code: */
/* */
/* First, read the short or long version of the paper (from the Web page */
/* above). */
/* */
/* Be sure to call exactinit() once, before calling any of the arithmetic */
/* functions or geometric predicates. Also be sure to turn on the */
/* optimizer when compiling this file. */
/* */
/* */
/* Several geometric predicates are defined. Their parameters are all */
/* points. Each point is an array of two or three floating-point */
/* numbers. The geometric predicates, described in the papers, are */
/* */
/* orient2d(pa, pb, pc) */
/* orient2dfast(pa, pb, pc) */
/* orient3d(pa, pb, pc, pd) */
/* orient3dfast(pa, pb, pc, pd) */
/* incircle(pa, pb, pc, pd) */
/* incirclefast(pa, pb, pc, pd) */
/* insphere(pa, pb, pc, pd, pe) */
/* inspherefast(pa, pb, pc, pd, pe) */
/* */
/* Those with suffix "fast" are approximate, non-robust versions. Those */
/* without the suffix are adaptive precision, robust versions. There */
/* are also versions with the suffices "exact" and "slow", which are */
/* non-adaptive, exact arithmetic versions, which I use only for timings */
/* in my arithmetic papers. */
/* */
/* */
/* An expansion is represented by an array of floating-point numbers, */
/* sorted from smallest to largest magnitude (possibly with interspersed */
/* zeros). The length of each expansion is stored as a separate integer, */
/* and each arithmetic function returns an integer which is the length */
/* of the expansion it created. */
/* */
/* Several arithmetic functions are defined. Their parameters are */
/* */
/* e, f Input expansions */
/* elen, flen Lengths of input expansions (must be >= 1) */
/* h Output expansion */
/* b Input scalar */
/* */
/* The arithmetic functions are */
/* */
/* grow_expansion(elen, e, b, h) */
/* grow_expansion_zeroelim(elen, e, b, h) */
/* expansion_sum(elen, e, flen, f, h) */
/* expansion_sum_zeroelim1(elen, e, flen, f, h) */
/* expansion_sum_zeroelim2(elen, e, flen, f, h) */
/* fast_expansion_sum(elen, e, flen, f, h) */
/* fast_expansion_sum_zeroelim(elen, e, flen, f, h) */
/* linear_expansion_sum(elen, e, flen, f, h) */
/* linear_expansion_sum_zeroelim(elen, e, flen, f, h) */
/* scale_expansion(elen, e, b, h) */
/* scale_expansion_zeroelim(elen, e, b, h) */
/* compress(elen, e, h) */
/* */
/* All of these are described in the long version of the paper; some are */
/* described in the short version. All return an integer that is the */
/* length of h. Those with suffix _zeroelim perform zero elimination, */
/* and are recommended over their counterparts. The procedure */
/* fast_expansion_sum_zeroelim() (or linear_expansion_sum_zeroelim() on */
/* processors that do not use the round-to-even tiebreaking rule) is */
/* recommended over expansion_sum_zeroelim(). Each procedure has a */
/* little note next to it (in the code below) that tells you whether or */
/* not the output expansion may be the same array as one of the input */
/* expansions. */
/* */
/* */
/* If you look around below, you'll also find macros for a bunch of */
/* simple unrolled arithmetic operations, and procedures for printing */
/* expansions (commented out because they don't work with all C */
/* compilers) and for generating random floating-point numbers whose */
/* significand bits are all random. Most of the macros have undocumented */
/* requirements that certain of their parameters should not be the same */
/* variable; for safety, better to make sure all the parameters are */
/* distinct variables. Feel free to send email to jrs@cs.cmu.edu if you */
/* have questions. */
/* */
/*****************************************************************************/
public class ShewchuksDeterminant
{
/**
* Implements a filter for computing the orientation index of three coordinates.
* <p>
* If the orientation can be computed safely using standard DP
* arithmetic, this routine returns the orientation index.
* Otherwise, a value i > 1 is returned.
* In this case the orientation index must
* be computed using some other method.
*
* @param pa a coordinate
* @param pb a coordinate
* @param pc a coordinate
* @return the orientation index if it can be computed safely, or
* i > 1 if the orientation index cannot be computed safely
*/
public static int orientationIndexFilter(Coordinate pa, Coordinate pb, Coordinate pc)
{
double detsum;
double detleft = (pa.x - pc.x) * (pb.y - pc.y);
double detright = (pa.y - pc.y) * (pb.x - pc.x);
double det = detleft - detright;
if (detleft > 0.0) {
if (detright <= 0.0) {
return signum(det);
}
else {
detsum = detleft + detright;
}
}
else if (detleft < 0.0) {
if (detright >= 0.0) {
return signum(det);
}
else {
detsum = -detleft - detright;
}
}
else {
return signum(det);
}
double ERR_BOUND = 1e-15;
double errbound = ERR_BOUND * detsum;
//double errbound = ccwerrboundA * detsum;
if ((det >= errbound) || (-det >= errbound)) {
return signum(det);
}
return 2;
}
private static int signum(double x)
{
if (x > 0) return 1;
if (x < 0) return -1;
return 0;
}
/**
* Returns the index of the direction of the point <code>q</code> relative to
* a vector specified by <code>p1-p2</code>.
*
* @param p1
* the origin point of the vector
* @param p2
* the final point of the vector
* @param q
* the point to compute the direction to
*
* @return 1 if q is counter-clockwise (left) from p1-p2;
* -1 if q is clockwise (right) from p1-p2;
* 0 if q is collinear with p1-p2
*/
public static int orientationIndex(Coordinate p1, Coordinate p2, Coordinate q)
{
double orientation = orient2d(p1, p2, q);
if (orientation > 0.0) return 1;
if (orientation < 0.0) return -1;
return 0;
}
private static double orient2d(Coordinate pa, Coordinate pb, Coordinate pc)
{
double detsum;
double detleft = (pa.x - pc.x) * (pb.y - pc.y);
double detright = (pa.y - pc.y) * (pb.x - pc.x);
double det = detleft - detright;
if (detleft > 0.0) {
if (detright <= 0.0) {
return det;
}
else {
detsum = detleft + detright;
}
}
else if (detleft < 0.0) {
if (detright >= 0.0) {
return det;
}
else {
detsum = -detleft - detright;
}
}
else {
return det;
}
double errbound = ccwerrboundA * detsum;
if ((det >= errbound) || (-det >= errbound)) {
return det;
}
return orient2dadapt(pa, pb, pc, detsum);
}
/*****************************************************************************/
/* */
/* orient2d() Adaptive exact 2D orientation test. Robust. */
/* */
/* Return a positive value if the points pa, pb, and pc occur */
/* in counterclockwise order; a negative value if they occur */
/* in clockwise order; and zero if they are collinear. The */
/* result is also a rough approximation of twice the signed */
/* area of the triangle defined by the three points. */
/* */
/* The last three use exact arithmetic to ensure a correct answer. The */
/* result returned is the determinant of a matrix. In orient2d() only, */
/* this determinant is computed adaptively, in the sense that exact */
/* arithmetic is used only to the degree it is needed to ensure that the */
/* returned value has the correct sign. Hence, orient2d() is usually quite */
/* fast, but will run more slowly when the input points are collinear or */
/* nearly so. */
/* */
/*****************************************************************************/
private static double orient2dadapt(Coordinate pa, Coordinate pb,
Coordinate pc, double detsum)
{
double acx = pa.x - pc.x;
double bcx = pb.x - pc.x;
double acy = pa.y - pc.y;
double bcy = pb.y - pc.y;
double detleft = Two_Product_Head(acx, bcy);
double detlefttail = Two_Product_Tail(acx, bcy, detleft);
double detright = Two_Product_Head(acy, bcx);
double detrighttail = Two_Product_Tail(acy, bcx, detright);
double B[] = new double[4];
B[2] = Two_Two_Diff__x2(detleft, detlefttail, detright, detrighttail);
B[1] = Two_Two_Diff__x1(detleft, detlefttail, detright, detrighttail);
B[0] = Two_Two_Diff__x0(detleft, detlefttail, detright, detrighttail);
B[3] = Two_Two_Diff__x3(detleft, detlefttail, detright, detrighttail);
double det = B[0] + B[1] + B[2] + B[3];
//det = estimate(4, B);
double errbound = ccwerrboundB * detsum;
if ((det >= errbound) || (-det >= errbound)) {
return det;
}
double acxtail = Two_Diff_Tail(pa.x, pc.x, acx);
double bcxtail = Two_Diff_Tail(pb.x, pc.x, bcx);
double acytail = Two_Diff_Tail(pa.y, pc.y, acy);
double bcytail = Two_Diff_Tail(pb.y, pc.y, bcy);
if ((acxtail == 0.0) && (acytail == 0.0) && (bcxtail == 0.0)
&& (bcytail == 0.0)) {
return det;
}
errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);
if ((det >= errbound) || (-det >= errbound)) {
return det;
}
double s1 = Two_Product_Head(acxtail, bcy);
double s0 = Two_Product_Tail(acxtail, bcy, s1);
double t1 = Two_Product_Head(acytail, bcx);
double t0 = Two_Product_Tail(acytail, bcx, t1);
double u3 = Two_Two_Diff__x3(s1, s0, t1, t0);
double u[] = new double[4];
u[2] = Two_Two_Diff__x2(s1, s0, t1, t0);
u[1] = Two_Two_Diff__x1(s1, s0, t1, t0);
u[0] = Two_Two_Diff__x0(s1, s0, t1, t0);
u[3] = u3;
double C1[] = new double[8];
int C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
s1 = Two_Product_Head(acx, bcytail);
s0 = Two_Product_Tail(acx, bcytail, s1);
t1 = Two_Product_Head(acy, bcxtail);
t0 = Two_Product_Tail(acy, bcxtail, t1);
u3 = Two_Two_Diff__x3(s1, s0, t1, t0);
u[2] = Two_Two_Diff__x2(s1, s0, t1, t0);
u[1] = Two_Two_Diff__x1(s1, s0, t1, t0);
u[0] = Two_Two_Diff__x0(s1, s0, t1, t0);
u[3] = u3;
double C2[] = new double[12];
int C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
s1 = Two_Product_Head(acxtail, bcytail);
s0 = Two_Product_Tail(acxtail, bcytail, s1);
t1 = Two_Product_Head(acytail, bcxtail);
t0 = Two_Product_Tail(acytail, bcxtail, t1);
u3 = Two_Two_Diff__x3(s1, s0, t1, t0);
u[2] = Two_Two_Diff__x2(s1, s0, t1, t0);
u[1] = Two_Two_Diff__x1(s1, s0, t1, t0);
u[0] = Two_Two_Diff__x0(s1, s0, t1, t0);
u[3] = u3;
double D[] = new double[16];
int Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
return (D[Dlength - 1]);
}
private static final double epsilon;
private static final double splitter;
private static final double resulterrbound;
private static final double ccwerrboundA;
private static final double ccwerrboundB;
private static final double ccwerrboundC;
private static final double o3derrboundA;
private static final double o3derrboundB;
private static final double o3derrboundC;
private static final double iccerrboundA;
private static final double iccerrboundB;
private static final double iccerrboundC;
private static final double isperrboundA;
private static final double isperrboundB;
private static final double isperrboundC;
/*****************************************************************************/
/* */
/* exactinit() Initialize the variables used for exact arithmetic. */
/* */
/* `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in */
/* floating-point arithmetic. `epsilon' bounds the relative roundoff */
/* error. It is used for floating-point error analysis. */
/* */
/* `splitter' is used to split floating-point numbers into two half- */
/* length significands for exact multiplication. */
/* */
/* I imagine that a highly optimizing compiler might be too smart for its */
/* own good, and somehow cause this routine to fail, if it pretends that */
/* floating-point arithmetic is too much like real arithmetic. */
/* */
/* Don't change this routine unless you fully understand it. */
/* */
/*****************************************************************************/
static {
double epsilon_temp;
double splitter_temp;
double half;
double check, lastcheck;
int every_other;
every_other = 1;
half = 0.5;
epsilon_temp = 1.0;
splitter_temp = 1.0;
check = 1.0;
/* Repeatedly divide `epsilon' by two until it is too small to add to */
/* one without causing roundoff. (Also check if the sum is equal to */
/* the previous sum, for machines that round up instead of using exact */
/* rounding. Not that this library will work on such machines anyway. */
do {
lastcheck = check;
epsilon_temp *= half;
if (every_other != 0) {
splitter_temp *= 2.0;
}
every_other = every_other == 0 ? 1 : 0;
check = 1.0 + epsilon_temp;
} while ((check != 1.0) && (check != lastcheck));
splitter_temp += 1.0;
/* Error bounds for orientation and incircle tests. */
resulterrbound = (3.0 + 8.0 * epsilon_temp) * epsilon_temp;
ccwerrboundA = (3.0 + 16.0 * epsilon_temp) * epsilon_temp;
ccwerrboundB = (2.0 + 12.0 * epsilon_temp) * epsilon_temp;
ccwerrboundC = (9.0 + 64.0 * epsilon_temp) * epsilon_temp * epsilon_temp;
o3derrboundA = (7.0 + 56.0 * epsilon_temp) * epsilon_temp;
o3derrboundB = (3.0 + 28.0 * epsilon_temp) * epsilon_temp;
o3derrboundC = (26.0 + 288.0 * epsilon_temp) * epsilon_temp * epsilon_temp;
iccerrboundA = (10.0 + 96.0 * epsilon_temp) * epsilon_temp;
iccerrboundB = (4.0 + 48.0 * epsilon_temp) * epsilon_temp;
iccerrboundC = (44.0 + 576.0 * epsilon_temp) * epsilon_temp * epsilon_temp;
isperrboundA = (16.0 + 224.0 * epsilon_temp) * epsilon_temp;
isperrboundB = (5.0 + 72.0 * epsilon_temp) * epsilon_temp;
isperrboundC = (71.0 + 1408.0 * epsilon_temp) * epsilon_temp * epsilon_temp;
epsilon = epsilon_temp;
splitter = splitter_temp;
}
private static double Absolute(double a)
{
return ((a) >= 0.0 ? (a) : -(a));
}
private static double Fast_Two_Sum_Tail(double a, double b, double x)
{
double bvirt = x - a;
double y = b - bvirt;
return y;
}
private static double Fast_Two_Sum_Head(double a, double b)
{
double x = (double) (a + b);
return x;
}
private static double Two_Sum_Tail(double a, double b, double x)
{
double bvirt = (double) (x - a);
double avirt = x - bvirt;
double bround = b - bvirt;
double around = a - avirt;
double y = around + bround;
return y;
}
private static double Two_Sum_Head(double a, double b)
{
double x = (double) (a + b);
return x;
}
private static double Two_Diff_Tail(double a, double b, double x)
{
double bvirt = (double) (a - x); // porting issue: why this cast?
double avirt = x + bvirt;
double bround = bvirt - b;
double around = a - avirt;
double y = around + bround;
return y;
}
private static double Two_Diff_Head(double a, double b)
{
double x = (double) (a - b);
return x;
}
private static double SplitLo(double a)
{
double c = (double) (splitter * a); // porting issue: why this cast?
double abig = (double) (c - a); // porting issue: why this cast?
double ahi = c - abig;
double alo = a - ahi;
return alo;
}
private static double SplitHi(double a)
{
double c = (double) (splitter * a); // porting issue: why this cast?
double abig = (double) (c - a); // porting issue: why this cast?
double ahi = c - abig;
return ahi;
}
private static double Two_Product_Tail(double a, double b, double x)
{
double ahi = SplitHi(a);
double alo = SplitLo(a);
double bhi = SplitHi(b);
double blo = SplitLo(b);
double err1 = x - (ahi * bhi);
double err2 = err1 - (alo * bhi);
double err3 = err2 - (ahi * blo);
double y = (alo * blo) - err3;
return y;
}
private static double Two_Product_Head(double a, double b)
{
double x = (double) (a * b);
return x;
}
// #define Two_One_Diff(a1, a0, b, x2, x1, x0)
private static double Two_One_Diff__x0(double a1, double a0, double b)
{
double _i = Two_Diff_Head(a0, b);
double x0 = Two_Diff_Tail(a0, b, _i);
return x0;
}
// #define Two_One_Diff(a1, a0, b, x2, x1, x0)
private static double Two_One_Diff__x1(double a1, double a0, double b)
{
double _i = Two_Diff_Head(a0, b);
double x2 = Two_Sum_Head(a1, _i);
double x1 = Two_Sum_Tail(a1, _i, x2);
return x1;
}
// #define Two_One_Diff(a1, a0, b, x2, x1, x0)
private static double Two_One_Diff__x2(double a1, double a0, double b)
{
double _i = Two_Diff_Head(a0, b);
double x2 = Two_Sum_Head(a1, _i);
return x2;
}
// #define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0)
private static double Two_Two_Diff__x0(double a1, double a0, double b1,
double b0)
{
double x0 = Two_One_Diff__x0(a1, a0, b0);
return x0;
}
// #define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0)
private static double Two_Two_Diff__x1(double a1, double a0, double b1,
double b0)
{
double _j = Two_One_Diff__x2(a1, a0, b0);
double _0 = Two_One_Diff__x1(a1, a0, b0);
double x1 = Two_One_Diff__x0(_j, _0, b1);
return x1;
}
// #define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0)
private static double Two_Two_Diff__x2(double a1, double a0, double b1,
double b0)
{
double _j = Two_One_Diff__x2(a1, a0, b0);
double _0 = Two_One_Diff__x1(a1, a0, b0);
double x2 = Two_One_Diff__x1(_j, _0, b1);
return x2;
}
// #define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0)
private static double Two_Two_Diff__x3(double a1, double a0, double b1,
double b0)
{
double _j = Two_One_Diff__x2(a1, a0, b0);
double _0 = Two_One_Diff__x1(a1, a0, b0);
double x3 = Two_One_Diff__x2(_j, _0, b1);
return x3;
}
/*****************************************************************************/
/* */
/* fast_expansion_sum_zeroelim() Sum two expansions, eliminating zero */
/* components from the output expansion. */
/* */
/* Sets h = e + f. See the long version of my paper for details. */
/* */
/* If round-to-even is used (as with IEEE 754), maintains the strongly */
/* nonoverlapping property. (That is, if e is strongly nonoverlapping, h */
/* will be also.) Does NOT maintain the nonoverlapping or nonadjacent */
/* properties. */
/* */
/*****************************************************************************/
private static int fast_expansion_sum_zeroelim(int elen, double[] e,
int flen, double[] f, double[] h) /* h cannot be e or f. */
{
double Q;
double Qnew;
double hh;
int eindex, findex, hindex;
double enow, fnow;
enow = e[0];
fnow = f[0];
eindex = findex = 0;
if ((fnow > enow) == (fnow > -enow)) {
Q = enow;
enow = e[eindex++];
}
else {
Q = fnow;
fnow = f[findex++];
}
hindex = 0;
if ((eindex < elen) && (findex < flen)) {
if ((fnow > enow) == (fnow > -enow)) {
Qnew = Fast_Two_Sum_Head(enow, Q);
hh = Fast_Two_Sum_Tail(enow, Q, Qnew);
enow = e[eindex++];
}
else {
Qnew = Fast_Two_Sum_Head(fnow, Q);
hh = Fast_Two_Sum_Tail(fnow, Q, Qnew);
fnow = f[findex++];
}
Q = Qnew;
if (hh != 0.0) {
h[hindex++] = hh;
}
while ((eindex < elen) && (findex < flen)) {
if ((fnow > enow) == (fnow > -enow)) {
Qnew = Two_Sum_Head(Q, enow);
hh = Two_Sum_Tail(Q, enow, Qnew);
enow = e[eindex++];
}
else {
Qnew = Two_Sum_Head(Q, fnow);
hh = Two_Sum_Tail(Q, fnow, Qnew);
fnow = f[findex++];
}
Q = Qnew;
if (hh != 0.0) {
h[hindex++] = hh;
}
}
}
while (eindex < elen) {
Qnew = Two_Sum_Head(Q, enow);
hh = Two_Sum_Tail(Q, enow, Qnew);
enow = e[eindex++];
Q = Qnew;
if (hh != 0.0) {
h[hindex++] = hh;
}
}
while (findex < flen) {
Qnew = Two_Sum_Head(Q, fnow);
hh = Two_Sum_Tail(Q, fnow, Qnew);
fnow = f[findex++];
Q = Qnew;
if (hh != 0.0) {
h[hindex++] = hh;
}
}
if ((Q != 0.0) || (hindex == 0)) {
h[hindex++] = Q;
}
return hindex;
}
/*****************************************************************************/
/* */
/* estimate() Produce a one-word estimate of an expansion's value. */
/* */
/* See either version of my paper for details. */
/* */
/*****************************************************************************/
private static double estimate(int elen, double[] e)
{
double Q;
int eindex;
Q = e[0];
for (eindex = 1; eindex < elen; eindex++) {
Q += e[eindex];
}
return Q;
}
}