pcb 4.1.1
An interactive printed circuit board layout editor.

predicates.c

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*                                                                           */
00003 /*  Routines for Arbitrary Precision Floating-point Arithmetic               */
00004 /*  and Fast Robust Geometric Predicates                                     */
00005 /*  (predicates.c)                                                           */
00006 /*                                                                           */
00007 /*  May 18, 1996                                                             */
00008 /*                                                                           */
00009 /*  Placed in the public domain by                                           */
00010 /*  Jonathan Richard Shewchuk                                                */
00011 /*  School of Computer Science                                               */
00012 /*  Carnegie Mellon University                                               */
00013 /*  5000 Forbes Avenue                                                       */
00014 /*  Pittsburgh, Pennsylvania  15213-3891                                     */
00015 /*  jrs@cs.cmu.edu                                                           */
00016 /*                                                                           */
00017 /*  This file contains C implementation of algorithms for exact addition     */
00018 /*    and multiplication of floating-point numbers, and predicates for       */
00019 /*    robustly performing the orientation and incircle tests used in         */
00020 /*    computational geometry.  The algorithms and underlying theory are      */
00021 /*    described in Jonathan Richard Shewchuk.  "Adaptive Precision Floating- */
00022 /*    Point Arithmetic and Fast Robust Geometric Predicates."  Technical     */
00023 /*    Report CMU-CS-96-140, School of Computer Science, Carnegie Mellon      */
00024 /*    University, Pittsburgh, Pennsylvania, May 1996.  (Submitted to         */
00025 /*    Discrete & Computational Geometry.)                                    */
00026 /*                                                                           */
00027 /*  This file, the paper listed above, and other information are available   */
00028 /*    from the Web page http://www.cs.cmu.edu/~quake/robust.html .           */
00029 /*                                                                           */
00030 /*****************************************************************************/
00031 
00032 /*****************************************************************************/
00033 /*                                                                           */
00034 /*  Using this code:                                                         */
00035 /*                                                                           */
00036 /*  First, read the short or long version of the paper (from the Web page    */
00037 /*    above).                                                                */
00038 /*                                                                           */
00039 /*  Be sure to call exactinit() once, before calling any of the arithmetic   */
00040 /*    functions or geometric predicates.  Also be sure to turn on the        */
00041 /*    optimizer when compiling this file.                                    */
00042 /*                                                                           */
00043 /*                                                                           */
00044 /*  Several geometric predicates are defined.  Their parameters are all      */
00045 /*    points.  Each point is an array of two or three floating-point         */
00046 /*    numbers.  The geometric predicates, described in the papers, are       */
00047 /*                                                                           */
00048 /*    orient2d(pa, pb, pc)                                                   */
00049 /*    orient2dfast(pa, pb, pc)                                               */
00050 /*    orient3d(pa, pb, pc, pd)                                               */
00051 /*    orient3dfast(pa, pb, pc, pd)                                           */
00052 /*    incircle(pa, pb, pc, pd)                                               */
00053 /*    incirclefast(pa, pb, pc, pd)                                           */
00054 /*    insphere(pa, pb, pc, pd, pe)                                           */
00055 /*    inspherefast(pa, pb, pc, pd, pe)                                       */
00056 /*                                                                           */
00057 /*  Those with suffix "fast" are approximate, non-robust versions.  Those    */
00058 /*    without the suffix are adaptive precision, robust versions.  There     */
00059 /*    are also versions with the suffices "exact" and "slow", which are      */
00060 /*    non-adaptive, exact arithmetic versions, which I use only for timings  */
00061 /*    in my arithmetic papers.                                               */
00062 /*                                                                           */
00063 /*                                                                           */
00064 /*  An expansion is represented by an array of floating-point numbers,       */
00065 /*    sorted from smallest to largest magnitude (possibly with interspersed  */
00066 /*    zeros).  The length of each expansion is stored as a separate integer, */
00067 /*    and each arithmetic function returns an integer which is the length    */
00068 /*    of the expansion it created.                                           */
00069 /*                                                                           */
00070 /*  Several arithmetic functions are defined.  Their parameters are          */
00071 /*                                                                           */
00072 /*    e, f           Input expansions                                        */
00073 /*    elen, flen     Lengths of input expansions (must be >= 1)              */
00074 /*    h              Output expansion                                        */
00075 /*    b              Input scalar                                            */
00076 /*                                                                           */
00077 /*  The arithmetic functions are                                             */
00078 /*                                                                           */
00079 /*    grow_expansion(elen, e, b, h)                                          */
00080 /*    grow_expansion_zeroelim(elen, e, b, h)                                 */
00081 /*    expansion_sum(elen, e, flen, f, h)                                     */
00082 /*    expansion_sum_zeroelim1(elen, e, flen, f, h)                           */
00083 /*    expansion_sum_zeroelim2(elen, e, flen, f, h)                           */
00084 /*    fast_expansion_sum(elen, e, flen, f, h)                                */
00085 /*    fast_expansion_sum_zeroelim(elen, e, flen, f, h)                       */
00086 /*    linear_expansion_sum(elen, e, flen, f, h)                              */
00087 /*    linear_expansion_sum_zeroelim(elen, e, flen, f, h)                     */
00088 /*    scale_expansion(elen, e, b, h)                                         */
00089 /*    scale_expansion_zeroelim(elen, e, b, h)                                */
00090 /*    compress(elen, e, h)                                                   */
00091 /*                                                                           */
00092 /*  All of these are described in the long version of the paper; some are    */
00093 /*    described in the short version.  All return an integer that is the     */
00094 /*    length of h.  Those with suffix _zeroelim perform zero elimination,    */
00095 /*    and are recommended over their counterparts.  The procedure            */
00096 /*    fast_expansion_sum_zeroelim() (or linear_expansion_sum_zeroelim() on   */
00097 /*    processors that do not use the round-to-even tiebreaking rule) is      */
00098 /*    recommended over expansion_sum_zeroelim().  Each procedure has a       */
00099 /*    little note next to it (in the code below) that tells you whether or   */
00100 /*    not the output expansion may be the same array as one of the input     */
00101 /*    expansions.                                                            */
00102 /*                                                                           */
00103 /*                                                                           */
00104 /*  If you look around below, you'll also find macros for a bunch of         */
00105 /*    simple unrolled arithmetic operations, and procedures for printing     */
00106 /*    expansions (commented out because they don't work with all C           */
00107 /*    compilers) and for generating random floating-point numbers whose      */
00108 /*    significand bits are all random.  Most of the macros have undocumented */
00109 /*    requirements that certain of their parameters should not be the same   */
00110 /*    variable; for safety, better to make sure all the parameters are       */
00111 /*    distinct variables.  Feel free to send email to jrs@cs.cmu.edu if you  */
00112 /*    have questions.                                                        */
00113 /*                                                                           */
00114 /*****************************************************************************/
00115 
00116 #include <stdio.h>
00117 #include <stdlib.h>
00118 #include <math.h>
00119 #include "predicates.h"
00120 
00121 /* Use header file generated automatically by predicates_init. */
00122 //#define USE_PREDICATES_INIT
00123 
00124 #ifdef USE_PREDICATES_INIT
00125 #include "predicates_init.h"
00126 #endif /* USE_PREDICATES_INIT */
00127 
00128 /* FPU control. We MUST have only double precision (not extended precision) */
00129 #include "rounding.h"
00130 
00131 /* On some machines, the exact arithmetic routines might be defeated by the  */
00132 /*   use of internal extended precision floating-point registers.  Sometimes */
00133 /*   this problem can be fixed by defining certain values to be volatile,    */
00134 /*   thus forcing them to be stored to memory and rounded off.  This isn't   */
00135 /*   a great solution, though, as it slows the arithmetic down.              */
00136 /*                                                                           */
00137 /* To try this out, write "#define INEXACT volatile" below.  Normally,       */
00138 /*   however, INEXACT should be defined to be nothing.  ("#define INEXACT".) */
00139 
00140 #define INEXACT                          /* Nothing */
00141 /* #define INEXACT volatile */
00142 
00143 #define REAL double                      /* float or double */
00144 #define REALPRINT doubleprint
00145 #define REALRAND doublerand
00146 #define NARROWRAND narrowdoublerand
00147 #define UNIFORMRAND uniformdoublerand
00148 
00149 /* Which of the following two methods of finding the absolute values is      */
00150 /*   fastest is compiler-dependent.  A few compilers can inline and optimize */
00151 /*   the fabs() call; but most will incur the overhead of a function call,   */
00152 /*   which is disastrously slow.  A faster way on IEEE machines might be to  */
00153 /*   mask the appropriate bit, but that's difficult to do in C.              */
00154 
00155 #define Absolute(a)  ((a) >= 0.0 ? (a) : -(a))
00156 /* #define Absolute(a)  fabs(a) */
00157 
00158 /* Many of the operations are broken up into two pieces, a main part that    */
00159 /*   performs an approximate operation, and a "tail" that computes the       */
00160 /*   roundoff error of that operation.                                       */
00161 /*                                                                           */
00162 /* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(),    */
00163 /*   Split(), and Two_Product() are all implemented as described in the      */
00164 /*   reference.  Each of these macros requires certain variables to be       */
00165 /*   defined in the calling routine.  The variables `bvirt', `c', `abig',    */
00166 /*   `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because   */
00167 /*   they store the result of an operation that may incur roundoff error.    */
00168 /*   The input parameter `x' (or the highest numbered `x_' parameter) must   */
00169 /*   also be declared `INEXACT'.                                             */
00170 
00171 #define Fast_Two_Sum_Tail(a, b, x, y) \
00172   bvirt = x - a; \
00173   y = b - bvirt
00174 
00175 #define Fast_Two_Sum(a, b, x, y) \
00176   x = (REAL) (a + b); \
00177   Fast_Two_Sum_Tail(a, b, x, y)
00178 
00179 #define Fast_Two_Diff_Tail(a, b, x, y) \
00180   bvirt = a - x; \
00181   y = bvirt - b
00182 
00183 #define Fast_Two_Diff(a, b, x, y) \
00184   x = (REAL) (a - b); \
00185   Fast_Two_Diff_Tail(a, b, x, y)
00186 
00187 #define Two_Sum_Tail(a, b, x, y) \
00188   bvirt = (REAL) (x - a); \
00189   avirt = x - bvirt; \
00190   bround = b - bvirt; \
00191   around = a - avirt; \
00192   y = around + bround
00193 
00194 #define Two_Sum(a, b, x, y) \
00195   x = (REAL) (a + b); \
00196   Two_Sum_Tail(a, b, x, y)
00197 
00198 #define Two_Diff_Tail(a, b, x, y) \
00199   bvirt = (REAL) (a - x); \
00200   avirt = x + bvirt; \
00201   bround = bvirt - b; \
00202   around = a - avirt; \
00203   y = around + bround
00204 
00205 #define Two_Diff(a, b, x, y) \
00206   x = (REAL) (a - b); \
00207   Two_Diff_Tail(a, b, x, y)
00208 
00209 #define Split(a, ahi, alo) \
00210   c = (REAL) (splitter * a); \
00211   abig = (REAL) (c - a); \
00212   ahi = c - abig; \
00213   alo = a - ahi
00214 
00215 #define Two_Product_Tail(a, b, x, y) \
00216   Split(a, ahi, alo); \
00217   Split(b, bhi, blo); \
00218   err1 = x - (ahi * bhi); \
00219   err2 = err1 - (alo * bhi); \
00220   err3 = err2 - (ahi * blo); \
00221   y = (alo * blo) - err3
00222 
00223 #define Two_Product(a, b, x, y) \
00224   x = (REAL) (a * b); \
00225   Two_Product_Tail(a, b, x, y)
00226 
00227 /* Two_Product_Presplit() is Two_Product() where one of the inputs has       */
00228 /*   already been split.  Avoids redundant splitting.                        */
00229 
00230 #define Two_Product_Presplit(a, b, bhi, blo, x, y) \
00231   x = (REAL) (a * b); \
00232   Split(a, ahi, alo); \
00233   err1 = x - (ahi * bhi); \
00234   err2 = err1 - (alo * bhi); \
00235   err3 = err2 - (ahi * blo); \
00236   y = (alo * blo) - err3
00237 
00238 /* Two_Product_2Presplit() is Two_Product() where both of the inputs have    */
00239 /*   already been split.  Avoids redundant splitting.                        */
00240 
00241 #define Two_Product_2Presplit(a, ahi, alo, b, bhi, blo, x, y) \
00242   x = (REAL) (a * b); \
00243   err1 = x - (ahi * bhi); \
00244   err2 = err1 - (alo * bhi); \
00245   err3 = err2 - (ahi * blo); \
00246   y = (alo * blo) - err3
00247 
00248 /* Square() can be done more quickly than Two_Product().                     */
00249 
00250 #define Square_Tail(a, x, y) \
00251   Split(a, ahi, alo); \
00252   err1 = x - (ahi * ahi); \
00253   err3 = err1 - ((ahi + ahi) * alo); \
00254   y = (alo * alo) - err3
00255 
00256 #define Square(a, x, y) \
00257   x = (REAL) (a * a); \
00258   Square_Tail(a, x, y)
00259 
00260 /* Macros for summing expansions of various fixed lengths.  These are all    */
00261 /*   unrolled versions of Expansion_Sum().                                   */
00262 
00263 #define Two_One_Sum(a1, a0, b, x2, x1, x0) \
00264   Two_Sum(a0, b , _i, x0); \
00265   Two_Sum(a1, _i, x2, x1)
00266 
00267 #define Two_One_Diff(a1, a0, b, x2, x1, x0) \
00268   Two_Diff(a0, b , _i, x0); \
00269   Two_Sum( a1, _i, x2, x1)
00270 
00271 #define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
00272   Two_One_Sum(a1, a0, b0, _j, _0, x0); \
00273   Two_One_Sum(_j, _0, b1, x3, x2, x1)
00274 
00275 #define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
00276   Two_One_Diff(a1, a0, b0, _j, _0, x0); \
00277   Two_One_Diff(_j, _0, b1, x3, x2, x1)
00278 
00279 #define Four_One_Sum(a3, a2, a1, a0, b, x4, x3, x2, x1, x0) \
00280   Two_One_Sum(a1, a0, b , _j, x1, x0); \
00281   Two_One_Sum(a3, a2, _j, x4, x3, x2)
00282 
00283 #define Four_Two_Sum(a3, a2, a1, a0, b1, b0, x5, x4, x3, x2, x1, x0) \
00284   Four_One_Sum(a3, a2, a1, a0, b0, _k, _2, _1, _0, x0); \
00285   Four_One_Sum(_k, _2, _1, _0, b1, x5, x4, x3, x2, x1)
00286 
00287 #define Four_Four_Sum(a3, a2, a1, a0, b4, b3, b1, b0, x7, x6, x5, x4, x3, x2, \
00288                       x1, x0) \
00289   Four_Two_Sum(a3, a2, a1, a0, b1, b0, _l, _2, _1, _0, x1, x0); \
00290   Four_Two_Sum(_l, _2, _1, _0, b4, b3, x7, x6, x5, x4, x3, x2)
00291 
00292 #define Eight_One_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b, x8, x7, x6, x5, x4, \
00293                       x3, x2, x1, x0) \
00294   Four_One_Sum(a3, a2, a1, a0, b , _j, x3, x2, x1, x0); \
00295   Four_One_Sum(a7, a6, a5, a4, _j, x8, x7, x6, x5, x4)
00296 
00297 #define Eight_Two_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b1, b0, x9, x8, x7, \
00298                       x6, x5, x4, x3, x2, x1, x0) \
00299   Eight_One_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b0, _k, _6, _5, _4, _3, _2, \
00300                 _1, _0, x0); \
00301   Eight_One_Sum(_k, _6, _5, _4, _3, _2, _1, _0, b1, x9, x8, x7, x6, x5, x4, \
00302                 x3, x2, x1)
00303 
00304 #define Eight_Four_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b4, b3, b1, b0, x11, \
00305                        x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0) \
00306   Eight_Two_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b1, b0, _l, _6, _5, _4, _3, \
00307                 _2, _1, _0, x1, x0); \
00308   Eight_Two_Sum(_l, _6, _5, _4, _3, _2, _1, _0, b4, b3, x11, x10, x9, x8, \
00309                 x7, x6, x5, x4, x3, x2)
00310 
00311 /* Macros for multiplying expansions of various fixed lengths.               */
00312 
00313 #define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
00314   Split(b, bhi, blo); \
00315   Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
00316   Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
00317   Two_Sum(_i, _0, _k, x1); \
00318   Fast_Two_Sum(_j, _k, x3, x2)
00319 
00320 #define Four_One_Product(a3, a2, a1, a0, b, x7, x6, x5, x4, x3, x2, x1, x0) \
00321   Split(b, bhi, blo); \
00322   Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
00323   Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
00324   Two_Sum(_i, _0, _k, x1); \
00325   Fast_Two_Sum(_j, _k, _i, x2); \
00326   Two_Product_Presplit(a2, b, bhi, blo, _j, _0); \
00327   Two_Sum(_i, _0, _k, x3); \
00328   Fast_Two_Sum(_j, _k, _i, x4); \
00329   Two_Product_Presplit(a3, b, bhi, blo, _j, _0); \
00330   Two_Sum(_i, _0, _k, x5); \
00331   Fast_Two_Sum(_j, _k, x7, x6)
00332 
00333 #define Two_Two_Product(a1, a0, b1, b0, x7, x6, x5, x4, x3, x2, x1, x0) \
00334   Split(a0, a0hi, a0lo); \
00335   Split(b0, bhi, blo); \
00336   Two_Product_2Presplit(a0, a0hi, a0lo, b0, bhi, blo, _i, x0); \
00337   Split(a1, a1hi, a1lo); \
00338   Two_Product_2Presplit(a1, a1hi, a1lo, b0, bhi, blo, _j, _0); \
00339   Two_Sum(_i, _0, _k, _1); \
00340   Fast_Two_Sum(_j, _k, _l, _2); \
00341   Split(b1, bhi, blo); \
00342   Two_Product_2Presplit(a0, a0hi, a0lo, b1, bhi, blo, _i, _0); \
00343   Two_Sum(_1, _0, _k, x1); \
00344   Two_Sum(_2, _k, _j, _1); \
00345   Two_Sum(_l, _j, _m, _2); \
00346   Two_Product_2Presplit(a1, a1hi, a1lo, b1, bhi, blo, _j, _0); \
00347   Two_Sum(_i, _0, _n, _0); \
00348   Two_Sum(_1, _0, _i, x2); \
00349   Two_Sum(_2, _i, _k, _1); \
00350   Two_Sum(_m, _k, _l, _2); \
00351   Two_Sum(_j, _n, _k, _0); \
00352   Two_Sum(_1, _0, _j, x3); \
00353   Two_Sum(_2, _j, _i, _1); \
00354   Two_Sum(_l, _i, _m, _2); \
00355   Two_Sum(_1, _k, _i, x4); \
00356   Two_Sum(_2, _i, _k, x5); \
00357   Two_Sum(_m, _k, x7, x6)
00358 
00359 /* An expansion of length two can be squared more quickly than finding the   */
00360 /*   product of two different expansions of length two, and the result is    */
00361 /*   guaranteed to have no more than six (rather than eight) components.     */
00362 
00363 #define Two_Square(a1, a0, x5, x4, x3, x2, x1, x0) \
00364   Square(a0, _j, x0); \
00365   _0 = a0 + a0; \
00366   Two_Product(a1, _0, _k, _1); \
00367   Two_One_Sum(_k, _1, _j, _l, _2, x1); \
00368   Square(a1, _j, _1); \
00369   Two_Two_Sum(_j, _1, _l, _2, x5, x4, x3, x2)
00370 
00371 #ifndef USE_PREDICATES_INIT
00372 
00373 static REAL splitter;     /* = 2^ceiling(p / 2) + 1.  Used to split floats in half. */
00374 /* A set of coefficients used to calculate maximum roundoff errors.          */
00375 static REAL resulterrbound;
00376 static REAL ccwerrboundA, ccwerrboundB, ccwerrboundC;
00377 static REAL o3derrboundA, o3derrboundB, o3derrboundC;
00378 static REAL iccerrboundA, iccerrboundB, iccerrboundC;
00379 static REAL isperrboundA, isperrboundB, isperrboundC;
00380 
00381 void 
00382 gts_predicates_init()
00383 {
00384   double half = 0.5;
00385   double check = 1.0, lastcheck;
00386   int every_other = 1;
00387   /* epsilon = 2^(-p).  Used to estimate roundoff errors. */
00388   double epsilon = 1.0;   
00389 
00390   FPU_ROUND_DOUBLE;
00391 
00392   splitter = 1.;
00393 
00394   /* Repeatedly divide `epsilon' by two until it is too small to add to   */
00395   /* one without causing roundoff.  (Also check if the sum is equal to    */
00396   /* the previous sum, for machines that round up instead of using exact  */
00397   /* rounding.  Not that this library will work on such machines anyway). */
00398   do {
00399     lastcheck = check;
00400     epsilon *= half;
00401     if (every_other) {
00402       splitter *= 2.0;
00403     }
00404     every_other = !every_other;
00405     check = 1.0 + epsilon;
00406   } while ((check != 1.0) && (check != lastcheck));
00407   splitter += 1.0;
00408   /* Error bounds for orientation and incircle tests. */
00409   resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
00410   ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
00411   ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
00412   ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
00413   o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
00414   o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
00415   o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
00416   iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
00417   iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
00418   iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
00419   isperrboundA = (16.0 + 224.0 * epsilon) * epsilon;
00420   isperrboundB = (5.0 + 72.0 * epsilon) * epsilon;
00421   isperrboundC = (71.0 + 1408.0 * epsilon) * epsilon * epsilon;
00422 
00423 
00424   FPU_RESTORE;
00425 }
00426 
00427 #endif /* USE_PREDICATES_INIT */
00428 
00429 /*****************************************************************************/
00430 /*                                                                           */
00431 /*  doubleprint()   Print the bit representation of a double.                */
00432 /*                                                                           */
00433 /*  Useful for debugging exact arithmetic routines.                          */
00434 /*                                                                           */
00435 /*****************************************************************************/
00436 
00437 /*
00438 void doubleprint(number)
00439 double number;
00440 {
00441   unsigned long long no;
00442   unsigned long long sign, expo;
00443   int exponent;
00444   int i, bottomi;
00445 
00446   no = *(unsigned long long *) &number;
00447   sign = no & 0x8000000000000000ll;
00448   expo = (no >> 52) & 0x7ffll;
00449   exponent = (int) expo;
00450   exponent = exponent - 1023;
00451   if (sign) {
00452     printf("-");
00453   } else {
00454     printf(" ");
00455   }
00456   if (exponent == -1023) {
00457     printf(
00458       "0.0000000000000000000000000000000000000000000000000000_     (   )");
00459   } else {
00460     printf("1.");
00461     bottomi = -1;
00462     for (i = 0; i < 52; i++) {
00463       if (no & 0x0008000000000000ll) {
00464         printf("1");
00465         bottomi = i;
00466       } else {
00467         printf("0");
00468       }
00469       no <<= 1;
00470     }
00471     printf("_%d  (%d)", exponent, exponent - 1 - bottomi);
00472   }
00473 }
00474 */
00475 
00476 /*****************************************************************************/
00477 /*                                                                           */
00478 /*  floatprint()   Print the bit representation of a float.                  */
00479 /*                                                                           */
00480 /*  Useful for debugging exact arithmetic routines.                          */
00481 /*                                                                           */
00482 /*****************************************************************************/
00483 
00484 /*
00485 void floatprint(number)
00486 float number;
00487 {
00488   unsigned no;
00489   unsigned sign, expo;
00490   int exponent;
00491   int i, bottomi;
00492 
00493   no = *(unsigned *) &number;
00494   sign = no & 0x80000000;
00495   expo = (no >> 23) & 0xff;
00496   exponent = (int) expo;
00497   exponent = exponent - 127;
00498   if (sign) {
00499     printf("-");
00500   } else {
00501     printf(" ");
00502   }
00503   if (exponent == -127) {
00504     printf("0.00000000000000000000000_     (   )");
00505   } else {
00506     printf("1.");
00507     bottomi = -1;
00508     for (i = 0; i < 23; i++) {
00509       if (no & 0x00400000) {
00510         printf("1");
00511         bottomi = i;
00512       } else {
00513         printf("0");
00514       }
00515       no <<= 1;
00516     }
00517     printf("_%3d  (%3d)", exponent, exponent - 1 - bottomi);
00518   }
00519 }
00520 */
00521 
00522 /*****************************************************************************/
00523 /*                                                                           */
00524 /*  expansion_print()   Print the bit representation of an expansion.        */
00525 /*                                                                           */
00526 /*  Useful for debugging exact arithmetic routines.                          */
00527 /*                                                                           */
00528 /*****************************************************************************/
00529 
00530 /*
00531 void expansion_print(elen, e)
00532 int elen;
00533 REAL *e;
00534 {
00535   int i;
00536 
00537   for (i = elen - 1; i >= 0; i--) {
00538     REALPRINT(e[i]);
00539     if (i > 0) {
00540       printf(" +\n");
00541     } else {
00542       printf("\n");
00543     }
00544   }
00545 }
00546 */
00547 
00548 /*****************************************************************************/
00549 /*                                                                           */
00550 /*  doublerand()   Generate a double with random 53-bit significand and a    */
00551 /*                 random exponent in [0, 511].                              */
00552 /*                                                                           */
00553 /*****************************************************************************/
00554 
00555 /*
00556 static double doublerand()
00557 {
00558   double result;
00559   double expo;
00560   long a, b, c;
00561   long i;
00562 
00563   a = random();
00564   b = random();
00565   c = random();
00566   result = (double) (a - 1073741824) * 8388608.0 + (double) (b >> 8);
00567   for (i = 512, expo = 2; i <= 131072; i *= 2, expo = expo * expo) {
00568     if (c & i) {
00569       result *= expo;
00570     }
00571   }
00572   return result;
00573 }
00574 */
00575 
00576 /*****************************************************************************/
00577 /*                                                                           */
00578 /*  narrowdoublerand()   Generate a double with random 53-bit significand    */
00579 /*                       and a random exponent in [0, 7].                    */
00580 /*                                                                           */
00581 /*****************************************************************************/
00582 
00583 /*
00584 static double narrowdoublerand()
00585 {
00586   double result;
00587   double expo;
00588   long a, b, c;
00589   long i;
00590 
00591   a = random();
00592   b = random();
00593   c = random();
00594   result = (double) (a - 1073741824) * 8388608.0 + (double) (b >> 8);
00595   for (i = 512, expo = 2; i <= 2048; i *= 2, expo = expo * expo) {
00596     if (c & i) {
00597       result *= expo;
00598     }
00599   }
00600   return result;
00601 }
00602 */
00603 
00604 /*****************************************************************************/
00605 /*                                                                           */
00606 /*  uniformdoublerand()   Generate a double with random 53-bit significand.  */
00607 /*                                                                           */
00608 /*****************************************************************************/
00609 
00610 /*
00611 static double uniformdoublerand()
00612 {
00613   double result;
00614   long a, b;
00615 
00616   a = random();
00617   b = random();
00618   result = (double) (a - 1073741824) * 8388608.0 + (double) (b >> 8);
00619   return result;
00620 }
00621 */
00622 
00623 /*****************************************************************************/
00624 /*                                                                           */
00625 /*  floatrand()   Generate a float with random 24-bit significand and a      */
00626 /*                random exponent in [0, 63].                                */
00627 /*                                                                           */
00628 /*****************************************************************************/
00629 
00630 /*
00631 static float floatrand()
00632 {
00633   float result;
00634   float expo;
00635   long a, c;
00636   long i;
00637 
00638   a = random();
00639   c = random();
00640   result = (float) ((a - 1073741824) >> 6);
00641   for (i = 512, expo = 2; i <= 16384; i *= 2, expo = expo * expo) {
00642     if (c & i) {
00643       result *= expo;
00644     }
00645   }
00646   return result;
00647 }
00648 */
00649 
00650 /*****************************************************************************/
00651 /*                                                                           */
00652 /*  narrowfloatrand()   Generate a float with random 24-bit significand and  */
00653 /*                      a random exponent in [0, 7].                         */
00654 /*                                                                           */
00655 /*****************************************************************************/
00656 
00657 /*
00658 static float narrowfloatrand()
00659 {
00660   float result;
00661   float expo;
00662   long a, c;
00663   long i;
00664 
00665   a = random();
00666   c = random();
00667   result = (float) ((a - 1073741824) >> 6);
00668   for (i = 512, expo = 2; i <= 2048; i *= 2, expo = expo * expo) {
00669     if (c & i) {
00670       result *= expo;
00671     }
00672   }
00673   return result;
00674 }
00675 */
00676 
00677 /*****************************************************************************/
00678 /*                                                                           */
00679 /*  uniformfloatrand()   Generate a float with random 24-bit significand.    */
00680 /*                                                                           */
00681 /*****************************************************************************/
00682 
00683 /*
00684 static float uniformfloatrand()
00685 {
00686   float result;
00687   long a;
00688 
00689   a = random();
00690   result = (float) ((a - 1073741824) >> 6);
00691   return result;
00692 }
00693 */
00694 
00695 /*****************************************************************************/
00696 /*                                                                           */
00697 /*  fast_expansion_sum_zeroelim()   Sum two expansions, eliminating zero     */
00698 /*                                  components from the output expansion.    */
00699 /*                                                                           */
00700 /*  Sets h = e + f.  See the long version of my paper for details.           */
00701 /*                                                                           */
00702 /*  If round-to-even is used (as with IEEE 754), maintains the strongly      */
00703 /*  nonoverlapping property.  (That is, if e is strongly nonoverlapping, h   */
00704 /*  will be also.)  Does NOT maintain the nonoverlapping or nonadjacent      */
00705 /*  properties.                                                              */
00706 /*                                                                           */
00707 /*****************************************************************************/
00708 
00709 static int fast_expansion_sum_zeroelim(int elen, REAL *e, 
00710                                        int flen, REAL *f, REAL *h)
00711      /* h cannot be e or f. */
00712 {
00713   REAL Q;
00714   INEXACT REAL Qnew;
00715   INEXACT REAL hh;
00716   INEXACT REAL bvirt;
00717   REAL avirt, bround, around;
00718   int eindex, findex, hindex;
00719   REAL enow, fnow;
00720 
00721   enow = e[0];
00722   fnow = f[0];
00723   eindex = findex = 0;
00724   if ((fnow > enow) == (fnow > -enow)) {
00725     Q = enow;
00726     enow = e[++eindex];
00727   } else {
00728     Q = fnow;
00729     fnow = f[++findex];
00730   }
00731   hindex = 0;
00732   if ((eindex < elen) && (findex < flen)) {
00733     if ((fnow > enow) == (fnow > -enow)) {
00734       Fast_Two_Sum(enow, Q, Qnew, hh);
00735       enow = e[++eindex];
00736     } else {
00737       Fast_Two_Sum(fnow, Q, Qnew, hh);
00738       fnow = f[++findex];
00739     }
00740     Q = Qnew;
00741     if (hh != 0.0) {
00742       h[hindex++] = hh;
00743     }
00744     while ((eindex < elen) && (findex < flen)) {
00745       if ((fnow > enow) == (fnow > -enow)) {
00746         Two_Sum(Q, enow, Qnew, hh);
00747         enow = e[++eindex];
00748       } else {
00749         Two_Sum(Q, fnow, Qnew, hh);
00750         fnow = f[++findex];
00751       }
00752       Q = Qnew;
00753       if (hh != 0.0) {
00754         h[hindex++] = hh;
00755       }
00756     }
00757   }
00758   while (eindex < elen) {
00759     Two_Sum(Q, enow, Qnew, hh);
00760     enow = e[++eindex];
00761     Q = Qnew;
00762     if (hh != 0.0) {
00763       h[hindex++] = hh;
00764     }
00765   }
00766   while (findex < flen) {
00767     Two_Sum(Q, fnow, Qnew, hh);
00768     fnow = f[++findex];
00769     Q = Qnew;
00770     if (hh != 0.0) {
00771       h[hindex++] = hh;
00772     }
00773   }
00774   if ((Q != 0.0) || (hindex == 0)) {
00775     h[hindex++] = Q;
00776   }
00777   return hindex;
00778 }
00779 
00780 /*****************************************************************************/
00781 /*                                                                           */
00782 /*  scale_expansion_zeroelim()   Multiply an expansion by a scalar,          */
00783 /*                               eliminating zero components from the        */
00784 /*                               output expansion.                           */
00785 /*                                                                           */
00786 /*  Sets h = be.  See either version of my paper for details.                */
00787 /*                                                                           */
00788 /*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
00789 /*  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent    */
00790 /*  properties as well.  (That is, if e has one of these properties, so      */
00791 /*  will h.)                                                                 */
00792 /*                                                                           */
00793 /*****************************************************************************/
00794 
00795 static int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h)
00796      /* e and h cannot be the same. */
00797 {
00798   INEXACT REAL Q, sum;
00799   REAL hh;
00800   INEXACT REAL product1;
00801   REAL product0;
00802   int eindex, hindex;
00803   REAL enow;
00804   INEXACT REAL bvirt;
00805   REAL avirt, bround, around;
00806   INEXACT REAL c;
00807   INEXACT REAL abig;
00808   REAL ahi, alo, bhi, blo;
00809   REAL err1, err2, err3;
00810 
00811   Split(b, bhi, blo);
00812   Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
00813   hindex = 0;
00814   if (hh != 0) {
00815     h[hindex++] = hh;
00816   }
00817   for (eindex = 1; eindex < elen; eindex++) {
00818     enow = e[eindex];
00819     Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
00820     Two_Sum(Q, product0, sum, hh);
00821     if (hh != 0) {
00822       h[hindex++] = hh;
00823     }
00824     Fast_Two_Sum(product1, sum, Q, hh);
00825     if (hh != 0) {
00826       h[hindex++] = hh;
00827     }
00828   }
00829   if ((Q != 0.0) || (hindex == 0)) {
00830     h[hindex++] = Q;
00831   }
00832   return hindex;
00833 }
00834 
00835 /*****************************************************************************/
00836 /*                                                                           */
00837 /*  estimate()   Produce a one-word estimate of an expansion's value.        */
00838 /*                                                                           */
00839 /*  See either version of my paper for details.                              */
00840 /*                                                                           */
00841 /*****************************************************************************/
00842 
00843 static REAL estimate(int elen, REAL *e)
00844 {
00845   REAL Q;
00846   int eindex;
00847 
00848   Q = e[0];
00849   for (eindex = 1; eindex < elen; eindex++) {
00850     Q += e[eindex];
00851   }
00852   return Q;
00853 }
00854 
00855 /*****************************************************************************/
00856 /*                                                                           */
00857 /*  orient2dfast()   Approximate 2D orientation test.  Nonrobust.            */
00858 /*  orient2dexact()   Exact 2D orientation test.  Robust.                    */
00859 /*  orient2dslow()   Another exact 2D orientation test.  Robust.             */
00860 /*  orient2d()   Adaptive exact 2D orientation test.  Robust.                */
00861 /*                                                                           */
00862 /*               Return a positive value if the points pa, pb, and pc occur  */
00863 /*               in counterclockwise order; a negative value if they occur   */
00864 /*               in clockwise order; and zero if they are collinear.  The    */
00865 /*               result is also a rough approximation of twice the signed    */
00866 /*               area of the triangle defined by the three points.           */
00867 /*                                                                           */
00868 /*  Only the first and last routine should be used; the middle two are for   */
00869 /*  timings.                                                                 */
00870 /*                                                                           */
00871 /*  The last three use exact arithmetic to ensure a correct answer.  The     */
00872 /*  result returned is the determinant of a matrix.  In orient2d() only,     */
00873 /*  this determinant is computed adaptively, in the sense that exact         */
00874 /*  arithmetic is used only to the degree it is needed to ensure that the    */
00875 /*  returned value has the correct sign.  Hence, orient2d() is usually quite */
00876 /*  fast, but will run more slowly when the input points are collinear or    */
00877 /*  nearly so.                                                               */
00878 /*                                                                           */
00879 /*****************************************************************************/
00880 
00881 static REAL orient2dadapt(REAL *pa, REAL *pb, REAL *pc, REAL detsum)
00882 {
00883   INEXACT REAL acx, acy, bcx, bcy;
00884   REAL acxtail, acytail, bcxtail, bcytail;
00885   INEXACT REAL detleft, detright;
00886   REAL detlefttail, detrighttail;
00887   REAL det, errbound;
00888   REAL B[4], C1[8], C2[12], D[16];
00889   INEXACT REAL B3;
00890   int C1length, C2length, Dlength;
00891   REAL u[4];
00892   INEXACT REAL u3;
00893   INEXACT REAL s1, t1;
00894   REAL s0, t0;
00895 
00896   INEXACT REAL bvirt;
00897   REAL avirt, bround, around;
00898   INEXACT REAL c;
00899   INEXACT REAL abig;
00900   REAL ahi, alo, bhi, blo;
00901   REAL err1, err2, err3;
00902   INEXACT REAL _i, _j;
00903   REAL _0;
00904 
00905   acx = (REAL) (pa[0] - pc[0]);
00906   bcx = (REAL) (pb[0] - pc[0]);
00907   acy = (REAL) (pa[1] - pc[1]);
00908   bcy = (REAL) (pb[1] - pc[1]);
00909 
00910   Two_Product(acx, bcy, detleft, detlefttail);
00911   Two_Product(acy, bcx, detright, detrighttail);
00912 
00913   Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
00914                B3, B[2], B[1], B[0]);
00915   B[3] = B3;
00916 
00917   det = estimate(4, B);
00918   errbound = ccwerrboundB * detsum;
00919   if ((det >= errbound) || (-det >= errbound)) {
00920     return det;
00921   }
00922 
00923   Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
00924   Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
00925   Two_Diff_Tail(pa[1], pc[1], acy, acytail);
00926   Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
00927 
00928   if ((acxtail == 0.0) && (acytail == 0.0)
00929       && (bcxtail == 0.0) && (bcytail == 0.0)) {
00930     return det;
00931   }
00932 
00933   errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
00934   det += (acx * bcytail + bcy * acxtail)
00935        - (acy * bcxtail + bcx * acytail);
00936   if ((det >= errbound) || (-det >= errbound)) {
00937     return det;
00938   }
00939 
00940   Two_Product(acxtail, bcy, s1, s0);
00941   Two_Product(acytail, bcx, t1, t0);
00942   Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
00943   u[3] = u3;
00944   C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
00945 
00946   Two_Product(acx, bcytail, s1, s0);
00947   Two_Product(acy, bcxtail, t1, t0);
00948   Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
00949   u[3] = u3;
00950   C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
00951 
00952   Two_Product(acxtail, bcytail, s1, s0);
00953   Two_Product(acytail, bcxtail, t1, t0);
00954   Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
00955   u[3] = u3;
00956   Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
00957 
00958   return(D[Dlength - 1]);
00959 }
00960 
00961 REAL orient2d(pa, pb, pc)
00962 REAL *pa;
00963 REAL *pb;
00964 REAL *pc;
00965 {
00966   REAL detleft, detright, det;
00967   REAL detsum, errbound;
00968   REAL orient;
00969 
00970   FPU_ROUND_DOUBLE;
00971 
00972   detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
00973   detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
00974   det = detleft - detright;
00975 
00976   if (detleft > 0.0) {
00977     if (detright <= 0.0) {
00978       FPU_RESTORE;
00979       return det;
00980     } else {
00981       detsum = detleft + detright;
00982     }
00983   } else if (detleft < 0.0) {
00984     if (detright >= 0.0) {
00985       FPU_RESTORE;
00986       return det;
00987     } else {
00988       detsum = -detleft - detright;
00989     }
00990   } else {
00991     FPU_RESTORE;
00992     return det;
00993   }
00994 
00995   errbound = ccwerrboundA * detsum;
00996   if ((det >= errbound) || (-det >= errbound)) {
00997     FPU_RESTORE;
00998     return det;
00999   }
01000 
01001   orient = orient2dadapt(pa, pb, pc, detsum);
01002   FPU_RESTORE;
01003   return orient;
01004 }
01005 
01006 /*****************************************************************************/
01007 /*                                                                           */
01008 /*  orient3dfast()   Approximate 3D orientation test.  Nonrobust.            */
01009 /*  orient3dexact()   Exact 3D orientation test.  Robust.                    */
01010 /*  orient3dslow()   Another exact 3D orientation test.  Robust.             */
01011 /*  orient3d()   Adaptive exact 3D orientation test.  Robust.                */
01012 /*                                                                           */
01013 /*               Return a positive value if the point pd lies below the      */
01014 /*               plane passing through pa, pb, and pc; "below" is defined so */
01015 /*               that pa, pb, and pc appear in counterclockwise order when   */
01016 /*               viewed from above the plane.  Returns a negative value if   */
01017 /*               pd lies above the plane.  Returns zero if the points are    */
01018 /*               coplanar.  The result is also a rough approximation of six  */
01019 /*               times the signed volume of the tetrahedron defined by the   */
01020 /*               four points.                                                */
01021 /*                                                                           */
01022 /*  Only the first and last routine should be used; the middle two are for   */
01023 /*  timings.                                                                 */
01024 /*                                                                           */
01025 /*  The last three use exact arithmetic to ensure a correct answer.  The     */
01026 /*  result returned is the determinant of a matrix.  In orient3d() only,     */
01027 /*  this determinant is computed adaptively, in the sense that exact         */
01028 /*  arithmetic is used only to the degree it is needed to ensure that the    */
01029 /*  returned value has the correct sign.  Hence, orient3d() is usually quite */
01030 /*  fast, but will run more slowly when the input points are coplanar or     */
01031 /*  nearly so.                                                               */
01032 /*                                                                           */
01033 /*****************************************************************************/
01034 
01035 static REAL orient3dadapt(REAL *pa, REAL *pb, REAL *pc, REAL *pd, 
01036                           REAL permanent)
01037 {
01038   INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adz, bdz, cdz;
01039   REAL det, errbound;
01040 
01041   INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
01042   REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
01043   REAL bc[4], ca[4], ab[4];
01044   INEXACT REAL bc3, ca3, ab3;
01045   REAL adet[8], bdet[8], cdet[8];
01046   int alen, blen, clen;
01047   REAL abdet[16];
01048   int ablen;
01049   REAL *finnow, *finother, *finswap;
01050   REAL fin1[192], fin2[192];
01051   int finlength;
01052 
01053   REAL adxtail, bdxtail, cdxtail;
01054   REAL adytail, bdytail, cdytail;
01055   REAL adztail, bdztail, cdztail;
01056   INEXACT REAL at_blarge, at_clarge;
01057   INEXACT REAL bt_clarge, bt_alarge;
01058   INEXACT REAL ct_alarge, ct_blarge;
01059   REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
01060   int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
01061   INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1;
01062   INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1;
01063   REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
01064   REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
01065   INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1;
01066   INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1;
01067   REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
01068   REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
01069   REAL bct[8], cat[8], abt[8];
01070   int bctlen, catlen, abtlen;
01071   INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
01072   INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1;
01073   REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
01074   REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
01075   REAL u[4], v[12], w[16];
01076   INEXACT REAL u3;
01077   int vlength, wlength;
01078   REAL negate;
01079 
01080   INEXACT REAL bvirt;
01081   REAL avirt, bround, around;
01082   INEXACT REAL c;
01083   INEXACT REAL abig;
01084   REAL ahi, alo, bhi, blo;
01085   REAL err1, err2, err3;
01086   INEXACT REAL _i, _j, _k;
01087   REAL _0;
01088 
01089   adx = (REAL) (pa[0] - pd[0]);
01090   bdx = (REAL) (pb[0] - pd[0]);
01091   cdx = (REAL) (pc[0] - pd[0]);
01092   ady = (REAL) (pa[1] - pd[1]);
01093   bdy = (REAL) (pb[1] - pd[1]);
01094   cdy = (REAL) (pc[1] - pd[1]);
01095   adz = (REAL) (pa[2] - pd[2]);
01096   bdz = (REAL) (pb[2] - pd[2]);
01097   cdz = (REAL) (pc[2] - pd[2]);
01098 
01099   Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
01100   Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
01101   Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
01102   bc[3] = bc3;
01103   alen = scale_expansion_zeroelim(4, bc, adz, adet);
01104 
01105   Two_Product(cdx, ady, cdxady1, cdxady0);
01106   Two_Product(adx, cdy, adxcdy1, adxcdy0);
01107   Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
01108   ca[3] = ca3;
01109   blen = scale_expansion_zeroelim(4, ca, bdz, bdet);
01110 
01111   Two_Product(adx, bdy, adxbdy1, adxbdy0);
01112   Two_Product(bdx, ady, bdxady1, bdxady0);
01113   Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
01114   ab[3] = ab3;
01115   clen = scale_expansion_zeroelim(4, ab, cdz, cdet);
01116 
01117   ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
01118   finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
01119 
01120   det = estimate(finlength, fin1);
01121   errbound = o3derrboundB * permanent;
01122   if ((det >= errbound) || (-det >= errbound)) {
01123     return det;
01124   }
01125 
01126   Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
01127   Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
01128   Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
01129   Two_Diff_Tail(pa[1], pd[1], ady, adytail);
01130   Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
01131   Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
01132   Two_Diff_Tail(pa[2], pd[2], adz, adztail);
01133   Two_Diff_Tail(pb[2], pd[2], bdz, bdztail);
01134   Two_Diff_Tail(pc[2], pd[2], cdz, cdztail);
01135 
01136   if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
01137       && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)
01138       && (adztail == 0.0) && (bdztail == 0.0) && (cdztail == 0.0)) {
01139     return det;
01140   }
01141 
01142   errbound = o3derrboundC * permanent + resulterrbound * Absolute(det);
01143   det += (adz * ((bdx * cdytail + cdy * bdxtail)
01144                  - (bdy * cdxtail + cdx * bdytail))
01145           + adztail * (bdx * cdy - bdy * cdx))
01146        + (bdz * ((cdx * adytail + ady * cdxtail)
01147                  - (cdy * adxtail + adx * cdytail))
01148           + bdztail * (cdx * ady - cdy * adx))
01149        + (cdz * ((adx * bdytail + bdy * adxtail)
01150                  - (ady * bdxtail + bdx * adytail))
01151           + cdztail * (adx * bdy - ady * bdx));
01152   if ((det >= errbound) || (-det >= errbound)) {
01153     return det;
01154   }
01155 
01156   finnow = fin1;
01157   finother = fin2;
01158 
01159   if (adxtail == 0.0) {
01160     if (adytail == 0.0) {
01161       at_b[0] = 0.0;
01162       at_blen = 1;
01163       at_c[0] = 0.0;
01164       at_clen = 1;
01165     } else {
01166       negate = -adytail;
01167       Two_Product(negate, bdx, at_blarge, at_b[0]);
01168       at_b[1] = at_blarge;
01169       at_blen = 2;
01170       Two_Product(adytail, cdx, at_clarge, at_c[0]);
01171       at_c[1] = at_clarge;
01172       at_clen = 2;
01173     }
01174   } else {
01175     if (adytail == 0.0) {
01176       Two_Product(adxtail, bdy, at_blarge, at_b[0]);
01177       at_b[1] = at_blarge;
01178       at_blen = 2;
01179       negate = -adxtail;
01180       Two_Product(negate, cdy, at_clarge, at_c[0]);
01181       at_c[1] = at_clarge;
01182       at_clen = 2;
01183     } else {
01184       Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0);
01185       Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0);
01186       Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
01187                    at_blarge, at_b[2], at_b[1], at_b[0]);
01188       at_b[3] = at_blarge;
01189       at_blen = 4;
01190       Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0);
01191       Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0);
01192       Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
01193                    at_clarge, at_c[2], at_c[1], at_c[0]);
01194       at_c[3] = at_clarge;
01195       at_clen = 4;
01196     }
01197   }
01198   if (bdxtail == 0.0) {
01199     if (bdytail == 0.0) {
01200       bt_c[0] = 0.0;
01201       bt_clen = 1;
01202       bt_a[0] = 0.0;
01203       bt_alen = 1;
01204     } else {
01205       negate = -bdytail;
01206       Two_Product(negate, cdx, bt_clarge, bt_c[0]);
01207       bt_c[1] = bt_clarge;
01208       bt_clen = 2;
01209       Two_Product(bdytail, adx, bt_alarge, bt_a[0]);
01210       bt_a[1] = bt_alarge;
01211       bt_alen = 2;
01212     }
01213   } else {
01214     if (bdytail == 0.0) {
01215       Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]);
01216       bt_c[1] = bt_clarge;
01217       bt_clen = 2;
01218       negate = -bdxtail;
01219       Two_Product(negate, ady, bt_alarge, bt_a[0]);
01220       bt_a[1] = bt_alarge;
01221       bt_alen = 2;
01222     } else {
01223       Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
01224       Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
01225       Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
01226                    bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
01227       bt_c[3] = bt_clarge;
01228       bt_clen = 4;
01229       Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0);
01230       Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0);
01231       Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
01232                   bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
01233       bt_a[3] = bt_alarge;
01234       bt_alen = 4;
01235     }
01236   }
01237   if (cdxtail == 0.0) {
01238     if (cdytail == 0.0) {
01239       ct_a[0] = 0.0;
01240       ct_alen = 1;
01241       ct_b[0] = 0.0;
01242       ct_blen = 1;
01243     } else {
01244       negate = -cdytail;
01245       Two_Product(negate, adx, ct_alarge, ct_a[0]);
01246       ct_a[1] = ct_alarge;
01247       ct_alen = 2;
01248       Two_Product(cdytail, bdx, ct_blarge, ct_b[0]);
01249       ct_b[1] = ct_blarge;
01250       ct_blen = 2;
01251     }
01252   } else {
01253     if (cdytail == 0.0) {
01254       Two_Product(cdxtail, ady, ct_alarge, ct_a[0]);
01255       ct_a[1] = ct_alarge;
01256       ct_alen = 2;
01257       negate = -cdxtail;
01258       Two_Product(negate, bdy, ct_blarge, ct_b[0]);
01259       ct_b[1] = ct_blarge;
01260       ct_blen = 2;
01261     } else {
01262       Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0);
01263       Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0);
01264       Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
01265                    ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
01266       ct_a[3] = ct_alarge;
01267       ct_alen = 4;
01268       Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
01269       Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
01270       Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
01271                    ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
01272       ct_b[3] = ct_blarge;
01273       ct_blen = 4;
01274     }
01275   }
01276 
01277   bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct);
01278   wlength = scale_expansion_zeroelim(bctlen, bct, adz, w);
01279   finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
01280                                           finother);
01281   finswap = finnow; finnow = finother; finother = finswap;
01282 
01283   catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat);
01284   wlength = scale_expansion_zeroelim(catlen, cat, bdz, w);
01285   finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
01286                                           finother);
01287   finswap = finnow; finnow = finother; finother = finswap;
01288 
01289   abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt);
01290   wlength = scale_expansion_zeroelim(abtlen, abt, cdz, w);
01291   finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
01292                                           finother);
01293   finswap = finnow; finnow = finother; finother = finswap;
01294 
01295   if (adztail != 0.0) {
01296     vlength = scale_expansion_zeroelim(4, bc, adztail, v);
01297     finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
01298                                             finother);
01299     finswap = finnow; finnow = finother; finother = finswap;
01300   }
01301   if (bdztail != 0.0) {
01302     vlength = scale_expansion_zeroelim(4, ca, bdztail, v);
01303     finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
01304                                             finother);
01305     finswap = finnow; finnow = finother; finother = finswap;
01306   }
01307   if (cdztail != 0.0) {
01308     vlength = scale_expansion_zeroelim(4, ab, cdztail, v);
01309     finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
01310                                             finother);
01311     finswap = finnow; finnow = finother; finother = finswap;
01312   }
01313 
01314   if (adxtail != 0.0) {
01315     if (bdytail != 0.0) {
01316       Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
01317       Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdz, u3, u[2], u[1], u[0]);
01318       u[3] = u3;
01319       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
01320                                               finother);
01321       finswap = finnow; finnow = finother; finother = finswap;
01322       if (cdztail != 0.0) {
01323         Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdztail, u3, u[2], u[1], u[0]);
01324         u[3] = u3;
01325         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
01326                                                 finother);
01327         finswap = finnow; finnow = finother; finother = finswap;
01328       }
01329     }
01330     if (cdytail != 0.0) {
01331       negate = -adxtail;
01332       Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
01333       Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdz, u3, u[2], u[1], u[0]);
01334       u[3] = u3;
01335       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
01336                                               finother);
01337       finswap = finnow; finnow = finother; finother = finswap;
01338       if (bdztail != 0.0) {
01339         Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdztail, u3, u[2], u[1], u[0]);
01340         u[3] = u3;
01341         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
01342                                                 finother);
01343         finswap = finnow; finnow = finother; finother = finswap;
01344       }
01345     }
01346   }
01347   if (bdxtail != 0.0) {
01348     if (cdytail != 0.0) {
01349       Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
01350       Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adz, u3, u[2], u[1], u[0]);
01351       u[3] = u3;
01352       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
01353                                               finother);
01354       finswap = finnow; finnow = finother; finother = finswap;
01355       if (adztail != 0.0) {
01356         Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adztail, u3, u[2], u[1], u[0]);
01357         u[3] = u3;
01358         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
01359                                                 finother);
01360         finswap = finnow; finnow = finother; finother = finswap;
01361       }
01362     }
01363     if (adytail != 0.0) {
01364       negate = -bdxtail;
01365       Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
01366       Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdz, u3, u[2], u[1], u[0]);
01367       u[3] = u3;
01368       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
01369                                               finother);
01370       finswap = finnow; finnow = finother; finother = finswap;
01371       if (cdztail != 0.0) {
01372         Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdztail, u3, u[2], u[1], u[0]);
01373         u[3] = u3;
01374         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
01375                                                 finother);
01376         finswap = finnow; finnow = finother; finother = finswap;
01377       }
01378     }
01379   }
01380   if (cdxtail != 0.0) {
01381     if (adytail != 0.0) {
01382       Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
01383       Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdz, u3, u[2], u[1], u[0]);
01384       u[3] = u3;
01385       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
01386                                               finother);
01387       finswap = finnow; finnow = finother; finother = finswap;
01388       if (bdztail != 0.0) {
01389         Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdztail, u3, u[2], u[1], u[0]);
01390         u[3] = u3;
01391         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
01392                                                 finother);
01393         finswap = finnow; finnow = finother; finother = finswap;
01394       }
01395     }
01396     if (bdytail != 0.0) {
01397       negate = -cdxtail;
01398       Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
01399       Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adz, u3, u[2], u[1], u[0]);
01400       u[3] = u3;
01401       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
01402                                               finother);
01403       finswap = finnow; finnow = finother; finother = finswap;
01404       if (adztail != 0.0) {
01405         Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adztail, u3, u[2], u[1], u[0]);
01406         u[3] = u3;
01407         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
01408                                                 finother);
01409         finswap = finnow; finnow = finother; finother = finswap;
01410       }
01411     }
01412   }
01413 
01414   if (adztail != 0.0) {
01415     wlength = scale_expansion_zeroelim(bctlen, bct, adztail, w);
01416     finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
01417                                             finother);
01418     finswap = finnow; finnow = finother; finother = finswap;
01419   }
01420   if (bdztail != 0.0) {
01421     wlength = scale_expansion_zeroelim(catlen, cat, bdztail, w);
01422     finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
01423                                             finother);
01424     finswap = finnow; finnow = finother; finother = finswap;
01425   }
01426   if (cdztail != 0.0) {
01427     wlength = scale_expansion_zeroelim(abtlen, abt, cdztail, w);
01428     finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
01429                                             finother);
01430     finswap = finnow; finnow = finother; finother = finswap;
01431   }
01432 
01433   return finnow[finlength - 1];
01434 }
01435 
01436 REAL orient3d(pa, pb, pc, pd)
01437 REAL *pa;
01438 REAL *pb;
01439 REAL *pc;
01440 REAL *pd;
01441 {
01442   REAL adx, bdx, cdx, ady, bdy, cdy, adz, bdz, cdz;
01443   REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
01444   REAL det;
01445   REAL permanent, errbound;
01446   REAL orient;
01447 
01448   FPU_ROUND_DOUBLE;
01449 
01450   adx = pa[0] - pd[0];
01451   bdx = pb[0] - pd[0];
01452   cdx = pc[0] - pd[0];
01453   ady = pa[1] - pd[1];
01454   bdy = pb[1] - pd[1];
01455   cdy = pc[1] - pd[1];
01456   adz = pa[2] - pd[2];
01457   bdz = pb[2] - pd[2];
01458   cdz = pc[2] - pd[2];
01459 
01460   bdxcdy = bdx * cdy;
01461   cdxbdy = cdx * bdy;
01462 
01463   cdxady = cdx * ady;
01464   adxcdy = adx * cdy;
01465 
01466   adxbdy = adx * bdy;
01467   bdxady = bdx * ady;
01468 
01469   det = adz * (bdxcdy - cdxbdy) 
01470       + bdz * (cdxady - adxcdy)
01471       + cdz * (adxbdy - bdxady);
01472 
01473   permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adz)
01474             + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdz)
01475             + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdz);
01476   errbound = o3derrboundA * permanent;
01477   if ((det > errbound) || (-det > errbound)) {
01478     FPU_RESTORE;
01479     return det;
01480   }
01481 
01482   orient = orient3dadapt(pa, pb, pc, pd, permanent);
01483   FPU_RESTORE;
01484   return orient;
01485 }
01486 
01487 /*****************************************************************************/
01488 /*                                                                           */
01489 /*  incirclefast()   Approximate 2D incircle test.  Nonrobust.               */
01490 /*  incircleexact()   Exact 2D incircle test.  Robust.                       */
01491 /*  incircleslow()   Another exact 2D incircle test.  Robust.                */
01492 /*  incircle()   Adaptive exact 2D incircle test.  Robust.                   */
01493 /*                                                                           */
01494 /*               Return a positive value if the point pd lies inside the     */
01495 /*               circle passing through pa, pb, and pc; a negative value if  */
01496 /*               it lies outside; and zero if the four points are cocircular.*/
01497 /*               The points pa, pb, and pc must be in counterclockwise       */
01498 /*               order, or the sign of the result will be reversed.          */
01499 /*                                                                           */
01500 /*  Only the first and last routine should be used; the middle two are for   */
01501 /*  timings.                                                                 */
01502 /*                                                                           */
01503 /*  The last three use exact arithmetic to ensure a correct answer.  The     */
01504 /*  result returned is the determinant of a matrix.  In incircle() only,     */
01505 /*  this determinant is computed adaptively, in the sense that exact         */
01506 /*  arithmetic is used only to the degree it is needed to ensure that the    */
01507 /*  returned value has the correct sign.  Hence, incircle() is usually quite */
01508 /*  fast, but will run more slowly when the input points are cocircular or   */
01509 /*  nearly so.                                                               */
01510 /*                                                                           */
01511 /*****************************************************************************/
01512 
01513 static REAL incircleadapt(REAL *pa, REAL *pb, REAL *pc, REAL *pd, 
01514                           REAL permanent)
01515 {
01516   INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
01517   REAL det, errbound;
01518 
01519   INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
01520   REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
01521   REAL bc[4], ca[4], ab[4];
01522   INEXACT REAL bc3, ca3, ab3;
01523   REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
01524   int axbclen, axxbclen, aybclen, ayybclen, alen;
01525   REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
01526   int bxcalen, bxxcalen, bycalen, byycalen, blen;
01527   REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
01528   int cxablen, cxxablen, cyablen, cyyablen, clen;
01529   REAL abdet[64];
01530   int ablen;
01531   REAL fin1[1152], fin2[1152];
01532   REAL *finnow, *finother, *finswap;
01533   int finlength;
01534 
01535   REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
01536   INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
01537   REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
01538   REAL aa[4], bb[4], cc[4];
01539   INEXACT REAL aa3, bb3, cc3;
01540   INEXACT REAL ti1, tj1;
01541   REAL ti0, tj0;
01542   REAL u[4], v[4];
01543   INEXACT REAL u3, v3;
01544   REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
01545   REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
01546   int temp8len, temp16alen, temp16blen, temp16clen;
01547   int temp32alen, temp32blen, temp48len, temp64len;
01548   REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
01549   int axtbblen, axtcclen, aytbblen, aytcclen;
01550   REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
01551   int bxtaalen, bxtcclen, bytaalen, bytcclen;
01552   REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
01553   int cxtaalen, cxtbblen, cytaalen, cytbblen;
01554   REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
01555   int axtbclen = 0, aytbclen = 0;
01556   int bxtcalen = 0, bytcalen = 0;
01557   int cxtablen = 0, cytablen = 0;
01558   REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
01559   int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
01560   REAL axtbctt[8], aytbctt[8], bxtcatt[8];
01561   REAL bytcatt[8], cxtabtt[8], cytabtt[8];
01562   int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
01563   REAL abt[8], bct[8], cat[8];
01564   int abtlen, bctlen, catlen;
01565   REAL abtt[4], bctt[4], catt[4];
01566   int abttlen, bcttlen, cattlen;
01567   INEXACT REAL abtt3, bctt3, catt3;
01568   REAL negate;
01569 
01570   INEXACT REAL bvirt;
01571   REAL avirt, bround, around;
01572   INEXACT REAL c;
01573   INEXACT REAL abig;
01574   REAL ahi, alo, bhi, blo;
01575   REAL err1, err2, err3;
01576   INEXACT REAL _i, _j;
01577   REAL _0;
01578 
01579   adx = (REAL) (pa[0] - pd[0]);
01580   bdx = (REAL) (pb[0] - pd[0]);
01581   cdx = (REAL) (pc[0] - pd[0]);
01582   ady = (REAL) (pa[1] - pd[1]);
01583   bdy = (REAL) (pb[1] - pd[1]);
01584   cdy = (REAL) (pc[1] - pd[1]);
01585 
01586   Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
01587   Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
01588   Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
01589   bc[3] = bc3;
01590   axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
01591   axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
01592   aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
01593   ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
01594   alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
01595 
01596   Two_Product(cdx, ady, cdxady1, cdxady0);
01597   Two_Product(adx, cdy, adxcdy1, adxcdy0);
01598   Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
01599   ca[3] = ca3;
01600   bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
01601   bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
01602   bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
01603   byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
01604   blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
01605 
01606   Two_Product(adx, bdy, adxbdy1, adxbdy0);
01607   Two_Product(bdx, ady, bdxady1, bdxady0);
01608   Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
01609   ab[3] = ab3;
01610   cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
01611   cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
01612   cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
01613   cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
01614   clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
01615 
01616   ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
01617   finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
01618 
01619   det = estimate(finlength, fin1);
01620   errbound = iccerrboundB * permanent;
01621   if ((det >= errbound) || (-det >= errbound)) {
01622     return det;
01623   }
01624 
01625   Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
01626   Two_Diff_Tail(pa[1], pd[1], ady, adytail);
01627   Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
01628   Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
01629   Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
01630   Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
01631   if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
01632       && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
01633     return det;
01634   }
01635 
01636   errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
01637   det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
01638                                      - (bdy * cdxtail + cdx * bdytail))
01639           + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
01640        + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
01641                                      - (cdy * adxtail + adx * cdytail))
01642           + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
01643        + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
01644                                      - (ady * bdxtail + bdx * adytail))
01645           + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
01646   if ((det >= errbound) || (-det >= errbound)) {
01647     return det;
01648   }
01649 
01650   finnow = fin1;
01651   finother = fin2;
01652 
01653   if ((bdxtail != 0.0) || (bdytail != 0.0)
01654       || (cdxtail != 0.0) || (cdytail != 0.0)) {
01655     Square(adx, adxadx1, adxadx0);
01656     Square(ady, adyady1, adyady0);
01657     Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
01658     aa[3] = aa3;
01659   }
01660   if ((cdxtail != 0.0) || (cdytail != 0.0)
01661       || (adxtail != 0.0) || (adytail != 0.0)) {
01662     Square(bdx, bdxbdx1, bdxbdx0);
01663     Square(bdy, bdybdy1, bdybdy0);
01664     Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
01665     bb[3] = bb3;
01666   }
01667   if ((adxtail != 0.0) || (adytail != 0.0)
01668       || (bdxtail != 0.0) || (bdytail != 0.0)) {
01669     Square(cdx, cdxcdx1, cdxcdx0);
01670     Square(cdy, cdycdy1, cdycdy0);
01671     Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
01672     cc[3] = cc3;
01673   }
01674 
01675   if (adxtail != 0.0) {
01676     axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
01677     temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
01678                                           temp16a);
01679 
01680     axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
01681     temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
01682 
01683     axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
01684     temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
01685 
01686     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01687                                             temp16blen, temp16b, temp32a);
01688     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
01689                                             temp32alen, temp32a, temp48);
01690     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
01691                                             temp48, finother);
01692     finswap = finnow; finnow = finother; finother = finswap;
01693   }
01694   if (adytail != 0.0) {
01695     aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
01696     temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
01697                                           temp16a);
01698 
01699     aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
01700     temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
01701 
01702     aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
01703     temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
01704 
01705     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01706                                             temp16blen, temp16b, temp32a);
01707     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
01708                                             temp32alen, temp32a, temp48);
01709     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
01710                                             temp48, finother);
01711     finswap = finnow; finnow = finother; finother = finswap;
01712   }
01713   if (bdxtail != 0.0) {
01714     bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
01715     temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
01716                                           temp16a);
01717 
01718     bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
01719     temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
01720 
01721     bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
01722     temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
01723 
01724     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01725                                             temp16blen, temp16b, temp32a);
01726     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
01727                                             temp32alen, temp32a, temp48);
01728     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
01729                                             temp48, finother);
01730     finswap = finnow; finnow = finother; finother = finswap;
01731   }
01732   if (bdytail != 0.0) {
01733     bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
01734     temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
01735                                           temp16a);
01736 
01737     bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
01738     temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
01739 
01740     bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
01741     temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
01742 
01743     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01744                                             temp16blen, temp16b, temp32a);
01745     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
01746                                             temp32alen, temp32a, temp48);
01747     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
01748                                             temp48, finother);
01749     finswap = finnow; finnow = finother; finother = finswap;
01750   }
01751   if (cdxtail != 0.0) {
01752     cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
01753     temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
01754                                           temp16a);
01755 
01756     cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
01757     temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
01758 
01759     cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
01760     temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
01761 
01762     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01763                                             temp16blen, temp16b, temp32a);
01764     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
01765                                             temp32alen, temp32a, temp48);
01766     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
01767                                             temp48, finother);
01768     finswap = finnow; finnow = finother; finother = finswap;
01769   }
01770   if (cdytail != 0.0) {
01771     cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
01772     temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
01773                                           temp16a);
01774 
01775     cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
01776     temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
01777 
01778     cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
01779     temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
01780 
01781     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01782                                             temp16blen, temp16b, temp32a);
01783     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
01784                                             temp32alen, temp32a, temp48);
01785     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
01786                                             temp48, finother);
01787     finswap = finnow; finnow = finother; finother = finswap;
01788   }
01789 
01790   if ((adxtail != 0.0) || (adytail != 0.0)) {
01791     if ((bdxtail != 0.0) || (bdytail != 0.0)
01792         || (cdxtail != 0.0) || (cdytail != 0.0)) {
01793       Two_Product(bdxtail, cdy, ti1, ti0);
01794       Two_Product(bdx, cdytail, tj1, tj0);
01795       Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
01796       u[3] = u3;
01797       negate = -bdy;
01798       Two_Product(cdxtail, negate, ti1, ti0);
01799       negate = -bdytail;
01800       Two_Product(cdx, negate, tj1, tj0);
01801       Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
01802       v[3] = v3;
01803       bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
01804 
01805       Two_Product(bdxtail, cdytail, ti1, ti0);
01806       Two_Product(cdxtail, bdytail, tj1, tj0);
01807       Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
01808       bctt[3] = bctt3;
01809       bcttlen = 4;
01810     } else {
01811       bct[0] = 0.0;
01812       bctlen = 1;
01813       bctt[0] = 0.0;
01814       bcttlen = 1;
01815     }
01816 
01817     if (adxtail != 0.0) {
01818       temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
01819       axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
01820       temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
01821                                             temp32a);
01822       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01823                                               temp32alen, temp32a, temp48);
01824       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
01825                                               temp48, finother);
01826       finswap = finnow; finnow = finother; finother = finswap;
01827       if (bdytail != 0.0) {
01828         temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
01829         temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
01830                                               temp16a);
01831         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
01832                                                 temp16a, finother);
01833         finswap = finnow; finnow = finother; finother = finswap;
01834       }
01835       if (cdytail != 0.0) {
01836         temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
01837         temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
01838                                               temp16a);
01839         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
01840                                                 temp16a, finother);
01841         finswap = finnow; finnow = finother; finother = finswap;
01842       }
01843 
01844       temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
01845                                             temp32a);
01846       axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
01847       temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
01848                                             temp16a);
01849       temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
01850                                             temp16b);
01851       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01852                                               temp16blen, temp16b, temp32b);
01853       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
01854                                               temp32blen, temp32b, temp64);
01855       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
01856                                               temp64, finother);
01857       finswap = finnow; finnow = finother; finother = finswap;
01858     }
01859     if (adytail != 0.0) {
01860       temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
01861       aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
01862       temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
01863                                             temp32a);
01864       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01865                                               temp32alen, temp32a, temp48);
01866       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
01867                                               temp48, finother);
01868       finswap = finnow; finnow = finother; finother = finswap;
01869 
01870 
01871       temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
01872                                             temp32a);
01873       aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
01874       temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
01875                                             temp16a);
01876       temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
01877                                             temp16b);
01878       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01879                                               temp16blen, temp16b, temp32b);
01880       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
01881                                               temp32blen, temp32b, temp64);
01882       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
01883                                               temp64, finother);
01884       finswap = finnow; finnow = finother; finother = finswap;
01885     }
01886   }
01887   if ((bdxtail != 0.0) || (bdytail != 0.0)) {
01888     if ((cdxtail != 0.0) || (cdytail != 0.0)
01889         || (adxtail != 0.0) || (adytail != 0.0)) {
01890       Two_Product(cdxtail, ady, ti1, ti0);
01891       Two_Product(cdx, adytail, tj1, tj0);
01892       Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
01893       u[3] = u3;
01894       negate = -cdy;
01895       Two_Product(adxtail, negate, ti1, ti0);
01896       negate = -cdytail;
01897       Two_Product(adx, negate, tj1, tj0);
01898       Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
01899       v[3] = v3;
01900       catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
01901 
01902       Two_Product(cdxtail, adytail, ti1, ti0);
01903       Two_Product(adxtail, cdytail, tj1, tj0);
01904       Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
01905       catt[3] = catt3;
01906       cattlen = 4;
01907     } else {
01908       cat[0] = 0.0;
01909       catlen = 1;
01910       catt[0] = 0.0;
01911       cattlen = 1;
01912     }
01913 
01914     if (bdxtail != 0.0) {
01915       temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
01916       bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
01917       temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
01918                                             temp32a);
01919       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01920                                               temp32alen, temp32a, temp48);
01921       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
01922                                               temp48, finother);
01923       finswap = finnow; finnow = finother; finother = finswap;
01924       if (cdytail != 0.0) {
01925         temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
01926         temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
01927                                               temp16a);
01928         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
01929                                                 temp16a, finother);
01930         finswap = finnow; finnow = finother; finother = finswap;
01931       }
01932       if (adytail != 0.0) {
01933         temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
01934         temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
01935                                               temp16a);
01936         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
01937                                                 temp16a, finother);
01938         finswap = finnow; finnow = finother; finother = finswap;
01939       }
01940 
01941       temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
01942                                             temp32a);
01943       bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
01944       temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
01945                                             temp16a);
01946       temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
01947                                             temp16b);
01948       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01949                                               temp16blen, temp16b, temp32b);
01950       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
01951                                               temp32blen, temp32b, temp64);
01952       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
01953                                               temp64, finother);
01954       finswap = finnow; finnow = finother; finother = finswap;
01955     }
01956     if (bdytail != 0.0) {
01957       temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
01958       bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
01959       temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
01960                                             temp32a);
01961       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01962                                               temp32alen, temp32a, temp48);
01963       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
01964                                               temp48, finother);
01965       finswap = finnow; finnow = finother; finother = finswap;
01966 
01967 
01968       temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
01969                                             temp32a);
01970       bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
01971       temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
01972                                             temp16a);
01973       temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
01974                                             temp16b);
01975       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
01976                                               temp16blen, temp16b, temp32b);
01977       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
01978                                               temp32blen, temp32b, temp64);
01979       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
01980                                               temp64, finother);
01981       finswap = finnow; finnow = finother; finother = finswap;
01982     }
01983   }
01984   if ((cdxtail != 0.0) || (cdytail != 0.0)) {
01985     if ((adxtail != 0.0) || (adytail != 0.0)
01986         || (bdxtail != 0.0) || (bdytail != 0.0)) {
01987       Two_Product(adxtail, bdy, ti1, ti0);
01988       Two_Product(adx, bdytail, tj1, tj0);
01989       Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
01990       u[3] = u3;
01991       negate = -ady;
01992       Two_Product(bdxtail, negate, ti1, ti0);
01993       negate = -adytail;
01994       Two_Product(bdx, negate, tj1, tj0);
01995       Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
01996       v[3] = v3;
01997       abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
01998 
01999       Two_Product(adxtail, bdytail, ti1, ti0);
02000       Two_Product(bdxtail, adytail, tj1, tj0);
02001       Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
02002       abtt[3] = abtt3;
02003       abttlen = 4;
02004     } else {
02005       abt[0] = 0.0;
02006       abtlen = 1;
02007       abtt[0] = 0.0;
02008       abttlen = 1;
02009     }
02010 
02011     if (cdxtail != 0.0) {
02012       temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
02013       cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
02014       temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
02015                                             temp32a);
02016       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
02017                                               temp32alen, temp32a, temp48);
02018       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
02019                                               temp48, finother);
02020       finswap = finnow; finnow = finother; finother = finswap;
02021       if (adytail != 0.0) {
02022         temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
02023         temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
02024                                               temp16a);
02025         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
02026                                                 temp16a, finother);
02027         finswap = finnow; finnow = finother; finother = finswap;
02028       }
02029       if (bdytail != 0.0) {
02030         temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
02031         temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
02032                                               temp16a);
02033         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
02034                                                 temp16a, finother);
02035         finswap = finnow; finnow = finother; finother = finswap;
02036       }
02037 
02038       temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
02039                                             temp32a);
02040       cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
02041       temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
02042                                             temp16a);
02043       temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
02044                                             temp16b);
02045       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
02046                                               temp16blen, temp16b, temp32b);
02047       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
02048                                               temp32blen, temp32b, temp64);
02049       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
02050                                               temp64, finother);
02051       finswap = finnow; finnow = finother; finother = finswap;
02052     }
02053     if (cdytail != 0.0) {
02054       temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
02055       cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
02056       temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
02057                                             temp32a);
02058       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
02059                                               temp32alen, temp32a, temp48);
02060       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
02061                                               temp48, finother);
02062       finswap = finnow; finnow = finother; finother = finswap;
02063 
02064 
02065       temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
02066                                             temp32a);
02067       cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
02068       temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
02069                                             temp16a);
02070       temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
02071                                             temp16b);
02072       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
02073                                               temp16blen, temp16b, temp32b);
02074       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
02075                                               temp32blen, temp32b, temp64);
02076       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
02077                                               temp64, finother);
02078       finswap = finnow; finnow = finother; finother = finswap;
02079     }
02080   }
02081 
02082   return finnow[finlength - 1];
02083 }
02084 
02085 REAL incircle(pa, pb, pc, pd)
02086 REAL *pa;
02087 REAL *pb;
02088 REAL *pc;
02089 REAL *pd;
02090 {
02091   REAL adx, bdx, cdx, ady, bdy, cdy;
02092   REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
02093   REAL alift, blift, clift;
02094   REAL det;
02095   REAL permanent, errbound;
02096   REAL inc;
02097 
02098   FPU_ROUND_DOUBLE;
02099   
02100   adx = pa[0] - pd[0];
02101   bdx = pb[0] - pd[0];
02102   cdx = pc[0] - pd[0];
02103   ady = pa[1] - pd[1];
02104   bdy = pb[1] - pd[1];
02105   cdy = pc[1] - pd[1];
02106 
02107   bdxcdy = bdx * cdy;
02108   cdxbdy = cdx * bdy;
02109   alift = adx * adx + ady * ady;
02110 
02111   cdxady = cdx * ady;
02112   adxcdy = adx * cdy;
02113   blift = bdx * bdx + bdy * bdy;
02114 
02115   adxbdy = adx * bdy;
02116   bdxady = bdx * ady;
02117   clift = cdx * cdx + cdy * cdy;
02118 
02119   det = alift * (bdxcdy - cdxbdy)
02120       + blift * (cdxady - adxcdy)
02121       + clift * (adxbdy - bdxady);
02122 
02123   permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
02124             + (Absolute(cdxady) + Absolute(adxcdy)) * blift
02125             + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
02126   errbound = iccerrboundA * permanent;
02127   if ((det > errbound) || (-det > errbound)) {
02128     FPU_RESTORE;
02129     return det;
02130   }
02131 
02132   inc = incircleadapt(pa, pb, pc, pd, permanent);
02133   FPU_RESTORE;
02134   return inc;
02135 }
02136 
02137 /*****************************************************************************/
02138 /*                                                                           */
02139 /*  inspherefast()   Approximate 3D insphere test.  Nonrobust.               */
02140 /*  insphereexact()   Exact 3D insphere test.  Robust.                       */
02141 /*  insphereslow()   Another exact 3D insphere test.  Robust.                */
02142 /*  insphere()   Adaptive exact 3D insphere test.  Robust.                   */
02143 /*                                                                           */
02144 /*               Return a positive value if the point pe lies inside the     */
02145 /*               sphere passing through pa, pb, pc, and pd; a negative value */
02146 /*               if it lies outside; and zero if the five points are         */
02147 /*               cospherical.  The points pa, pb, pc, and pd must be ordered */
02148 /*               so that they have a positive orientation (as defined by     */
02149 /*               orient3d()), or the sign of the result will be reversed.    */
02150 /*                                                                           */
02151 /*  Only the first and last routine should be used; the middle two are for   */
02152 /*  timings.                                                                 */
02153 /*                                                                           */
02154 /*  The last three use exact arithmetic to ensure a correct answer.  The     */
02155 /*  result returned is the determinant of a matrix.  In insphere() only,     */
02156 /*  this determinant is computed adaptively, in the sense that exact         */
02157 /*  arithmetic is used only to the degree it is needed to ensure that the    */
02158 /*  returned value has the correct sign.  Hence, insphere() is usually quite */
02159 /*  fast, but will run more slowly when the input points are cospherical or  */
02160 /*  nearly so.                                                               */
02161 /*                                                                           */
02162 /*****************************************************************************/
02163 
02164 static REAL insphereexact(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe)
02165 {
02166   INEXACT REAL axby1, bxcy1, cxdy1, dxey1, exay1;
02167   INEXACT REAL bxay1, cxby1, dxcy1, exdy1, axey1;
02168   INEXACT REAL axcy1, bxdy1, cxey1, dxay1, exby1;
02169   INEXACT REAL cxay1, dxby1, excy1, axdy1, bxey1;
02170   REAL axby0, bxcy0, cxdy0, dxey0, exay0;
02171   REAL bxay0, cxby0, dxcy0, exdy0, axey0;
02172   REAL axcy0, bxdy0, cxey0, dxay0, exby0;
02173   REAL cxay0, dxby0, excy0, axdy0, bxey0;
02174   REAL ab[4], bc[4], cd[4], de[4], ea[4];
02175   REAL ac[4], bd[4], ce[4], da[4], eb[4];
02176   REAL temp8a[8], temp8b[8], temp16[16];
02177   int temp8alen, temp8blen, temp16len;
02178   REAL abc[24], bcd[24], cde[24], dea[24], eab[24];
02179   REAL abd[24], bce[24], cda[24], deb[24], eac[24];
02180   int abclen, bcdlen, cdelen, dealen, eablen;
02181   int abdlen, bcelen, cdalen, deblen, eaclen;
02182   REAL temp48a[48], temp48b[48];
02183   int temp48alen, temp48blen;
02184   REAL abcd[96], bcde[96], cdea[96], deab[96], eabc[96];
02185   int abcdlen, bcdelen, cdealen, deablen, eabclen;
02186   REAL temp192[192];
02187   REAL det384x[384], det384y[384], det384z[384];
02188   int xlen, ylen, zlen;
02189   REAL detxy[768];
02190   int xylen;
02191   REAL adet[1152], bdet[1152], cdet[1152], ddet[1152], edet[1152];
02192   int alen, blen, clen, dlen, elen;
02193   REAL abdet[2304], cddet[2304], cdedet[3456];
02194   int ablen, cdlen;
02195   REAL deter[5760];
02196   int deterlen;
02197   int i;
02198 
02199   INEXACT REAL bvirt;
02200   REAL avirt, bround, around;
02201   INEXACT REAL c;
02202   INEXACT REAL abig;
02203   REAL ahi, alo, bhi, blo;
02204   REAL err1, err2, err3;
02205   INEXACT REAL _i, _j;
02206   REAL _0;
02207 
02208   Two_Product(pa[0], pb[1], axby1, axby0);
02209   Two_Product(pb[0], pa[1], bxay1, bxay0);
02210   Two_Two_Diff(axby1, axby0, bxay1, bxay0, ab[3], ab[2], ab[1], ab[0]);
02211 
02212   Two_Product(pb[0], pc[1], bxcy1, bxcy0);
02213   Two_Product(pc[0], pb[1], cxby1, cxby0);
02214   Two_Two_Diff(bxcy1, bxcy0, cxby1, cxby0, bc[3], bc[2], bc[1], bc[0]);
02215 
02216   Two_Product(pc[0], pd[1], cxdy1, cxdy0);
02217   Two_Product(pd[0], pc[1], dxcy1, dxcy0);
02218   Two_Two_Diff(cxdy1, cxdy0, dxcy1, dxcy0, cd[3], cd[2], cd[1], cd[0]);
02219 
02220   Two_Product(pd[0], pe[1], dxey1, dxey0);
02221   Two_Product(pe[0], pd[1], exdy1, exdy0);
02222   Two_Two_Diff(dxey1, dxey0, exdy1, exdy0, de[3], de[2], de[1], de[0]);
02223 
02224   Two_Product(pe[0], pa[1], exay1, exay0);
02225   Two_Product(pa[0], pe[1], axey1, axey0);
02226   Two_Two_Diff(exay1, exay0, axey1, axey0, ea[3], ea[2], ea[1], ea[0]);
02227 
02228   Two_Product(pa[0], pc[1], axcy1, axcy0);
02229   Two_Product(pc[0], pa[1], cxay1, cxay0);
02230   Two_Two_Diff(axcy1, axcy0, cxay1, cxay0, ac[3], ac[2], ac[1], ac[0]);
02231 
02232   Two_Product(pb[0], pd[1], bxdy1, bxdy0);
02233   Two_Product(pd[0], pb[1], dxby1, dxby0);
02234   Two_Two_Diff(bxdy1, bxdy0, dxby1, dxby0, bd[3], bd[2], bd[1], bd[0]);
02235 
02236   Two_Product(pc[0], pe[1], cxey1, cxey0);
02237   Two_Product(pe[0], pc[1], excy1, excy0);
02238   Two_Two_Diff(cxey1, cxey0, excy1, excy0, ce[3], ce[2], ce[1], ce[0]);
02239 
02240   Two_Product(pd[0], pa[1], dxay1, dxay0);
02241   Two_Product(pa[0], pd[1], axdy1, axdy0);
02242   Two_Two_Diff(dxay1, dxay0, axdy1, axdy0, da[3], da[2], da[1], da[0]);
02243 
02244   Two_Product(pe[0], pb[1], exby1, exby0);
02245   Two_Product(pb[0], pe[1], bxey1, bxey0);
02246   Two_Two_Diff(exby1, exby0, bxey1, bxey0, eb[3], eb[2], eb[1], eb[0]);
02247 
02248   temp8alen = scale_expansion_zeroelim(4, bc, pa[2], temp8a);
02249   temp8blen = scale_expansion_zeroelim(4, ac, -pb[2], temp8b);
02250   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
02251                                           temp16);
02252   temp8alen = scale_expansion_zeroelim(4, ab, pc[2], temp8a);
02253   abclen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
02254                                        abc);
02255 
02256   temp8alen = scale_expansion_zeroelim(4, cd, pb[2], temp8a);
02257   temp8blen = scale_expansion_zeroelim(4, bd, -pc[2], temp8b);
02258   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
02259                                           temp16);
02260   temp8alen = scale_expansion_zeroelim(4, bc, pd[2], temp8a);
02261   bcdlen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
02262                                        bcd);
02263 
02264   temp8alen = scale_expansion_zeroelim(4, de, pc[2], temp8a);
02265   temp8blen = scale_expansion_zeroelim(4, ce, -pd[2], temp8b);
02266   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
02267                                           temp16);
02268   temp8alen = scale_expansion_zeroelim(4, cd, pe[2], temp8a);
02269   cdelen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
02270                                        cde);
02271 
02272   temp8alen = scale_expansion_zeroelim(4, ea, pd[2], temp8a);
02273   temp8blen = scale_expansion_zeroelim(4, da, -pe[2], temp8b);
02274   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
02275                                           temp16);
02276   temp8alen = scale_expansion_zeroelim(4, de, pa[2], temp8a);
02277   dealen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
02278                                        dea);
02279 
02280   temp8alen = scale_expansion_zeroelim(4, ab, pe[2], temp8a);
02281   temp8blen = scale_expansion_zeroelim(4, eb, -pa[2], temp8b);
02282   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
02283                                           temp16);
02284   temp8alen = scale_expansion_zeroelim(4, ea, pb[2], temp8a);
02285   eablen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
02286                                        eab);
02287 
02288   temp8alen = scale_expansion_zeroelim(4, bd, pa[2], temp8a);
02289   temp8blen = scale_expansion_zeroelim(4, da, pb[2], temp8b);
02290   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
02291                                           temp16);
02292   temp8alen = scale_expansion_zeroelim(4, ab, pd[2], temp8a);
02293   abdlen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
02294                                        abd);
02295 
02296   temp8alen = scale_expansion_zeroelim(4, ce, pb[2], temp8a);
02297   temp8blen = scale_expansion_zeroelim(4, eb, pc[2], temp8b);
02298   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
02299                                           temp16);
02300   temp8alen = scale_expansion_zeroelim(4, bc, pe[2], temp8a);
02301   bcelen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
02302                                        bce);
02303 
02304   temp8alen = scale_expansion_zeroelim(4, da, pc[2], temp8a);
02305   temp8blen = scale_expansion_zeroelim(4, ac, pd[2], temp8b);
02306   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
02307                                           temp16);
02308   temp8alen = scale_expansion_zeroelim(4, cd, pa[2], temp8a);
02309   cdalen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
02310                                        cda);
02311 
02312   temp8alen = scale_expansion_zeroelim(4, eb, pd[2], temp8a);
02313   temp8blen = scale_expansion_zeroelim(4, bd, pe[2], temp8b);
02314   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
02315                                           temp16);
02316   temp8alen = scale_expansion_zeroelim(4, de, pb[2], temp8a);
02317   deblen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
02318                                        deb);
02319 
02320   temp8alen = scale_expansion_zeroelim(4, ac, pe[2], temp8a);
02321   temp8blen = scale_expansion_zeroelim(4, ce, pa[2], temp8b);
02322   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
02323                                           temp16);
02324   temp8alen = scale_expansion_zeroelim(4, ea, pc[2], temp8a);
02325   eaclen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
02326                                        eac);
02327 
02328   temp48alen = fast_expansion_sum_zeroelim(cdelen, cde, bcelen, bce, temp48a);
02329   temp48blen = fast_expansion_sum_zeroelim(deblen, deb, bcdlen, bcd, temp48b);
02330   for (i = 0; i < temp48blen; i++) {
02331     temp48b[i] = -temp48b[i];
02332   }
02333   bcdelen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
02334                                         temp48blen, temp48b, bcde);
02335   xlen = scale_expansion_zeroelim(bcdelen, bcde, pa[0], temp192);
02336   xlen = scale_expansion_zeroelim(xlen, temp192, pa[0], det384x);
02337   ylen = scale_expansion_zeroelim(bcdelen, bcde, pa[1], temp192);
02338   ylen = scale_expansion_zeroelim(ylen, temp192, pa[1], det384y);
02339   zlen = scale_expansion_zeroelim(bcdelen, bcde, pa[2], temp192);
02340   zlen = scale_expansion_zeroelim(zlen, temp192, pa[2], det384z);
02341   xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
02342   alen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, adet);
02343 
02344   temp48alen = fast_expansion_sum_zeroelim(dealen, dea, cdalen, cda, temp48a);
02345   temp48blen = fast_expansion_sum_zeroelim(eaclen, eac, cdelen, cde, temp48b);
02346   for (i = 0; i < temp48blen; i++) {
02347     temp48b[i] = -temp48b[i];
02348   }
02349   cdealen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
02350                                         temp48blen, temp48b, cdea);
02351   xlen = scale_expansion_zeroelim(cdealen, cdea, pb[0], temp192);
02352   xlen = scale_expansion_zeroelim(xlen, temp192, pb[0], det384x);
02353   ylen = scale_expansion_zeroelim(cdealen, cdea, pb[1], temp192);
02354   ylen = scale_expansion_zeroelim(ylen, temp192, pb[1], det384y);
02355   zlen = scale_expansion_zeroelim(cdealen, cdea, pb[2], temp192);
02356   zlen = scale_expansion_zeroelim(zlen, temp192, pb[2], det384z);
02357   xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
02358   blen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, bdet);
02359 
02360   temp48alen = fast_expansion_sum_zeroelim(eablen, eab, deblen, deb, temp48a);
02361   temp48blen = fast_expansion_sum_zeroelim(abdlen, abd, dealen, dea, temp48b);
02362   for (i = 0; i < temp48blen; i++) {
02363     temp48b[i] = -temp48b[i];
02364   }
02365   deablen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
02366                                         temp48blen, temp48b, deab);
02367   xlen = scale_expansion_zeroelim(deablen, deab, pc[0], temp192);
02368   xlen = scale_expansion_zeroelim(xlen, temp192, pc[0], det384x);
02369   ylen = scale_expansion_zeroelim(deablen, deab, pc[1], temp192);
02370   ylen = scale_expansion_zeroelim(ylen, temp192, pc[1], det384y);
02371   zlen = scale_expansion_zeroelim(deablen, deab, pc[2], temp192);
02372   zlen = scale_expansion_zeroelim(zlen, temp192, pc[2], det384z);
02373   xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
02374   clen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, cdet);
02375 
02376   temp48alen = fast_expansion_sum_zeroelim(abclen, abc, eaclen, eac, temp48a);
02377   temp48blen = fast_expansion_sum_zeroelim(bcelen, bce, eablen, eab, temp48b);
02378   for (i = 0; i < temp48blen; i++) {
02379     temp48b[i] = -temp48b[i];
02380   }
02381   eabclen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
02382                                         temp48blen, temp48b, eabc);
02383   xlen = scale_expansion_zeroelim(eabclen, eabc, pd[0], temp192);
02384   xlen = scale_expansion_zeroelim(xlen, temp192, pd[0], det384x);
02385   ylen = scale_expansion_zeroelim(eabclen, eabc, pd[1], temp192);
02386   ylen = scale_expansion_zeroelim(ylen, temp192, pd[1], det384y);
02387   zlen = scale_expansion_zeroelim(eabclen, eabc, pd[2], temp192);
02388   zlen = scale_expansion_zeroelim(zlen, temp192, pd[2], det384z);
02389   xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
02390   dlen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, ddet);
02391 
02392   temp48alen = fast_expansion_sum_zeroelim(bcdlen, bcd, abdlen, abd, temp48a);
02393   temp48blen = fast_expansion_sum_zeroelim(cdalen, cda, abclen, abc, temp48b);
02394   for (i = 0; i < temp48blen; i++) {
02395     temp48b[i] = -temp48b[i];
02396   }
02397   abcdlen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
02398                                         temp48blen, temp48b, abcd);
02399   xlen = scale_expansion_zeroelim(abcdlen, abcd, pe[0], temp192);
02400   xlen = scale_expansion_zeroelim(xlen, temp192, pe[0], det384x);
02401   ylen = scale_expansion_zeroelim(abcdlen, abcd, pe[1], temp192);
02402   ylen = scale_expansion_zeroelim(ylen, temp192, pe[1], det384y);
02403   zlen = scale_expansion_zeroelim(abcdlen, abcd, pe[2], temp192);
02404   zlen = scale_expansion_zeroelim(zlen, temp192, pe[2], det384z);
02405   xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
02406   elen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, edet);
02407 
02408   ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
02409   cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet);
02410   cdelen = fast_expansion_sum_zeroelim(cdlen, cddet, elen, edet, cdedet);
02411   deterlen = fast_expansion_sum_zeroelim(ablen, abdet, cdelen, cdedet, deter);
02412 
02413   return deter[deterlen - 1];
02414 }
02415 
02416 static REAL insphereadapt(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe, 
02417                           REAL permanent)
02418 {
02419   INEXACT REAL aex, bex, cex, dex, aey, bey, cey, dey, aez, bez, cez, dez;
02420   REAL det, errbound;
02421 
02422   INEXACT REAL aexbey1, bexaey1, bexcey1, cexbey1;
02423   INEXACT REAL cexdey1, dexcey1, dexaey1, aexdey1;
02424   INEXACT REAL aexcey1, cexaey1, bexdey1, dexbey1;
02425   REAL aexbey0, bexaey0, bexcey0, cexbey0;
02426   REAL cexdey0, dexcey0, dexaey0, aexdey0;
02427   REAL aexcey0, cexaey0, bexdey0, dexbey0;
02428   REAL ab[4], bc[4], cd[4], da[4], ac[4], bd[4];
02429   INEXACT REAL ab3, bc3, cd3, da3, ac3, bd3;
02430   REAL abeps, bceps, cdeps, daeps, aceps, bdeps;
02431   REAL temp8a[8], temp8b[8], temp8c[8], temp16[16], temp24[24], temp48[48];
02432   int temp8alen, temp8blen, temp8clen, temp16len, temp24len, temp48len;
02433   REAL xdet[96], ydet[96], zdet[96], xydet[192];
02434   int xlen, ylen, zlen, xylen;
02435   REAL adet[288], bdet[288], cdet[288], ddet[288];
02436   int alen, blen, clen, dlen;
02437   REAL abdet[576], cddet[576];
02438   int ablen, cdlen;
02439   REAL fin1[1152];
02440   int finlength;
02441 
02442   REAL aextail, bextail, cextail, dextail;
02443   REAL aeytail, beytail, ceytail, deytail;
02444   REAL aeztail, beztail, ceztail, deztail;
02445 
02446   INEXACT REAL bvirt;
02447   REAL avirt, bround, around;
02448   INEXACT REAL c;
02449   INEXACT REAL abig;
02450   REAL ahi, alo, bhi, blo;
02451   REAL err1, err2, err3;
02452   INEXACT REAL _i, _j;
02453   REAL _0;
02454 
02455   aex = (REAL) (pa[0] - pe[0]);
02456   bex = (REAL) (pb[0] - pe[0]);
02457   cex = (REAL) (pc[0] - pe[0]);
02458   dex = (REAL) (pd[0] - pe[0]);
02459   aey = (REAL) (pa[1] - pe[1]);
02460   bey = (REAL) (pb[1] - pe[1]);
02461   cey = (REAL) (pc[1] - pe[1]);
02462   dey = (REAL) (pd[1] - pe[1]);
02463   aez = (REAL) (pa[2] - pe[2]);
02464   bez = (REAL) (pb[2] - pe[2]);
02465   cez = (REAL) (pc[2] - pe[2]);
02466   dez = (REAL) (pd[2] - pe[2]);
02467 
02468   Two_Product(aex, bey, aexbey1, aexbey0);
02469   Two_Product(bex, aey, bexaey1, bexaey0);
02470   Two_Two_Diff(aexbey1, aexbey0, bexaey1, bexaey0, ab3, ab[2], ab[1], ab[0]);
02471   ab[3] = ab3;
02472 
02473   Two_Product(bex, cey, bexcey1, bexcey0);
02474   Two_Product(cex, bey, cexbey1, cexbey0);
02475   Two_Two_Diff(bexcey1, bexcey0, cexbey1, cexbey0, bc3, bc[2], bc[1], bc[0]);
02476   bc[3] = bc3;
02477 
02478   Two_Product(cex, dey, cexdey1, cexdey0);
02479   Two_Product(dex, cey, dexcey1, dexcey0);
02480   Two_Two_Diff(cexdey1, cexdey0, dexcey1, dexcey0, cd3, cd[2], cd[1], cd[0]);
02481   cd[3] = cd3;
02482 
02483   Two_Product(dex, aey, dexaey1, dexaey0);
02484   Two_Product(aex, dey, aexdey1, aexdey0);
02485   Two_Two_Diff(dexaey1, dexaey0, aexdey1, aexdey0, da3, da[2], da[1], da[0]);
02486   da[3] = da3;
02487 
02488   Two_Product(aex, cey, aexcey1, aexcey0);
02489   Two_Product(cex, aey, cexaey1, cexaey0);
02490   Two_Two_Diff(aexcey1, aexcey0, cexaey1, cexaey0, ac3, ac[2], ac[1], ac[0]);
02491   ac[3] = ac3;
02492 
02493   Two_Product(bex, dey, bexdey1, bexdey0);
02494   Two_Product(dex, bey, dexbey1, dexbey0);
02495   Two_Two_Diff(bexdey1, bexdey0, dexbey1, dexbey0, bd3, bd[2], bd[1], bd[0]);
02496   bd[3] = bd3;
02497 
02498   temp8alen = scale_expansion_zeroelim(4, cd, bez, temp8a);
02499   temp8blen = scale_expansion_zeroelim(4, bd, -cez, temp8b);
02500   temp8clen = scale_expansion_zeroelim(4, bc, dez, temp8c);
02501   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a,
02502                                           temp8blen, temp8b, temp16);
02503   temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c,
02504                                           temp16len, temp16, temp24);
02505   temp48len = scale_expansion_zeroelim(temp24len, temp24, aex, temp48);
02506   xlen = scale_expansion_zeroelim(temp48len, temp48, -aex, xdet);
02507   temp48len = scale_expansion_zeroelim(temp24len, temp24, aey, temp48);
02508   ylen = scale_expansion_zeroelim(temp48len, temp48, -aey, ydet);
02509   temp48len = scale_expansion_zeroelim(temp24len, temp24, aez, temp48);
02510   zlen = scale_expansion_zeroelim(temp48len, temp48, -aez, zdet);
02511   xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet);
02512   alen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, adet);
02513 
02514   temp8alen = scale_expansion_zeroelim(4, da, cez, temp8a);
02515   temp8blen = scale_expansion_zeroelim(4, ac, dez, temp8b);
02516   temp8clen = scale_expansion_zeroelim(4, cd, aez, temp8c);
02517   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a,
02518                                           temp8blen, temp8b, temp16);
02519   temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c,
02520                                           temp16len, temp16, temp24);
02521   temp48len = scale_expansion_zeroelim(temp24len, temp24, bex, temp48);
02522   xlen = scale_expansion_zeroelim(temp48len, temp48, bex, xdet);
02523   temp48len = scale_expansion_zeroelim(temp24len, temp24, bey, temp48);
02524   ylen = scale_expansion_zeroelim(temp48len, temp48, bey, ydet);
02525   temp48len = scale_expansion_zeroelim(temp24len, temp24, bez, temp48);
02526   zlen = scale_expansion_zeroelim(temp48len, temp48, bez, zdet);
02527   xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet);
02528   blen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, bdet);
02529 
02530   temp8alen = scale_expansion_zeroelim(4, ab, dez, temp8a);
02531   temp8blen = scale_expansion_zeroelim(4, bd, aez, temp8b);
02532   temp8clen = scale_expansion_zeroelim(4, da, bez, temp8c);
02533   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a,
02534                                           temp8blen, temp8b, temp16);
02535   temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c,
02536                                           temp16len, temp16, temp24);
02537   temp48len = scale_expansion_zeroelim(temp24len, temp24, cex, temp48);
02538   xlen = scale_expansion_zeroelim(temp48len, temp48, -cex, xdet);
02539   temp48len = scale_expansion_zeroelim(temp24len, temp24, cey, temp48);
02540   ylen = scale_expansion_zeroelim(temp48len, temp48, -cey, ydet);
02541   temp48len = scale_expansion_zeroelim(temp24len, temp24, cez, temp48);
02542   zlen = scale_expansion_zeroelim(temp48len, temp48, -cez, zdet);
02543   xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet);
02544   clen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, cdet);
02545 
02546   temp8alen = scale_expansion_zeroelim(4, bc, aez, temp8a);
02547   temp8blen = scale_expansion_zeroelim(4, ac, -bez, temp8b);
02548   temp8clen = scale_expansion_zeroelim(4, ab, cez, temp8c);
02549   temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a,
02550                                           temp8blen, temp8b, temp16);
02551   temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c,
02552                                           temp16len, temp16, temp24);
02553   temp48len = scale_expansion_zeroelim(temp24len, temp24, dex, temp48);
02554   xlen = scale_expansion_zeroelim(temp48len, temp48, dex, xdet);
02555   temp48len = scale_expansion_zeroelim(temp24len, temp24, dey, temp48);
02556   ylen = scale_expansion_zeroelim(temp48len, temp48, dey, ydet);
02557   temp48len = scale_expansion_zeroelim(temp24len, temp24, dez, temp48);
02558   zlen = scale_expansion_zeroelim(temp48len, temp48, dez, zdet);
02559   xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet);
02560   dlen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, ddet);
02561 
02562   ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
02563   cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet);
02564   finlength = fast_expansion_sum_zeroelim(ablen, abdet, cdlen, cddet, fin1);
02565 
02566   det = estimate(finlength, fin1);
02567   errbound = isperrboundB * permanent;
02568   if ((det >= errbound) || (-det >= errbound)) {
02569     return det;
02570   }
02571 
02572   Two_Diff_Tail(pa[0], pe[0], aex, aextail);
02573   Two_Diff_Tail(pa[1], pe[1], aey, aeytail);
02574   Two_Diff_Tail(pa[2], pe[2], aez, aeztail);
02575   Two_Diff_Tail(pb[0], pe[0], bex, bextail);
02576   Two_Diff_Tail(pb[1], pe[1], bey, beytail);
02577   Two_Diff_Tail(pb[2], pe[2], bez, beztail);
02578   Two_Diff_Tail(pc[0], pe[0], cex, cextail);
02579   Two_Diff_Tail(pc[1], pe[1], cey, ceytail);
02580   Two_Diff_Tail(pc[2], pe[2], cez, ceztail);
02581   Two_Diff_Tail(pd[0], pe[0], dex, dextail);
02582   Two_Diff_Tail(pd[1], pe[1], dey, deytail);
02583   Two_Diff_Tail(pd[2], pe[2], dez, deztail);
02584   if ((aextail == 0.0) && (aeytail == 0.0) && (aeztail == 0.0)
02585       && (bextail == 0.0) && (beytail == 0.0) && (beztail == 0.0)
02586       && (cextail == 0.0) && (ceytail == 0.0) && (ceztail == 0.0)
02587       && (dextail == 0.0) && (deytail == 0.0) && (deztail == 0.0)) {
02588     return det;
02589   }
02590 
02591   errbound = isperrboundC * permanent + resulterrbound * Absolute(det);
02592   abeps = (aex * beytail + bey * aextail)
02593         - (aey * bextail + bex * aeytail);
02594   bceps = (bex * ceytail + cey * bextail)
02595         - (bey * cextail + cex * beytail);
02596   cdeps = (cex * deytail + dey * cextail)
02597         - (cey * dextail + dex * ceytail);
02598   daeps = (dex * aeytail + aey * dextail)
02599         - (dey * aextail + aex * deytail);
02600   aceps = (aex * ceytail + cey * aextail)
02601         - (aey * cextail + cex * aeytail);
02602   bdeps = (bex * deytail + dey * bextail)
02603         - (bey * dextail + dex * beytail);
02604   det += (((bex * bex + bey * bey + bez * bez)
02605            * ((cez * daeps + dez * aceps + aez * cdeps)
02606               + (ceztail * da3 + deztail * ac3 + aeztail * cd3))
02607            + (dex * dex + dey * dey + dez * dez)
02608            * ((aez * bceps - bez * aceps + cez * abeps)
02609               + (aeztail * bc3 - beztail * ac3 + ceztail * ab3)))
02610           - ((aex * aex + aey * aey + aez * aez)
02611            * ((bez * cdeps - cez * bdeps + dez * bceps)
02612               + (beztail * cd3 - ceztail * bd3 + deztail * bc3))
02613            + (cex * cex + cey * cey + cez * cez)
02614            * ((dez * abeps + aez * bdeps + bez * daeps)
02615               + (deztail * ab3 + aeztail * bd3 + beztail * da3))))
02616        + 2.0 * (((bex * bextail + bey * beytail + bez * beztail)
02617                  * (cez * da3 + dez * ac3 + aez * cd3)
02618                  + (dex * dextail + dey * deytail + dez * deztail)
02619                  * (aez * bc3 - bez * ac3 + cez * ab3))
02620                 - ((aex * aextail + aey * aeytail + aez * aeztail)
02621                  * (bez * cd3 - cez * bd3 + dez * bc3)
02622                  + (cex * cextail + cey * ceytail + cez * ceztail)
02623                  * (dez * ab3 + aez * bd3 + bez * da3)));
02624   if ((det >= errbound) || (-det >= errbound)) {
02625     return det;
02626   }
02627 
02628   return insphereexact(pa, pb, pc, pd, pe);
02629 }
02630 
02631 REAL insphere(pa, pb, pc, pd, pe)
02632 REAL *pa;
02633 REAL *pb;
02634 REAL *pc;
02635 REAL *pd;
02636 REAL *pe;
02637 {
02638   REAL aex, bex, cex, dex;
02639   REAL aey, bey, cey, dey;
02640   REAL aez, bez, cez, dez;
02641   REAL aexbey, bexaey, bexcey, cexbey, cexdey, dexcey, dexaey, aexdey;
02642   REAL aexcey, cexaey, bexdey, dexbey;
02643   REAL alift, blift, clift, dlift;
02644   REAL ab, bc, cd, da, ac, bd;
02645   REAL abc, bcd, cda, dab;
02646   REAL aezplus, bezplus, cezplus, dezplus;
02647   REAL aexbeyplus, bexaeyplus, bexceyplus, cexbeyplus;
02648   REAL cexdeyplus, dexceyplus, dexaeyplus, aexdeyplus;
02649   REAL aexceyplus, cexaeyplus, bexdeyplus, dexbeyplus;
02650   REAL det;
02651   REAL permanent, errbound;
02652   REAL ins;
02653 
02654   FPU_ROUND_DOUBLE;
02655 
02656   aex = pa[0] - pe[0];
02657   bex = pb[0] - pe[0];
02658   cex = pc[0] - pe[0];
02659   dex = pd[0] - pe[0];
02660   aey = pa[1] - pe[1];
02661   bey = pb[1] - pe[1];
02662   cey = pc[1] - pe[1];
02663   dey = pd[1] - pe[1];
02664   aez = pa[2] - pe[2];
02665   bez = pb[2] - pe[2];
02666   cez = pc[2] - pe[2];
02667   dez = pd[2] - pe[2];
02668 
02669   aexbey = aex * bey;
02670   bexaey = bex * aey;
02671   ab = aexbey - bexaey;
02672   bexcey = bex * cey;
02673   cexbey = cex * bey;
02674   bc = bexcey - cexbey;
02675   cexdey = cex * dey;
02676   dexcey = dex * cey;
02677   cd = cexdey - dexcey;
02678   dexaey = dex * aey;
02679   aexdey = aex * dey;
02680   da = dexaey - aexdey;
02681 
02682   aexcey = aex * cey;
02683   cexaey = cex * aey;
02684   ac = aexcey - cexaey;
02685   bexdey = bex * dey;
02686   dexbey = dex * bey;
02687   bd = bexdey - dexbey;
02688 
02689   abc = aez * bc - bez * ac + cez * ab;
02690   bcd = bez * cd - cez * bd + dez * bc;
02691   cda = cez * da + dez * ac + aez * cd;
02692   dab = dez * ab + aez * bd + bez * da;
02693 
02694   alift = aex * aex + aey * aey + aez * aez;
02695   blift = bex * bex + bey * bey + bez * bez;
02696   clift = cex * cex + cey * cey + cez * cez;
02697   dlift = dex * dex + dey * dey + dez * dez;
02698 
02699   det = (dlift * abc - clift * dab) + (blift * cda - alift * bcd);
02700 
02701   aezplus = Absolute(aez);
02702   bezplus = Absolute(bez);
02703   cezplus = Absolute(cez);
02704   dezplus = Absolute(dez);
02705   aexbeyplus = Absolute(aexbey);
02706   bexaeyplus = Absolute(bexaey);
02707   bexceyplus = Absolute(bexcey);
02708   cexbeyplus = Absolute(cexbey);
02709   cexdeyplus = Absolute(cexdey);
02710   dexceyplus = Absolute(dexcey);
02711   dexaeyplus = Absolute(dexaey);
02712   aexdeyplus = Absolute(aexdey);
02713   aexceyplus = Absolute(aexcey);
02714   cexaeyplus = Absolute(cexaey);
02715   bexdeyplus = Absolute(bexdey);
02716   dexbeyplus = Absolute(dexbey);
02717   permanent = ((cexdeyplus + dexceyplus) * bezplus
02718                + (dexbeyplus + bexdeyplus) * cezplus
02719                + (bexceyplus + cexbeyplus) * dezplus)
02720             * alift
02721             + ((dexaeyplus + aexdeyplus) * cezplus
02722                + (aexceyplus + cexaeyplus) * dezplus
02723                + (cexdeyplus + dexceyplus) * aezplus)
02724             * blift
02725             + ((aexbeyplus + bexaeyplus) * dezplus
02726                + (bexdeyplus + dexbeyplus) * aezplus
02727                + (dexaeyplus + aexdeyplus) * bezplus)
02728             * clift
02729             + ((bexceyplus + cexbeyplus) * aezplus
02730                + (cexaeyplus + aexceyplus) * bezplus
02731                + (aexbeyplus + bexaeyplus) * cezplus)
02732             * dlift;
02733   errbound = isperrboundA * permanent;
02734   if ((det > errbound) || (-det > errbound)) {
02735     FPU_RESTORE;
02736     return det;
02737   }
02738 
02739   ins = insphereadapt(pa, pb, pc, pd, pe, permanent);
02740   FPU_RESTORE;
02741   return ins;
02742 }