triangle.c
Upload User: yflamps
Upload Date: 2010-04-01
Package Size: 155k
Code Size: 636k
Category:

3D Graphic

Development Platform:

C/C++

  1. );
  2.   printf(
  3. "  to me.  The more people I know are using this program, the more easily In"
  4. );
  5.   printf(
  6. "  can justify spending time on improvements, which in turn will benefitn");
  7.   printf(
  8. "  you.  Also, I can put you on a list to receive email whenever a newn");
  9.   printf("  version of Triangle is available.nn");
  10.   printf(
  11. "  If you use a mesh generated by Triangle in a publication, please includen"
  12. );
  13.   printf(
  14. "  an acknowledgment as well.  And please spell Triangle with a capital `T'!n"
  15. );
  16.   printf(
  17. "  If you want to include a citation, use `Jonathan Richard Shewchuk,n");
  18.   printf(
  19. "  ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunayn");
  20.   printf(
  21. "  Triangulator,'' in Applied Computational Geometry:  Towards Geometricn");
  22.   printf(
  23. "  Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 ofn");
  24.   printf(
  25. "  Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,n");
  26.   printf(
  27. "  Berlin, May 1996.  (From the First ACM Workshop on Applied Computationaln"
  28. );
  29.   printf("  Geometry.)'nn");
  30.   printf("Research credit:nn");
  31.   printf(
  32. "  Of course, I can take credit for only a fraction of the ideas that maden");
  33.   printf(
  34. "  this mesh generator possible.  Triangle owes its existence to the effortsn"
  35. );
  36.   printf(
  37. "  of many fine computational geometers and other researchers, includingn");
  38.   printf(
  39. "  Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.n"
  40. );
  41.   printf(
  42. "  Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.n");
  43.   printf(
  44. "  Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,n");
  45.   printf(
  46. "  Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.n");
  47.   printf(
  48. "  Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,n"
  49. );
  50.   printf("  Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.n");
  51.   printf(
  52. "  Walkington, and Binhai Zhu.  See the comments at the beginning of then");
  53.   printf("  source code for references.nn");
  54.   triexit(0);
  55. }
  56. #endif /* not TRILIBRARY */
  57. /*****************************************************************************/
  58. /*                                                                           */
  59. /*  internalerror()   Ask the user to send me the defective product.  Exit.  */
  60. /*                                                                           */
  61. /*****************************************************************************/
  62. void internalerror()
  63. {
  64.   printf("  Please report this bug to jrs@cs.berkeley.edun");
  65.   printf("  Include the message above, your input data set, and the exactn");
  66.   printf("    command line you used to run Triangle.n");
  67.   triexit(1);
  68. }
  69. /*****************************************************************************/
  70. /*                                                                           */
  71. /*  parsecommandline()   Read the command line, identify switches, and set   */
  72. /*                       up options and file names.                          */
  73. /*                                                                           */
  74. /*****************************************************************************/
  75. #ifdef ANSI_DECLARATORS
  76. void parsecommandline(int argc, char **argv, struct behavior *b)
  77. #else /* not ANSI_DECLARATORS */
  78. void parsecommandline(argc, argv, b)
  79. int argc;
  80. char **argv;
  81. struct behavior *b;
  82. #endif /* not ANSI_DECLARATORS */
  83. {
  84. #ifdef TRILIBRARY
  85. #define STARTINDEX 0
  86. #else /* not TRILIBRARY */
  87. #define STARTINDEX 1
  88.   int increment;
  89.   int meshnumber;
  90. #endif /* not TRILIBRARY */
  91.   int i, j, k;
  92.   char workstring[FILENAMESIZE];
  93.   b->poly = b->refine = b->quality = 0;
  94.   b->vararea = b->fixedarea = b->usertest = 0;
  95.   b->regionattrib = b->convex = b->weighted = b->jettison = 0;
  96.   b->firstnumber = 1;
  97.   b->edgesout = b->voronoi = b->neighbors = b->geomview = 0;
  98.   b->nobound = b->nopolywritten = b->nonodewritten = b->noelewritten = 0;
  99.   b->noiterationnum = 0;
  100.   b->noholes = b->noexact = 0;
  101.   b->incremental = b->sweepline = 0;
  102.   b->dwyer = 1;
  103.   b->splitseg = 0;
  104.   b->docheck = 0;
  105.   b->nobisect = 0;
  106.   b->conformdel = 0;
  107.   b->steiner = -1;
  108.   b->order = 1;
  109.   b->minangle = 0.0;
  110.   b->maxarea = -1.0;
  111.   b->quiet = b->verbose = 0;
  112. #ifndef TRILIBRARY
  113.   b->innodefilename[0] = '';
  114. #endif /* not TRILIBRARY */
  115.   for (i = STARTINDEX; i < argc; i++) {
  116. #ifndef TRILIBRARY
  117.     if (argv[i][0] == '-') {
  118. #endif /* not TRILIBRARY */
  119.       for (j = STARTINDEX; argv[i][j] != ''; j++) {
  120.         if (argv[i][j] == 'p') {
  121.           b->poly = 1;
  122. }
  123. #ifndef CDT_ONLY
  124.         if (argv[i][j] == 'r') {
  125.           b->refine = 1;
  126. }
  127.         if (argv[i][j] == 'q') {
  128.           b->quality = 1;
  129.           if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
  130.               (argv[i][j + 1] == '.')) {
  131.             k = 0;
  132.             while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
  133.                    (argv[i][j + 1] == '.')) {
  134.               j++;
  135.               workstring[k] = argv[i][j];
  136.               k++;
  137.             }
  138.             workstring[k] = '';
  139.             b->minangle = (REAL) strtod(workstring, (char **) NULL);
  140.   } else {
  141.             b->minangle = 20.0;
  142.   }
  143. }
  144.         if (argv[i][j] == 'a') {
  145.           b->quality = 1;
  146.           if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
  147.               (argv[i][j + 1] == '.')) {
  148.             b->fixedarea = 1;
  149.             k = 0;
  150.             while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
  151.                    (argv[i][j + 1] == '.')) {
  152.               j++;
  153.               workstring[k] = argv[i][j];
  154.               k++;
  155.             }
  156.             workstring[k] = '';
  157.             b->maxarea = (REAL) strtod(workstring, (char **) NULL);
  158.             if (b->maxarea <= 0.0) {
  159.               printf("Error:  Maximum area must be greater than zero.n");
  160.               triexit(1);
  161.     }
  162.   } else {
  163.             b->vararea = 1;
  164.   }
  165. }
  166.         if (argv[i][j] == 'u') {
  167.           b->quality = 1;
  168.           b->usertest = 1;
  169.         }
  170. #endif /* not CDT_ONLY */
  171.         if (argv[i][j] == 'A') {
  172.           b->regionattrib = 1;
  173.         }
  174.         if (argv[i][j] == 'c') {
  175.           b->convex = 1;
  176.         }
  177.         if (argv[i][j] == 'w') {
  178.           b->weighted = 1;
  179.         }
  180.         if (argv[i][j] == 'W') {
  181.           b->weighted = 2;
  182.         }
  183.         if (argv[i][j] == 'j') {
  184.           b->jettison = 1;
  185.         }
  186.         if (argv[i][j] == 'z') {
  187.           b->firstnumber = 0;
  188.         }
  189.         if (argv[i][j] == 'e') {
  190.           b->edgesout = 1;
  191. }
  192.         if (argv[i][j] == 'v') {
  193.           b->voronoi = 1;
  194. }
  195.         if (argv[i][j] == 'n') {
  196.           b->neighbors = 1;
  197. }
  198.         if (argv[i][j] == 'g') {
  199.           b->geomview = 1;
  200. }
  201.         if (argv[i][j] == 'B') {
  202.           b->nobound = 1;
  203. }
  204.         if (argv[i][j] == 'P') {
  205.           b->nopolywritten = 1;
  206. }
  207.         if (argv[i][j] == 'N') {
  208.           b->nonodewritten = 1;
  209. }
  210.         if (argv[i][j] == 'E') {
  211.           b->noelewritten = 1;
  212. }
  213. #ifndef TRILIBRARY
  214.         if (argv[i][j] == 'I') {
  215.           b->noiterationnum = 1;
  216. }
  217. #endif /* not TRILIBRARY */
  218.         if (argv[i][j] == 'O') {
  219.           b->noholes = 1;
  220. }
  221.         if (argv[i][j] == 'X') {
  222.           b->noexact = 1;
  223. }
  224.         if (argv[i][j] == 'o') {
  225.           if (argv[i][j + 1] == '2') {
  226.             j++;
  227.             b->order = 2;
  228.           }
  229. }
  230. #ifndef CDT_ONLY
  231.         if (argv[i][j] == 'Y') {
  232.           b->nobisect++;
  233. }
  234.         if (argv[i][j] == 'S') {
  235.           b->steiner = 0;
  236.           while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
  237.             j++;
  238.             b->steiner = b->steiner * 10 + (int) (argv[i][j] - '0');
  239.           }
  240.         }
  241. #endif /* not CDT_ONLY */
  242. #ifndef REDUCED
  243.         if (argv[i][j] == 'i') {
  244.           b->incremental = 1;
  245.         }
  246.         if (argv[i][j] == 'F') {
  247.           b->sweepline = 1;
  248.         }
  249. #endif /* not REDUCED */
  250.         if (argv[i][j] == 'l') {
  251.           b->dwyer = 0;
  252.         }
  253. #ifndef REDUCED
  254. #ifndef CDT_ONLY
  255.         if (argv[i][j] == 's') {
  256.           b->splitseg = 1;
  257.         }
  258.         if ((argv[i][j] == 'D') || (argv[i][j] == 'L')) {
  259.           b->quality = 1;
  260.           b->conformdel = 1;
  261.         }
  262. #endif /* not CDT_ONLY */
  263.         if (argv[i][j] == 'C') {
  264.           b->docheck = 1;
  265.         }
  266. #endif /* not REDUCED */
  267.         if (argv[i][j] == 'Q') {
  268.           b->quiet = 1;
  269.         }
  270.         if (argv[i][j] == 'V') {
  271.           b->verbose++;
  272.         }
  273. #ifndef TRILIBRARY
  274.         if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
  275.             (argv[i][j] == '?')) {
  276.           info();
  277. }
  278. #endif /* not TRILIBRARY */
  279.       }
  280. #ifndef TRILIBRARY
  281.     } else {
  282.       strncpy(b->innodefilename, argv[i], FILENAMESIZE - 1);
  283.       b->innodefilename[FILENAMESIZE - 1] = '';
  284.     }
  285. #endif /* not TRILIBRARY */
  286.   }
  287. #ifndef TRILIBRARY
  288.   if (b->innodefilename[0] == '') {
  289.     syntax();
  290.   }
  291.   if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".node")) {
  292.     b->innodefilename[strlen(b->innodefilename) - 5] = '';
  293.   }
  294.   if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".poly")) {
  295.     b->innodefilename[strlen(b->innodefilename) - 5] = '';
  296.     b->poly = 1;
  297.   }
  298. #ifndef CDT_ONLY
  299.   if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 4], ".ele")) {
  300.     b->innodefilename[strlen(b->innodefilename) - 4] = '';
  301.     b->refine = 1;
  302.   }
  303.   if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".area")) {
  304.     b->innodefilename[strlen(b->innodefilename) - 5] = '';
  305.     b->refine = 1;
  306.     b->quality = 1;
  307.     b->vararea = 1;
  308.   }
  309. #endif /* not CDT_ONLY */
  310. #endif /* not TRILIBRARY */
  311.   b->usesegments = b->poly || b->refine || b->quality || b->convex;
  312.   b->goodangle = cos(b->minangle * PI / 180.0);
  313.   if (b->goodangle == 1.0) {
  314.     b->offconstant = 0.0;
  315.   } else {
  316.     b->offconstant = 0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle));
  317.   }
  318.   b->goodangle *= b->goodangle;
  319.   if (b->refine && b->noiterationnum) {
  320.     printf(
  321.       "Error:  You cannot use the -I switch when refining a triangulation.n");
  322.     triexit(1);
  323.   }
  324.   /* Be careful not to allocate space for element area constraints that */
  325.   /*   will never be assigned any value (other than the default -1.0).  */
  326.   if (!b->refine && !b->poly) {
  327.     b->vararea = 0;
  328.   }
  329.   /* Be careful not to add an extra attribute to each element unless the */
  330.   /*   input supports it (PSLG in, but not refining a preexisting mesh). */
  331.   if (b->refine || !b->poly) {
  332.     b->regionattrib = 0;
  333.   }
  334.   /* Regular/weighted triangulations are incompatible with PSLGs */
  335.   /*   and meshing.                                              */
  336.   if (b->weighted && (b->poly || b->quality)) {
  337.     b->weighted = 0;
  338.     if (!b->quiet) {
  339.       printf("Warning:  weighted triangulations (-w, -W) are incompatiblen");
  340.       printf("  with PSLGs (-p) and meshing (-q, -a, -u).  Weights ignored.n"
  341.              );
  342.     }
  343.   }
  344.   if (b->jettison && b->nonodewritten && !b->quiet) {
  345.     printf("Warning:  -j and -N switches are somewhat incompatible.n");
  346.     printf("  If any vertices are jettisoned, you will need the outputn");
  347.     printf("  .node file to reconstruct the new node indices.");
  348.   }
  349. #ifndef TRILIBRARY
  350.   strcpy(b->inpolyfilename, b->innodefilename);
  351.   strcpy(b->inelefilename, b->innodefilename);
  352.   strcpy(b->areafilename, b->innodefilename);
  353.   increment = 0;
  354.   strcpy(workstring, b->innodefilename);
  355.   j = 1;
  356.   while (workstring[j] != '') {
  357.     if ((workstring[j] == '.') && (workstring[j + 1] != '')) {
  358.       increment = j + 1;
  359.     }
  360.     j++;
  361.   }
  362.   meshnumber = 0;
  363.   if (increment > 0) {
  364.     j = increment;
  365.     do {
  366.       if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
  367.         meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
  368.       } else {
  369.         increment = 0;
  370.       }
  371.       j++;
  372.     } while (workstring[j] != '');
  373.   }
  374.   if (b->noiterationnum) {
  375.     strcpy(b->outnodefilename, b->innodefilename);
  376.     strcpy(b->outelefilename, b->innodefilename);
  377.     strcpy(b->edgefilename, b->innodefilename);
  378.     strcpy(b->vnodefilename, b->innodefilename);
  379.     strcpy(b->vedgefilename, b->innodefilename);
  380.     strcpy(b->neighborfilename, b->innodefilename);
  381.     strcpy(b->offfilename, b->innodefilename);
  382.     strcat(b->outnodefilename, ".node");
  383.     strcat(b->outelefilename, ".ele");
  384.     strcat(b->edgefilename, ".edge");
  385.     strcat(b->vnodefilename, ".v.node");
  386.     strcat(b->vedgefilename, ".v.edge");
  387.     strcat(b->neighborfilename, ".neigh");
  388.     strcat(b->offfilename, ".off");
  389.   } else if (increment == 0) {
  390.     strcpy(b->outnodefilename, b->innodefilename);
  391.     strcpy(b->outpolyfilename, b->innodefilename);
  392.     strcpy(b->outelefilename, b->innodefilename);
  393.     strcpy(b->edgefilename, b->innodefilename);
  394.     strcpy(b->vnodefilename, b->innodefilename);
  395.     strcpy(b->vedgefilename, b->innodefilename);
  396.     strcpy(b->neighborfilename, b->innodefilename);
  397.     strcpy(b->offfilename, b->innodefilename);
  398.     strcat(b->outnodefilename, ".1.node");
  399.     strcat(b->outpolyfilename, ".1.poly");
  400.     strcat(b->outelefilename, ".1.ele");
  401.     strcat(b->edgefilename, ".1.edge");
  402.     strcat(b->vnodefilename, ".1.v.node");
  403.     strcat(b->vedgefilename, ".1.v.edge");
  404.     strcat(b->neighborfilename, ".1.neigh");
  405.     strcat(b->offfilename, ".1.off");
  406.   } else {
  407.     workstring[increment] = '%';
  408.     workstring[increment + 1] = 'd';
  409.     workstring[increment + 2] = '';
  410.     sprintf(b->outnodefilename, workstring, meshnumber + 1);
  411.     strcpy(b->outpolyfilename, b->outnodefilename);
  412.     strcpy(b->outelefilename, b->outnodefilename);
  413.     strcpy(b->edgefilename, b->outnodefilename);
  414.     strcpy(b->vnodefilename, b->outnodefilename);
  415.     strcpy(b->vedgefilename, b->outnodefilename);
  416.     strcpy(b->neighborfilename, b->outnodefilename);
  417.     strcpy(b->offfilename, b->outnodefilename);
  418.     strcat(b->outnodefilename, ".node");
  419.     strcat(b->outpolyfilename, ".poly");
  420.     strcat(b->outelefilename, ".ele");
  421.     strcat(b->edgefilename, ".edge");
  422.     strcat(b->vnodefilename, ".v.node");
  423.     strcat(b->vedgefilename, ".v.edge");
  424.     strcat(b->neighborfilename, ".neigh");
  425.     strcat(b->offfilename, ".off");
  426.   }
  427.   strcat(b->innodefilename, ".node");
  428.   strcat(b->inpolyfilename, ".poly");
  429.   strcat(b->inelefilename, ".ele");
  430.   strcat(b->areafilename, ".area");
  431. #endif /* not TRILIBRARY */
  432. }
  433. /**                                                                         **/
  434. /**                                                                         **/
  435. /********* User interaction routines begin here                      *********/
  436. /********* Debugging routines begin here                             *********/
  437. /**                                                                         **/
  438. /**                                                                         **/
  439. /*****************************************************************************/
  440. /*                                                                           */
  441. /*  printtriangle()   Print out the details of an oriented triangle.         */
  442. /*                                                                           */
  443. /*  I originally wrote this procedure to simplify debugging; it can be       */
  444. /*  called directly from the debugger, and presents information about an     */
  445. /*  oriented triangle in digestible form.  It's also used when the           */
  446. /*  highest level of verbosity (`-VVV') is specified.                        */
  447. /*                                                                           */
  448. /*****************************************************************************/
  449. #ifdef ANSI_DECLARATORS
  450. void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
  451. #else /* not ANSI_DECLARATORS */
  452. void printtriangle(m, b, t)
  453. struct mesh *m;
  454. struct behavior *b;
  455. struct otri *t;
  456. #endif /* not ANSI_DECLARATORS */
  457. {
  458.   struct otri printtri;
  459.   struct osub printsh;
  460.   vertex printvertex;
  461.   printf("triangle x%lx with orientation %d:n", (unsigned long) t->tri,
  462.          t->orient);
  463.   decode(t->tri[0], printtri);
  464.   if (printtri.tri == m->dummytri) {
  465.     printf("    [0] = Outer spacen");
  466.   } else {
  467.     printf("    [0] = x%lx  %dn", (unsigned long) printtri.tri,
  468.            printtri.orient);
  469.   }
  470.   decode(t->tri[1], printtri);
  471.   if (printtri.tri == m->dummytri) {
  472.     printf("    [1] = Outer spacen");
  473.   } else {
  474.     printf("    [1] = x%lx  %dn", (unsigned long) printtri.tri,
  475.            printtri.orient);
  476.   }
  477.   decode(t->tri[2], printtri);
  478.   if (printtri.tri == m->dummytri) {
  479.     printf("    [2] = Outer spacen");
  480.   } else {
  481.     printf("    [2] = x%lx  %dn", (unsigned long) printtri.tri,
  482.            printtri.orient);
  483.   }
  484.   org(*t, printvertex);
  485.   if (printvertex == (vertex) NULL)
  486.     printf("    Origin[%d] = NULLn", (t->orient + 1) % 3 + 3);
  487.   else
  488.     printf("    Origin[%d] = x%lx  (%.12g, %.12g)n",
  489.            (t->orient + 1) % 3 + 3, (unsigned long) printvertex,
  490.            printvertex[0], printvertex[1]);
  491.   dest(*t, printvertex);
  492.   if (printvertex == (vertex) NULL)
  493.     printf("    Dest  [%d] = NULLn", (t->orient + 2) % 3 + 3);
  494.   else
  495.     printf("    Dest  [%d] = x%lx  (%.12g, %.12g)n",
  496.            (t->orient + 2) % 3 + 3, (unsigned long) printvertex,
  497.            printvertex[0], printvertex[1]);
  498.   apex(*t, printvertex);
  499.   if (printvertex == (vertex) NULL)
  500.     printf("    Apex  [%d] = NULLn", t->orient + 3);
  501.   else
  502.     printf("    Apex  [%d] = x%lx  (%.12g, %.12g)n",
  503.            t->orient + 3, (unsigned long) printvertex,
  504.            printvertex[0], printvertex[1]);
  505.   if (b->usesegments) {
  506.     sdecode(t->tri[6], printsh);
  507.     if (printsh.ss != m->dummysub) {
  508.       printf("    [6] = x%lx  %dn", (unsigned long) printsh.ss,
  509.              printsh.ssorient);
  510.     }
  511.     sdecode(t->tri[7], printsh);
  512.     if (printsh.ss != m->dummysub) {
  513.       printf("    [7] = x%lx  %dn", (unsigned long) printsh.ss,
  514.              printsh.ssorient);
  515.     }
  516.     sdecode(t->tri[8], printsh);
  517.     if (printsh.ss != m->dummysub) {
  518.       printf("    [8] = x%lx  %dn", (unsigned long) printsh.ss,
  519.              printsh.ssorient);
  520.     }
  521.   }
  522.   if (b->vararea) {
  523.     printf("    Area constraint:  %.4gn", areabound(*t));
  524.   }
  525. }
  526. /*****************************************************************************/
  527. /*                                                                           */
  528. /*  printsubseg()   Print out the details of an oriented subsegment.         */
  529. /*                                                                           */
  530. /*  I originally wrote this procedure to simplify debugging; it can be       */
  531. /*  called directly from the debugger, and presents information about an     */
  532. /*  oriented subsegment in digestible form.  It's also used when the highest */
  533. /*  level of verbosity (`-VVV') is specified.                                */
  534. /*                                                                           */
  535. /*****************************************************************************/
  536. #ifdef ANSI_DECLARATORS
  537. void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
  538. #else /* not ANSI_DECLARATORS */
  539. void printsubseg(m, b, s)
  540. struct mesh *m;
  541. struct behavior *b;
  542. struct osub *s;
  543. #endif /* not ANSI_DECLARATORS */
  544. {
  545.   struct osub printsh;
  546.   struct otri printtri;
  547.   vertex printvertex;
  548.   printf("subsegment x%lx with orientation %d and mark %d:n",
  549.          (unsigned long) s->ss, s->ssorient, mark(*s));
  550.   sdecode(s->ss[0], printsh);
  551.   if (printsh.ss == m->dummysub) {
  552.     printf("    [0] = No subsegmentn");
  553.   } else {
  554.     printf("    [0] = x%lx  %dn", (unsigned long) printsh.ss,
  555.            printsh.ssorient);
  556.   }
  557.   sdecode(s->ss[1], printsh);
  558.   if (printsh.ss == m->dummysub) {
  559.     printf("    [1] = No subsegmentn");
  560.   } else {
  561.     printf("    [1] = x%lx  %dn", (unsigned long) printsh.ss,
  562.            printsh.ssorient);
  563.   }
  564.   sorg(*s, printvertex);
  565.   if (printvertex == (vertex) NULL)
  566.     printf("    Origin[%d] = NULLn", 2 + s->ssorient);
  567.   else
  568.     printf("    Origin[%d] = x%lx  (%.12g, %.12g)n",
  569.            2 + s->ssorient, (unsigned long) printvertex,
  570.            printvertex[0], printvertex[1]);
  571.   sdest(*s, printvertex);
  572.   if (printvertex == (vertex) NULL)
  573.     printf("    Dest  [%d] = NULLn", 3 - s->ssorient);
  574.   else
  575.     printf("    Dest  [%d] = x%lx  (%.12g, %.12g)n",
  576.            3 - s->ssorient, (unsigned long) printvertex,
  577.            printvertex[0], printvertex[1]);
  578.   decode(s->ss[6], printtri);
  579.   if (printtri.tri == m->dummytri) {
  580.     printf("    [6] = Outer spacen");
  581.   } else {
  582.     printf("    [6] = x%lx  %dn", (unsigned long) printtri.tri,
  583.            printtri.orient);
  584.   }
  585.   decode(s->ss[7], printtri);
  586.   if (printtri.tri == m->dummytri) {
  587.     printf("    [7] = Outer spacen");
  588.   } else {
  589.     printf("    [7] = x%lx  %dn", (unsigned long) printtri.tri,
  590.            printtri.orient);
  591.   }
  592.   segorg(*s, printvertex);
  593.   if (printvertex == (vertex) NULL)
  594.     printf("    Segment origin[%d] = NULLn", 4 + s->ssorient);
  595.   else
  596.     printf("    Segment origin[%d] = x%lx  (%.12g, %.12g)n",
  597.            4 + s->ssorient, (unsigned long) printvertex,
  598.            printvertex[0], printvertex[1]);
  599.   segdest(*s, printvertex);
  600.   if (printvertex == (vertex) NULL)
  601.     printf("    Segment dest  [%d] = NULLn", 5 - s->ssorient);
  602.   else
  603.     printf("    Segment dest  [%d] = x%lx  (%.12g, %.12g)n",
  604.            5 - s->ssorient, (unsigned long) printvertex,
  605.            printvertex[0], printvertex[1]);
  606. }
  607. /**                                                                         **/
  608. /**                                                                         **/
  609. /********* Debugging routines end here                               *********/
  610. /********* Memory management routines begin here                     *********/
  611. /**                                                                         **/
  612. /**                                                                         **/
  613. /*****************************************************************************/
  614. /*                                                                           */
  615. /*  poolzero()   Set all of a pool's fields to zero.                         */
  616. /*                                                                           */
  617. /*  This procedure should never be called on a pool that has any memory      */
  618. /*  allocated to it, as that memory would leak.                              */
  619. /*                                                                           */
  620. /*****************************************************************************/
  621. #ifdef ANSI_DECLARATORS
  622. void poolzero(struct memorypool *pool)
  623. #else /* not ANSI_DECLARATORS */
  624. void poolzero(pool)
  625. struct memorypool *pool;
  626. #endif /* not ANSI_DECLARATORS */
  627. {
  628.   pool->firstblock = (VOID **) NULL;
  629.   pool->nowblock = (VOID **) NULL;
  630.   pool->nextitem = (VOID *) NULL;
  631.   pool->deaditemstack = (VOID *) NULL;
  632.   pool->pathblock = (VOID **) NULL;
  633.   pool->pathitem = (VOID *) NULL;
  634.   pool->alignbytes = 0;
  635.   pool->itembytes = 0;
  636.   pool->itemsperblock = 0;
  637.   pool->itemsfirstblock = 0;
  638.   pool->items = 0;
  639.   pool->maxitems = 0;
  640.   pool->unallocateditems = 0;
  641.   pool->pathitemsleft = 0;
  642. }
  643. /*****************************************************************************/
  644. /*                                                                           */
  645. /*  poolrestart()   Deallocate all items in a pool.                          */
  646. /*                                                                           */
  647. /*  The pool is returned to its starting state, except that no memory is     */
  648. /*  freed to the operating system.  Rather, the previously allocated blocks  */
  649. /*  are ready to be reused.                                                  */
  650. /*                                                                           */
  651. /*****************************************************************************/
  652. #ifdef ANSI_DECLARATORS
  653. void poolrestart(struct memorypool *pool)
  654. #else /* not ANSI_DECLARATORS */
  655. void poolrestart(pool)
  656. struct memorypool *pool;
  657. #endif /* not ANSI_DECLARATORS */
  658. {
  659.   unsigned long alignptr;
  660.   pool->items = 0;
  661.   pool->maxitems = 0;
  662.   /* Set the currently active block. */
  663.   pool->nowblock = pool->firstblock;
  664.   /* Find the first item in the pool.  Increment by the size of (VOID *). */
  665.   alignptr = (unsigned long) (pool->nowblock + 1);
  666.   /* Align the item on an `alignbytes'-byte boundary. */
  667.   pool->nextitem = (VOID *)
  668.     (alignptr + (unsigned long) pool->alignbytes -
  669.      (alignptr % (unsigned long) pool->alignbytes));
  670.   /* There are lots of unallocated items left in this block. */
  671.   pool->unallocateditems = pool->itemsfirstblock;
  672.   /* The stack of deallocated items is empty. */
  673.   pool->deaditemstack = (VOID *) NULL;
  674. }
  675. /*****************************************************************************/
  676. /*                                                                           */
  677. /*  poolinit()   Initialize a pool of memory for allocation of items.        */
  678. /*                                                                           */
  679. /*  This routine initializes the machinery for allocating items.  A `pool'   */
  680. /*  is created whose records have size at least `bytecount'.  Items will be  */
  681. /*  allocated in `itemcount'-item blocks.  Each item is assumed to be a      */
  682. /*  collection of words, and either pointers or floating-point values are    */
  683. /*  assumed to be the "primary" word type.  (The "primary" word type is used */
  684. /*  to determine alignment of items.)  If `alignment' isn't zero, all items  */
  685. /*  will be `alignment'-byte aligned in memory.  `alignment' must be either  */
  686. /*  a multiple or a factor of the primary word size; powers of two are safe. */
  687. /*  `alignment' is normally used to create a few unused bits at the bottom   */
  688. /*  of each item's pointer, in which information may be stored.              */
  689. /*                                                                           */
  690. /*  Don't change this routine unless you understand it.                      */
  691. /*                                                                           */
  692. /*****************************************************************************/
  693. #ifdef ANSI_DECLARATORS
  694. void poolinit(struct memorypool *pool, int bytecount, int itemcount,
  695.               int firstitemcount, int alignment)
  696. #else /* not ANSI_DECLARATORS */
  697. void poolinit(pool, bytecount, itemcount, firstitemcount, alignment)
  698. struct memorypool *pool;
  699. int bytecount;
  700. int itemcount;
  701. int firstitemcount;
  702. int alignment;
  703. #endif /* not ANSI_DECLARATORS */
  704. {
  705.   /* Find the proper alignment, which must be at least as large as:   */
  706.   /*   - The parameter `alignment'.                                   */
  707.   /*   - sizeof(VOID *), so the stack of dead items can be maintained */
  708.   /*       without unaligned accesses.                                */
  709.   if (alignment > sizeof(VOID *)) {
  710.     pool->alignbytes = alignment;
  711.   } else {
  712.     pool->alignbytes = sizeof(VOID *);
  713.   }
  714.   pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) *
  715.                     pool->alignbytes;
  716.   pool->itemsperblock = itemcount;
  717.   if (firstitemcount == 0) {
  718.     pool->itemsfirstblock = itemcount;
  719.   } else {
  720.     pool->itemsfirstblock = firstitemcount;
  721.   }
  722.   /* Allocate a block of items.  Space for `itemsfirstblock' items and one  */
  723.   /*   pointer (to point to the next block) are allocated, as well as space */
  724.   /*   to ensure alignment of the items.                                    */
  725.   pool->firstblock = (VOID **)
  726.     trimalloc(pool->itemsfirstblock * pool->itembytes + (int) sizeof(VOID *) +
  727.               pool->alignbytes);
  728.   /* Set the next block pointer to NULL. */
  729.   *(pool->firstblock) = (VOID *) NULL;
  730.   poolrestart(pool);
  731. }
  732. /*****************************************************************************/
  733. /*                                                                           */
  734. /*  pooldeinit()   Free to the operating system all memory taken by a pool.  */
  735. /*                                                                           */
  736. /*****************************************************************************/
  737. #ifdef ANSI_DECLARATORS
  738. void pooldeinit(struct memorypool *pool)
  739. #else /* not ANSI_DECLARATORS */
  740. void pooldeinit(pool)
  741. struct memorypool *pool;
  742. #endif /* not ANSI_DECLARATORS */
  743. {
  744.   while (pool->firstblock != (VOID **) NULL) {
  745.     pool->nowblock = (VOID **) *(pool->firstblock);
  746.     trifree((VOID *) pool->firstblock);
  747.     pool->firstblock = pool->nowblock;
  748.   }
  749. }
  750. /*****************************************************************************/
  751. /*                                                                           */
  752. /*  poolalloc()   Allocate space for an item.                                */
  753. /*                                                                           */
  754. /*****************************************************************************/
  755. #ifdef ANSI_DECLARATORS
  756. VOID *poolalloc(struct memorypool *pool)
  757. #else /* not ANSI_DECLARATORS */
  758. VOID *poolalloc(pool)
  759. struct memorypool *pool;
  760. #endif /* not ANSI_DECLARATORS */
  761. {
  762.   VOID *newitem;
  763.   VOID **newblock;
  764.   unsigned long alignptr;
  765.   /* First check the linked list of dead items.  If the list is not   */
  766.   /*   empty, allocate an item from the list rather than a fresh one. */
  767.   if (pool->deaditemstack != (VOID *) NULL) {
  768.     newitem = pool->deaditemstack;               /* Take first item in list. */
  769.     pool->deaditemstack = * (VOID **) pool->deaditemstack;
  770.   } else {
  771.     /* Check if there are any free items left in the current block. */
  772.     if (pool->unallocateditems == 0) {
  773.       /* Check if another block must be allocated. */
  774.       if (*(pool->nowblock) == (VOID *) NULL) {
  775.         /* Allocate a new block of items, pointed to by the previous block. */
  776.         newblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes +
  777.                                        (int) sizeof(VOID *) +
  778.                                        pool->alignbytes);
  779.         *(pool->nowblock) = (VOID *) newblock;
  780.         /* The next block pointer is NULL. */
  781.         *newblock = (VOID *) NULL;
  782.       }
  783.       /* Move to the new block. */
  784.       pool->nowblock = (VOID **) *(pool->nowblock);
  785.       /* Find the first item in the block.    */
  786.       /*   Increment by the size of (VOID *). */
  787.       alignptr = (unsigned long) (pool->nowblock + 1);
  788.       /* Align the item on an `alignbytes'-byte boundary. */
  789.       pool->nextitem = (VOID *)
  790.         (alignptr + (unsigned long) pool->alignbytes -
  791.          (alignptr % (unsigned long) pool->alignbytes));
  792.       /* There are lots of unallocated items left in this block. */
  793.       pool->unallocateditems = pool->itemsperblock;
  794.     }
  795.     /* Allocate a new item. */
  796.     newitem = pool->nextitem;
  797.     /* Advance `nextitem' pointer to next free item in block. */
  798.     pool->nextitem = (VOID *) ((char *) pool->nextitem + pool->itembytes);
  799.     pool->unallocateditems--;
  800.     pool->maxitems++;
  801.   }
  802.   pool->items++;
  803.   return newitem;
  804. }
  805. /*****************************************************************************/
  806. /*                                                                           */
  807. /*  pooldealloc()   Deallocate space for an item.                            */
  808. /*                                                                           */
  809. /*  The deallocated space is stored in a queue for later reuse.              */
  810. /*                                                                           */
  811. /*****************************************************************************/
  812. #ifdef ANSI_DECLARATORS
  813. void pooldealloc(struct memorypool *pool, VOID *dyingitem)
  814. #else /* not ANSI_DECLARATORS */
  815. void pooldealloc(pool, dyingitem)
  816. struct memorypool *pool;
  817. VOID *dyingitem;
  818. #endif /* not ANSI_DECLARATORS */
  819. {
  820.   /* Push freshly killed item onto stack. */
  821.   *((VOID **) dyingitem) = pool->deaditemstack;
  822.   pool->deaditemstack = dyingitem;
  823.   pool->items--;
  824. }
  825. /*****************************************************************************/
  826. /*                                                                           */
  827. /*  traversalinit()   Prepare to traverse the entire list of items.          */
  828. /*                                                                           */
  829. /*  This routine is used in conjunction with traverse().                     */
  830. /*                                                                           */
  831. /*****************************************************************************/
  832. #ifdef ANSI_DECLARATORS
  833. void traversalinit(struct memorypool *pool)
  834. #else /* not ANSI_DECLARATORS */
  835. void traversalinit(pool)
  836. struct memorypool *pool;
  837. #endif /* not ANSI_DECLARATORS */
  838. {
  839.   unsigned long alignptr;
  840.   /* Begin the traversal in the first block. */
  841.   pool->pathblock = pool->firstblock;
  842.   /* Find the first item in the block.  Increment by the size of (VOID *). */
  843.   alignptr = (unsigned long) (pool->pathblock + 1);
  844.   /* Align with item on an `alignbytes'-byte boundary. */
  845.   pool->pathitem = (VOID *)
  846.     (alignptr + (unsigned long) pool->alignbytes -
  847.      (alignptr % (unsigned long) pool->alignbytes));
  848.   /* Set the number of items left in the current block. */
  849.   pool->pathitemsleft = pool->itemsfirstblock;
  850. }
  851. /*****************************************************************************/
  852. /*                                                                           */
  853. /*  traverse()   Find the next item in the list.                             */
  854. /*                                                                           */
  855. /*  This routine is used in conjunction with traversalinit().  Be forewarned */
  856. /*  that this routine successively returns all items in the list, including  */
  857. /*  deallocated ones on the deaditemqueue.  It's up to you to figure out     */
  858. /*  which ones are actually dead.  Why?  I don't want to allocate extra      */
  859. /*  space just to demarcate dead items.  It can usually be done more         */
  860. /*  space-efficiently by a routine that knows something about the structure  */
  861. /*  of the item.                                                             */
  862. /*                                                                           */
  863. /*****************************************************************************/
  864. #ifdef ANSI_DECLARATORS
  865. VOID *traverse(struct memorypool *pool)
  866. #else /* not ANSI_DECLARATORS */
  867. VOID *traverse(pool)
  868. struct memorypool *pool;
  869. #endif /* not ANSI_DECLARATORS */
  870. {
  871.   VOID *newitem;
  872.   unsigned long alignptr;
  873.   /* Stop upon exhausting the list of items. */
  874.   if (pool->pathitem == pool->nextitem) {
  875.     return (VOID *) NULL;
  876.   }
  877.   /* Check whether any untraversed items remain in the current block. */
  878.   if (pool->pathitemsleft == 0) {
  879.     /* Find the next block. */
  880.     pool->pathblock = (VOID **) *(pool->pathblock);
  881.     /* Find the first item in the block.  Increment by the size of (VOID *). */
  882.     alignptr = (unsigned long) (pool->pathblock + 1);
  883.     /* Align with item on an `alignbytes'-byte boundary. */
  884.     pool->pathitem = (VOID *)
  885.       (alignptr + (unsigned long) pool->alignbytes -
  886.        (alignptr % (unsigned long) pool->alignbytes));
  887.     /* Set the number of items left in the current block. */
  888.     pool->pathitemsleft = pool->itemsperblock;
  889.   }
  890.   newitem = pool->pathitem;
  891.   /* Find the next item in the block. */
  892.   pool->pathitem = (VOID *) ((char *) pool->pathitem + pool->itembytes);
  893.   pool->pathitemsleft--;
  894.   return newitem;
  895. }
  896. /*****************************************************************************/
  897. /*                                                                           */
  898. /*  dummyinit()   Initialize the triangle that fills "outer space" and the   */
  899. /*                omnipresent subsegment.                                    */
  900. /*                                                                           */
  901. /*  The triangle that fills "outer space," called `dummytri', is pointed to  */
  902. /*  by every triangle and subsegment on a boundary (be it outer or inner) of */
  903. /*  the triangulation.  Also, `dummytri' points to one of the triangles on   */
  904. /*  the convex hull (until the holes and concavities are carved), making it  */
  905. /*  possible to find a starting triangle for point location.                 */
  906. /*                                                                           */
  907. /*  The omnipresent subsegment, `dummysub', is pointed to by every triangle  */
  908. /*  or subsegment that doesn't have a full complement of real subsegments    */
  909. /*  to point to.                                                             */
  910. /*                                                                           */
  911. /*  `dummytri' and `dummysub' are generally required to fulfill only a few   */
  912. /*  invariants:  their vertices must remain NULL and `dummytri' must always  */
  913. /*  be bonded (at offset zero) to some triangle on the convex hull of the    */
  914. /*  mesh, via a boundary edge.  Otherwise, the connections of `dummytri' and */
  915. /*  `dummysub' may change willy-nilly.  This makes it possible to avoid      */
  916. /*  writing a good deal of special-case code (in the edge flip, for example) */
  917. /*  for dealing with the boundary of the mesh, places where no subsegment is */
  918. /*  present, and so forth.  Other entities are frequently bonded to          */
  919. /*  `dummytri' and `dummysub' as if they were real mesh entities, with no    */
  920. /*  harm done.                                                               */
  921. /*                                                                           */
  922. /*****************************************************************************/
  923. #ifdef ANSI_DECLARATORS
  924. void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes,
  925.                int subsegbytes)
  926. #else /* not ANSI_DECLARATORS */
  927. void dummyinit(m, b, trianglebytes, subsegbytes)
  928. struct mesh *m;
  929. struct behavior *b;
  930. int trianglebytes;
  931. int subsegbytes;
  932. #endif /* not ANSI_DECLARATORS */
  933. {
  934.   unsigned long alignptr;
  935.   /* Set up `dummytri', the `triangle' that occupies "outer space." */
  936.   m->dummytribase = (triangle *) trimalloc(trianglebytes +
  937.                                            m->triangles.alignbytes);
  938.   /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
  939.   alignptr = (unsigned long) m->dummytribase;
  940.   m->dummytri = (triangle *)
  941.     (alignptr + (unsigned long) m->triangles.alignbytes -
  942.      (alignptr % (unsigned long) m->triangles.alignbytes));
  943.   /* Initialize the three adjoining triangles to be "outer space."  These  */
  944.   /*   will eventually be changed by various bonding operations, but their */
  945.   /*   values don't really matter, as long as they can legally be          */
  946.   /*   dereferenced.                                                       */
  947.   m->dummytri[0] = (triangle) m->dummytri;
  948.   m->dummytri[1] = (triangle) m->dummytri;
  949.   m->dummytri[2] = (triangle) m->dummytri;
  950.   /* Three NULL vertices. */
  951.   m->dummytri[3] = (triangle) NULL;
  952.   m->dummytri[4] = (triangle) NULL;
  953.   m->dummytri[5] = (triangle) NULL;
  954.   if (b->usesegments) {
  955.     /* Set up `dummysub', the omnipresent subsegment pointed to by any */
  956.     /*   triangle side or subsegment end that isn't attached to a real */
  957.     /*   subsegment.                                                   */
  958.     m->dummysubbase = (subseg *) trimalloc(subsegbytes +
  959.                                            m->subsegs.alignbytes);
  960.     /* Align `dummysub' on a `subsegs.alignbytes'-byte boundary. */
  961.     alignptr = (unsigned long) m->dummysubbase;
  962.     m->dummysub = (subseg *)
  963.       (alignptr + (unsigned long) m->subsegs.alignbytes -
  964.        (alignptr % (unsigned long) m->subsegs.alignbytes));
  965.     /* Initialize the two adjoining subsegments to be the omnipresent      */
  966.     /*   subsegment.  These will eventually be changed by various bonding  */
  967.     /*   operations, but their values don't really matter, as long as they */
  968.     /*   can legally be dereferenced.                                      */
  969.     m->dummysub[0] = (subseg) m->dummysub;
  970.     m->dummysub[1] = (subseg) m->dummysub;
  971.     /* Four NULL vertices. */
  972.     m->dummysub[2] = (subseg) NULL;
  973.     m->dummysub[3] = (subseg) NULL;
  974.     m->dummysub[4] = (subseg) NULL;
  975.     m->dummysub[5] = (subseg) NULL;
  976.     /* Initialize the two adjoining triangles to be "outer space." */
  977.     m->dummysub[6] = (subseg) m->dummytri;
  978.     m->dummysub[7] = (subseg) m->dummytri;
  979.     /* Set the boundary marker to zero. */
  980.     * (int *) (m->dummysub + 8) = 0;
  981.     /* Initialize the three adjoining subsegments of `dummytri' to be */
  982.     /*   the omnipresent subsegment.                                  */
  983.     m->dummytri[6] = (triangle) m->dummysub;
  984.     m->dummytri[7] = (triangle) m->dummysub;
  985.     m->dummytri[8] = (triangle) m->dummysub;
  986.   }
  987. }
  988. /*****************************************************************************/
  989. /*                                                                           */
  990. /*  initializevertexpool()   Calculate the size of the vertex data structure */
  991. /*                           and initialize its memory pool.                 */
  992. /*                                                                           */
  993. /*  This routine also computes the `vertexmarkindex' and `vertex2triindex'   */
  994. /*  indices used to find values within each vertex.                          */
  995. /*                                                                           */
  996. /*****************************************************************************/
  997. #ifdef ANSI_DECLARATORS
  998. void initializevertexpool(struct mesh *m, struct behavior *b)
  999. #else /* not ANSI_DECLARATORS */
  1000. void initializevertexpool(m, b)
  1001. struct mesh *m;
  1002. struct behavior *b;
  1003. #endif /* not ANSI_DECLARATORS */
  1004. {
  1005.   int vertexsize;
  1006.   /* The index within each vertex at which the boundary marker is found,    */
  1007.   /*   followed by the vertex type.  Ensure the vertex marker is aligned to */
  1008.   /*   a sizeof(int)-byte address.                                          */
  1009.   m->vertexmarkindex = ((m->mesh_dim + m->nextras) * sizeof(REAL) +
  1010.                         sizeof(int) - 1) /
  1011.                        sizeof(int);
  1012.   vertexsize = (m->vertexmarkindex + 2) * sizeof(int);
  1013.   if (b->poly) {
  1014.     /* The index within each vertex at which a triangle pointer is found.  */
  1015.     /*   Ensure the pointer is aligned to a sizeof(triangle)-byte address. */
  1016.     m->vertex2triindex = (vertexsize + sizeof(triangle) - 1) /
  1017.                          sizeof(triangle);
  1018.     vertexsize = (m->vertex2triindex + 1) * sizeof(triangle);
  1019.   }
  1020.   /* Initialize the pool of vertices. */
  1021.   poolinit(&m->vertices, vertexsize, VERTEXPERBLOCK,
  1022.            m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK,
  1023.            sizeof(REAL));
  1024. }
  1025. /*****************************************************************************/
  1026. /*                                                                           */
  1027. /*  initializetrisubpools()   Calculate the sizes of the triangle and        */
  1028. /*                            subsegment data structures and initialize      */
  1029. /*                            their memory pools.                            */
  1030. /*                                                                           */
  1031. /*  This routine also computes the `highorderindex', `elemattribindex', and  */
  1032. /*  `areaboundindex' indices used to find values within each triangle.       */
  1033. /*                                                                           */
  1034. /*****************************************************************************/
  1035. #ifdef ANSI_DECLARATORS
  1036. void initializetrisubpools(struct mesh *m, struct behavior *b)
  1037. #else /* not ANSI_DECLARATORS */
  1038. void initializetrisubpools(m, b)
  1039. struct mesh *m;
  1040. struct behavior *b;
  1041. #endif /* not ANSI_DECLARATORS */
  1042. {
  1043.   int trisize;
  1044.   /* The index within each triangle at which the extra nodes (above three)  */
  1045.   /*   associated with high order elements are found.  There are three      */
  1046.   /*   pointers to other triangles, three pointers to corners, and possibly */
  1047.   /*   three pointers to subsegments before the extra nodes.                */
  1048.   m->highorderindex = 6 + (b->usesegments * 3);
  1049.   /* The number of bytes occupied by a triangle. */
  1050.   trisize = ((b->order + 1) * (b->order + 2) / 2 + (m->highorderindex - 3)) *
  1051.             sizeof(triangle);
  1052.   /* The index within each triangle at which its attributes are found, */
  1053.   /*   where the index is measured in REALs.                           */
  1054.   m->elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
  1055.   /* The index within each triangle at which the maximum area constraint  */
  1056.   /*   is found, where the index is measured in REALs.  Note that if the  */
  1057.   /*   `regionattrib' flag is set, an additional attribute will be added. */
  1058.   m->areaboundindex = m->elemattribindex + m->eextras + b->regionattrib;
  1059.   /* If triangle attributes or an area bound are needed, increase the number */
  1060.   /*   of bytes occupied by a triangle.                                      */
  1061.   if (b->vararea) {
  1062.     trisize = (m->areaboundindex + 1) * sizeof(REAL);
  1063.   } else if (m->eextras + b->regionattrib > 0) {
  1064.     trisize = m->areaboundindex * sizeof(REAL);
  1065.   }
  1066.   /* If a Voronoi diagram or triangle neighbor graph is requested, make    */
  1067.   /*   sure there's room to store an integer index in each triangle.  This */
  1068.   /*   integer index can occupy the same space as the subsegment pointers  */
  1069.   /*   or attributes or area constraint or extra nodes.                    */
  1070.   if ((b->voronoi || b->neighbors) &&
  1071.       (trisize < 6 * sizeof(triangle) + sizeof(int))) {
  1072.     trisize = 6 * sizeof(triangle) + sizeof(int);
  1073.   }
  1074.   /* Having determined the memory size of a triangle, initialize the pool. */
  1075.   poolinit(&m->triangles, trisize, TRIPERBLOCK,
  1076.            (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2) :
  1077.            TRIPERBLOCK, 4);
  1078.   if (b->usesegments) {
  1079.     /* Initialize the pool of subsegments.  Take into account all eight */
  1080.     /*   pointers and one boundary marker.                              */
  1081.     poolinit(&m->subsegs, 8 * sizeof(triangle) + sizeof(int),
  1082.              SUBSEGPERBLOCK, SUBSEGPERBLOCK, 4);
  1083.     /* Initialize the "outer space" triangle and omnipresent subsegment. */
  1084.     dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes);
  1085.   } else {
  1086.     /* Initialize the "outer space" triangle. */
  1087.     dummyinit(m, b, m->triangles.itembytes, 0);
  1088.   }
  1089. }
  1090. /*****************************************************************************/
  1091. /*                                                                           */
  1092. /*  triangledealloc()   Deallocate space for a triangle, marking it dead.    */
  1093. /*                                                                           */
  1094. /*****************************************************************************/
  1095. #ifdef ANSI_DECLARATORS
  1096. void triangledealloc(struct mesh *m, triangle *dyingtriangle)
  1097. #else /* not ANSI_DECLARATORS */
  1098. void triangledealloc(m, dyingtriangle)
  1099. struct mesh *m;
  1100. triangle *dyingtriangle;
  1101. #endif /* not ANSI_DECLARATORS */
  1102. {
  1103.   /* Mark the triangle as dead.  This makes it possible to detect dead */
  1104.   /*   triangles when traversing the list of all triangles.            */
  1105.   killtri(dyingtriangle);
  1106.   pooldealloc(&m->triangles, (VOID *) dyingtriangle);
  1107. }
  1108. /*****************************************************************************/
  1109. /*                                                                           */
  1110. /*  triangletraverse()   Traverse the triangles, skipping dead ones.         */
  1111. /*                                                                           */
  1112. /*****************************************************************************/
  1113. #ifdef ANSI_DECLARATORS
  1114. triangle *triangletraverse(struct mesh *m)
  1115. #else /* not ANSI_DECLARATORS */
  1116. triangle *triangletraverse(m)
  1117. struct mesh *m;
  1118. #endif /* not ANSI_DECLARATORS */
  1119. {
  1120.   triangle *newtriangle;
  1121.   do {
  1122.     newtriangle = (triangle *) traverse(&m->triangles);
  1123.     if (newtriangle == (triangle *) NULL) {
  1124.       return (triangle *) NULL;
  1125.     }
  1126.   } while (deadtri(newtriangle));                         /* Skip dead ones. */
  1127.   return newtriangle;
  1128. }
  1129. /*****************************************************************************/
  1130. /*                                                                           */
  1131. /*  subsegdealloc()   Deallocate space for a subsegment, marking it dead.    */
  1132. /*                                                                           */
  1133. /*****************************************************************************/
  1134. #ifdef ANSI_DECLARATORS
  1135. void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
  1136. #else /* not ANSI_DECLARATORS */
  1137. void subsegdealloc(m, dyingsubseg)
  1138. struct mesh *m;
  1139. subseg *dyingsubseg;
  1140. #endif /* not ANSI_DECLARATORS */
  1141. {
  1142.   /* Mark the subsegment as dead.  This makes it possible to detect dead */
  1143.   /*   subsegments when traversing the list of all subsegments.          */
  1144.   killsubseg(dyingsubseg);
  1145.   pooldealloc(&m->subsegs, (VOID *) dyingsubseg);
  1146. }
  1147. /*****************************************************************************/
  1148. /*                                                                           */
  1149. /*  subsegtraverse()   Traverse the subsegments, skipping dead ones.         */
  1150. /*                                                                           */
  1151. /*****************************************************************************/
  1152. #ifdef ANSI_DECLARATORS
  1153. subseg *subsegtraverse(struct mesh *m)
  1154. #else /* not ANSI_DECLARATORS */
  1155. subseg *subsegtraverse(m)
  1156. struct mesh *m;
  1157. #endif /* not ANSI_DECLARATORS */
  1158. {
  1159.   subseg *newsubseg;
  1160.   do {
  1161.     newsubseg = (subseg *) traverse(&m->subsegs);
  1162.     if (newsubseg == (subseg *) NULL) {
  1163.       return (subseg *) NULL;
  1164.     }
  1165.   } while (deadsubseg(newsubseg));                        /* Skip dead ones. */
  1166.   return newsubseg;
  1167. }
  1168. /*****************************************************************************/
  1169. /*                                                                           */
  1170. /*  vertexdealloc()   Deallocate space for a vertex, marking it dead.        */
  1171. /*                                                                           */
  1172. /*****************************************************************************/
  1173. #ifdef ANSI_DECLARATORS
  1174. void vertexdealloc(struct mesh *m, vertex dyingvertex)
  1175. #else /* not ANSI_DECLARATORS */
  1176. void vertexdealloc(m, dyingvertex)
  1177. struct mesh *m;
  1178. vertex dyingvertex;
  1179. #endif /* not ANSI_DECLARATORS */
  1180. {
  1181.   /* Mark the vertex as dead.  This makes it possible to detect dead */
  1182.   /*   vertices when traversing the list of all vertices.            */
  1183.   setvertextype(dyingvertex, DEADVERTEX);
  1184.   pooldealloc(&m->vertices, (VOID *) dyingvertex);
  1185. }
  1186. /*****************************************************************************/
  1187. /*                                                                           */
  1188. /*  vertextraverse()   Traverse the vertices, skipping dead ones.            */
  1189. /*                                                                           */
  1190. /*****************************************************************************/
  1191. #ifdef ANSI_DECLARATORS
  1192. vertex vertextraverse(struct mesh *m)
  1193. #else /* not ANSI_DECLARATORS */
  1194. vertex vertextraverse(m)
  1195. struct mesh *m;
  1196. #endif /* not ANSI_DECLARATORS */
  1197. {
  1198.   vertex newvertex;
  1199.   do {
  1200.     newvertex = (vertex) traverse(&m->vertices);
  1201.     if (newvertex == (vertex) NULL) {
  1202.       return (vertex) NULL;
  1203.     }
  1204.   } while (vertextype(newvertex) == DEADVERTEX);          /* Skip dead ones. */
  1205.   return newvertex;
  1206. }
  1207. /*****************************************************************************/
  1208. /*                                                                           */
  1209. /*  badsubsegdealloc()   Deallocate space for a bad subsegment, marking it   */
  1210. /*                       dead.                                               */
  1211. /*                                                                           */
  1212. /*****************************************************************************/
  1213. #ifndef CDT_ONLY
  1214. #ifdef ANSI_DECLARATORS
  1215. void badsubsegdealloc(struct mesh *m, struct badsubseg *dyingseg)
  1216. #else /* not ANSI_DECLARATORS */
  1217. void badsubsegdealloc(m, dyingseg)
  1218. struct mesh *m;
  1219. struct badsubseg *dyingseg;
  1220. #endif /* not ANSI_DECLARATORS */
  1221. {
  1222.   /* Set subsegment's origin to NULL.  This makes it possible to detect dead */
  1223.   /*   badsubsegs when traversing the list of all badsubsegs             .   */
  1224.   dyingseg->subsegorg = (vertex) NULL;
  1225.   pooldealloc(&m->badsubsegs, (VOID *) dyingseg);
  1226. }
  1227. #endif /* not CDT_ONLY */
  1228. /*****************************************************************************/
  1229. /*                                                                           */
  1230. /*  badsubsegtraverse()   Traverse the bad subsegments, skipping dead ones.  */
  1231. /*                                                                           */
  1232. /*****************************************************************************/
  1233. #ifndef CDT_ONLY
  1234. #ifdef ANSI_DECLARATORS
  1235. struct badsubseg *badsubsegtraverse(struct mesh *m)
  1236. #else /* not ANSI_DECLARATORS */
  1237. struct badsubseg *badsubsegtraverse(m)
  1238. struct mesh *m;
  1239. #endif /* not ANSI_DECLARATORS */
  1240. {
  1241.   struct badsubseg *newseg;
  1242.   do {
  1243.     newseg = (struct badsubseg *) traverse(&m->badsubsegs);
  1244.     if (newseg == (struct badsubseg *) NULL) {
  1245.       return (struct badsubseg *) NULL;
  1246.     }
  1247.   } while (newseg->subsegorg == (vertex) NULL);           /* Skip dead ones. */
  1248.   return newseg;
  1249. }
  1250. #endif /* not CDT_ONLY */
  1251. /*****************************************************************************/
  1252. /*                                                                           */
  1253. /*  getvertex()   Get a specific vertex, by number, from the list.           */
  1254. /*                                                                           */
  1255. /*  The first vertex is number 'firstnumber'.                                */
  1256. /*                                                                           */
  1257. /*  Note that this takes O(n) time (with a small constant, if VERTEXPERBLOCK */
  1258. /*  is large).  I don't care to take the trouble to make it work in constant */
  1259. /*  time.                                                                    */
  1260. /*                                                                           */
  1261. /*****************************************************************************/
  1262. #ifdef ANSI_DECLARATORS
  1263. vertex getvertex(struct mesh *m, struct behavior *b, int number)
  1264. #else /* not ANSI_DECLARATORS */
  1265. vertex getvertex(m, b, number)
  1266. struct mesh *m;
  1267. struct behavior *b;
  1268. int number;
  1269. #endif /* not ANSI_DECLARATORS */
  1270. {
  1271.   VOID **getblock;
  1272.   char *foundvertex;
  1273.   unsigned long alignptr;
  1274.   int current;
  1275.   getblock = m->vertices.firstblock;
  1276.   current = b->firstnumber;
  1277.   /* Find the right block. */
  1278.   if (current + m->vertices.itemsfirstblock <= number) {
  1279.     getblock = (VOID **) *getblock;
  1280.     current += m->vertices.itemsfirstblock;
  1281.     while (current + m->vertices.itemsperblock <= number) {
  1282.       getblock = (VOID **) *getblock;
  1283.       current += m->vertices.itemsperblock;
  1284.     }
  1285.   }
  1286.   /* Now find the right vertex. */
  1287.   alignptr = (unsigned long) (getblock + 1);
  1288.   foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes -
  1289.                           (alignptr % (unsigned long) m->vertices.alignbytes));
  1290.   return (vertex) (foundvertex + m->vertices.itembytes * (number - current));
  1291. }
  1292. /*****************************************************************************/
  1293. /*                                                                           */
  1294. /*  triangledeinit()   Free all remaining allocated memory.                  */
  1295. /*                                                                           */
  1296. /*****************************************************************************/
  1297. #ifdef ANSI_DECLARATORS
  1298. void triangledeinit(struct mesh *m, struct behavior *b)
  1299. #else /* not ANSI_DECLARATORS */
  1300. void triangledeinit(m, b)
  1301. struct mesh *m;
  1302. struct behavior *b;
  1303. #endif /* not ANSI_DECLARATORS */
  1304. {
  1305.   pooldeinit(&m->triangles);
  1306.   trifree((VOID *) m->dummytribase);
  1307.   if (b->usesegments) {
  1308.     pooldeinit(&m->subsegs);
  1309.     trifree((VOID *) m->dummysubbase);
  1310.   }
  1311.   pooldeinit(&m->vertices);
  1312. #ifndef CDT_ONLY
  1313.   if (b->quality) {
  1314.     pooldeinit(&m->badsubsegs);
  1315.     if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
  1316.       pooldeinit(&m->badtriangles);
  1317.       pooldeinit(&m->flipstackers);
  1318.     }
  1319.   }
  1320. #endif /* not CDT_ONLY */
  1321. }
  1322. /**                                                                         **/
  1323. /**                                                                         **/
  1324. /********* Memory management routines end here                       *********/
  1325. /********* Constructors begin here                                   *********/
  1326. /**                                                                         **/
  1327. /**                                                                         **/
  1328. /*****************************************************************************/
  1329. /*                                                                           */
  1330. /*  maketriangle()   Create a new triangle with orientation zero.            */
  1331. /*                                                                           */
  1332. /*****************************************************************************/
  1333. #ifdef ANSI_DECLARATORS
  1334. void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
  1335. #else /* not ANSI_DECLARATORS */
  1336. void maketriangle(m, b, newotri)
  1337. struct mesh *m;
  1338. struct behavior *b;
  1339. struct otri *newotri;
  1340. #endif /* not ANSI_DECLARATORS */
  1341. {
  1342.   int i;
  1343.   newotri->tri = (triangle *) poolalloc(&m->triangles);
  1344.   /* Initialize the three adjoining triangles to be "outer space". */
  1345.   newotri->tri[0] = (triangle) m->dummytri;
  1346.   newotri->tri[1] = (triangle) m->dummytri;
  1347.   newotri->tri[2] = (triangle) m->dummytri;
  1348.   /* Three NULL vertices. */
  1349.   newotri->tri[3] = (triangle) NULL;
  1350.   newotri->tri[4] = (triangle) NULL;
  1351.   newotri->tri[5] = (triangle) NULL;
  1352.   if (b->usesegments) {
  1353.     /* Initialize the three adjoining subsegments to be the omnipresent */
  1354.     /*   subsegment.                                                    */
  1355.     newotri->tri[6] = (triangle) m->dummysub;
  1356.     newotri->tri[7] = (triangle) m->dummysub;
  1357.     newotri->tri[8] = (triangle) m->dummysub;
  1358.   }
  1359.   for (i = 0; i < m->eextras; i++) {
  1360.     setelemattribute(*newotri, i, 0.0);
  1361.   }
  1362.   if (b->vararea) {
  1363.     setareabound(*newotri, -1.0);
  1364.   }
  1365.   newotri->orient = 0;
  1366. }
  1367. /*****************************************************************************/
  1368. /*                                                                           */
  1369. /*  makesubseg()   Create a new subsegment with orientation zero.            */
  1370. /*                                                                           */
  1371. /*****************************************************************************/
  1372. #ifdef ANSI_DECLARATORS
  1373. void makesubseg(struct mesh *m, struct osub *newsubseg)
  1374. #else /* not ANSI_DECLARATORS */
  1375. void makesubseg(m, newsubseg)
  1376. struct mesh *m;
  1377. struct osub *newsubseg;
  1378. #endif /* not ANSI_DECLARATORS */
  1379. {
  1380.   newsubseg->ss = (subseg *) poolalloc(&m->subsegs);
  1381.   /* Initialize the two adjoining subsegments to be the omnipresent */
  1382.   /*   subsegment.                                                  */
  1383.   newsubseg->ss[0] = (subseg) m->dummysub;
  1384.   newsubseg->ss[1] = (subseg) m->dummysub;
  1385.   /* Four NULL vertices. */
  1386.   newsubseg->ss[2] = (subseg) NULL;
  1387.   newsubseg->ss[3] = (subseg) NULL;
  1388.   newsubseg->ss[4] = (subseg) NULL;
  1389.   newsubseg->ss[5] = (subseg) NULL;
  1390.   /* Initialize the two adjoining triangles to be "outer space." */
  1391.   newsubseg->ss[6] = (subseg) m->dummytri;
  1392.   newsubseg->ss[7] = (subseg) m->dummytri;
  1393.   /* Set the boundary marker to zero. */
  1394.   setmark(*newsubseg, 0);
  1395.   newsubseg->ssorient = 0;
  1396. }
  1397. /**                                                                         **/
  1398. /**                                                                         **/
  1399. /********* Constructors end here                                     *********/
  1400. /********* Geometric primitives begin here                           *********/
  1401. /**                                                                         **/
  1402. /**                                                                         **/
  1403. /* The adaptive exact arithmetic geometric predicates implemented herein are */
  1404. /*   described in detail in my paper, "Adaptive Precision Floating-Point     */
  1405. /*   Arithmetic and Fast Robust Geometric Predicates."  See the header for a */
  1406. /*   full citation.                                                          */
  1407. /* Which of the following two methods of finding the absolute values is      */
  1408. /*   fastest is compiler-dependent.  A few compilers can inline and optimize */
  1409. /*   the fabs() call; but most will incur the overhead of a function call,   */
  1410. /*   which is disastrously slow.  A faster way on IEEE machines might be to  */
  1411. /*   mask the appropriate bit, but that's difficult to do in C without       */
  1412. /*   forcing the value to be stored to memory (rather than be kept in the    */
  1413. /*   register to which the optimizer assigned it).                           */
  1414. #define Absolute(a)  ((a) >= 0.0 ? (a) : -(a))
  1415. /* #define Absolute(a)  fabs(a) */
  1416. /* Many of the operations are broken up into two pieces, a main part that    */
  1417. /*   performs an approximate operation, and a "tail" that computes the       */
  1418. /*   roundoff error of that operation.                                       */
  1419. /*                                                                           */
  1420. /* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(),    */
  1421. /*   Split(), and Two_Product() are all implemented as described in the      */
  1422. /*   reference.  Each of these macros requires certain variables to be       */
  1423. /*   defined in the calling routine.  The variables `bvirt', `c', `abig',    */
  1424. /*   `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because   */
  1425. /*   they store the result of an operation that may incur roundoff error.    */
  1426. /*   The input parameter `x' (or the highest numbered `x_' parameter) must   */
  1427. /*   also be declared `INEXACT'.                                             */
  1428. #define Fast_Two_Sum_Tail(a, b, x, y) 
  1429.   bvirt = x - a; 
  1430.   y = b - bvirt
  1431. #define Fast_Two_Sum(a, b, x, y) 
  1432.   x = (REAL) (a + b); 
  1433.   Fast_Two_Sum_Tail(a, b, x, y)
  1434. #define Two_Sum_Tail(a, b, x, y) 
  1435.   bvirt = (REAL) (x - a); 
  1436.   avirt = x - bvirt; 
  1437.   bround = b - bvirt; 
  1438.   around = a - avirt; 
  1439.   y = around + bround
  1440. #define Two_Sum(a, b, x, y) 
  1441.   x = (REAL) (a + b); 
  1442.   Two_Sum_Tail(a, b, x, y)
  1443. #define Two_Diff_Tail(a, b, x, y) 
  1444.   bvirt = (REAL) (a - x); 
  1445.   avirt = x + bvirt; 
  1446.   bround = bvirt - b; 
  1447.   around = a - avirt; 
  1448.   y = around + bround
  1449. #define Two_Diff(a, b, x, y) 
  1450.   x = (REAL) (a - b); 
  1451.   Two_Diff_Tail(a, b, x, y)
  1452. #define Split(a, ahi, alo) 
  1453.   c = (REAL) (splitter * a); 
  1454.   abig = (REAL) (c - a); 
  1455.   ahi = c - abig; 
  1456.   alo = a - ahi
  1457. #define Two_Product_Tail(a, b, x, y) 
  1458.   Split(a, ahi, alo); 
  1459.   Split(b, bhi, blo); 
  1460.   err1 = x - (ahi * bhi); 
  1461.   err2 = err1 - (alo * bhi); 
  1462.   err3 = err2 - (ahi * blo); 
  1463.   y = (alo * blo) - err3
  1464. #define Two_Product(a, b, x, y) 
  1465.   x = (REAL) (a * b); 
  1466.   Two_Product_Tail(a, b, x, y)
  1467. /* Two_Product_Presplit() is Two_Product() where one of the inputs has       */
  1468. /*   already been split.  Avoids redundant splitting.                        */
  1469. #define Two_Product_Presplit(a, b, bhi, blo, x, y) 
  1470.   x = (REAL) (a * b); 
  1471.   Split(a, ahi, alo); 
  1472.   err1 = x - (ahi * bhi); 
  1473.   err2 = err1 - (alo * bhi); 
  1474.   err3 = err2 - (ahi * blo); 
  1475.   y = (alo * blo) - err3
  1476. /* Square() can be done more quickly than Two_Product().                     */
  1477. #define Square_Tail(a, x, y) 
  1478.   Split(a, ahi, alo); 
  1479.   err1 = x - (ahi * ahi); 
  1480.   err3 = err1 - ((ahi + ahi) * alo); 
  1481.   y = (alo * alo) - err3
  1482. #define Square(a, x, y) 
  1483.   x = (REAL) (a * a); 
  1484.   Square_Tail(a, x, y)
  1485. /* Macros for summing expansions of various fixed lengths.  These are all    */
  1486. /*   unrolled versions of Expansion_Sum().                                   */
  1487. #define Two_One_Sum(a1, a0, b, x2, x1, x0) 
  1488.   Two_Sum(a0, b , _i, x0); 
  1489.   Two_Sum(a1, _i, x2, x1)
  1490. #define Two_One_Diff(a1, a0, b, x2, x1, x0) 
  1491.   Two_Diff(a0, b , _i, x0); 
  1492.   Two_Sum( a1, _i, x2, x1)
  1493. #define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) 
  1494.   Two_One_Sum(a1, a0, b0, _j, _0, x0); 
  1495.   Two_One_Sum(_j, _0, b1, x3, x2, x1)
  1496. #define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) 
  1497.   Two_One_Diff(a1, a0, b0, _j, _0, x0); 
  1498.   Two_One_Diff(_j, _0, b1, x3, x2, x1)
  1499. /* Macro for multiplying a two-component expansion by a single component.    */
  1500. #define Two_One_Product(a1, a0, b, x3, x2, x1, x0) 
  1501.   Split(b, bhi, blo); 
  1502.   Two_Product_Presplit(a0, b, bhi, blo, _i, x0); 
  1503.   Two_Product_Presplit(a1, b, bhi, blo, _j, _0); 
  1504.   Two_Sum(_i, _0, _k, x1); 
  1505.   Fast_Two_Sum(_j, _k, x3, x2)
  1506. /*****************************************************************************/
  1507. /*                                                                           */
  1508. /*  exactinit()   Initialize the variables used for exact arithmetic.        */
  1509. /*                                                                           */
  1510. /*  `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in   */
  1511. /*  floating-point arithmetic.  `epsilon' bounds the relative roundoff       */
  1512. /*  error.  It is used for floating-point error analysis.                    */
  1513. /*                                                                           */
  1514. /*  `splitter' is used to split floating-point numbers into two half-        */
  1515. /*  length significands for exact multiplication.                            */
  1516. /*                                                                           */
  1517. /*  I imagine that a highly optimizing compiler might be too smart for its   */
  1518. /*  own good, and somehow cause this routine to fail, if it pretends that    */
  1519. /*  floating-point arithmetic is too much like real arithmetic.              */
  1520. /*                                                                           */
  1521. /*  Don't change this routine unless you fully understand it.                */
  1522. /*                                                                           */
  1523. /*****************************************************************************/
  1524. void exactinit()
  1525. {
  1526.   REAL half;
  1527.   REAL check, lastcheck;
  1528.   int every_other;
  1529. #ifdef LINUX
  1530.   int cword;
  1531. #endif /* LINUX */
  1532. #ifdef CPU86
  1533. #ifdef SINGLE
  1534.   _control87(_PC_24, _MCW_PC); /* Set FPU control word for single precision. */
  1535. #else /* not SINGLE */
  1536.   _control87(_PC_53, _MCW_PC); /* Set FPU control word for double precision. */
  1537. #endif /* not SINGLE */
  1538. #endif /* CPU86 */
  1539. #ifdef LINUX
  1540. #ifdef SINGLE
  1541.   /*  cword = 4223; */
  1542.   cword = 4210;                 /* set FPU control word for single precision */
  1543. #else /* not SINGLE */
  1544.   /*  cword = 4735; */
  1545.   cword = 4722;                 /* set FPU control word for double precision */
  1546. #endif /* not SINGLE */
  1547.   _FPU_SETCW(cword);
  1548. #endif /* LINUX */
  1549.   every_other = 1;
  1550.   half = 0.5;
  1551.   epsilon = 1.0;
  1552.   splitter = 1.0;
  1553.   check = 1.0;
  1554.   /* Repeatedly divide `epsilon' by two until it is too small to add to      */
  1555.   /*   one without causing roundoff.  (Also check if the sum is equal to     */
  1556.   /*   the previous sum, for machines that round up instead of using exact   */
  1557.   /*   rounding.  Not that these routines will work on such machines.)       */
  1558.   do {
  1559.     lastcheck = check;
  1560.     epsilon *= half;
  1561.     if (every_other) {
  1562.       splitter *= 2.0;
  1563.     }
  1564.     every_other = !every_other;
  1565.     check = 1.0 + epsilon;
  1566.   } while ((check != 1.0) && (check != lastcheck));
  1567.   splitter += 1.0;
  1568.   /* Error bounds for orientation and incircle tests. */
  1569.   resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
  1570.   ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
  1571.   ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
  1572.   ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
  1573.   iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
  1574.   iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
  1575.   iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
  1576.   o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
  1577.   o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
  1578.   o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
  1579. }
  1580. /*****************************************************************************/
  1581. /*                                                                           */
  1582. /*  fast_expansion_sum_zeroelim()   Sum two expansions, eliminating zero     */
  1583. /*                                  components from the output expansion.    */
  1584. /*                                                                           */
  1585. /*  Sets h = e + f.  See my Robust Predicates paper for details.             */
  1586. /*                                                                           */
  1587. /*  If round-to-even is used (as with IEEE 754), maintains the strongly      */
  1588. /*  nonoverlapping property.  (That is, if e is strongly nonoverlapping, h   */
  1589. /*  will be also.)  Does NOT maintain the nonoverlapping or nonadjacent      */
  1590. /*  properties.                                                              */
  1591. /*                                                                           */
  1592. /*****************************************************************************/
  1593. #ifdef ANSI_DECLARATORS
  1594. int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
  1595. #else /* not ANSI_DECLARATORS */
  1596. int fast_expansion_sum_zeroelim(elen, e, flen, f, h)  /* h cannot be e or f. */
  1597. int elen;
  1598. REAL *e;
  1599. int flen;
  1600. REAL *f;
  1601. REAL *h;
  1602. #endif /* not ANSI_DECLARATORS */
  1603. {
  1604.   REAL Q;
  1605.   INEXACT REAL Qnew;
  1606.   INEXACT REAL hh;
  1607.   INEXACT REAL bvirt;
  1608.   REAL avirt, bround, around;
  1609.   int eindex, findex, hindex;
  1610.   REAL enow, fnow;
  1611.   enow = e[0];
  1612.   fnow = f[0];
  1613.   eindex = findex = 0;
  1614.   if ((fnow > enow) == (fnow > -enow)) {
  1615.     Q = enow;
  1616.     enow = e[++eindex];
  1617.   } else {
  1618.     Q = fnow;
  1619.     fnow = f[++findex];
  1620.   }
  1621.   hindex = 0;
  1622.   if ((eindex < elen) && (findex < flen)) {
  1623.     if ((fnow > enow) == (fnow > -enow)) {
  1624.       Fast_Two_Sum(enow, Q, Qnew, hh);
  1625.       enow = e[++eindex];
  1626.     } else {
  1627.       Fast_Two_Sum(fnow, Q, Qnew, hh);
  1628.       fnow = f[++findex];
  1629.     }
  1630.     Q = Qnew;
  1631.     if (hh != 0.0) {
  1632.       h[hindex++] = hh;
  1633.     }
  1634.     while ((eindex < elen) && (findex < flen)) {
  1635.       if ((fnow > enow) == (fnow > -enow)) {
  1636.         Two_Sum(Q, enow, Qnew, hh);
  1637.         enow = e[++eindex];
  1638.       } else {
  1639.         Two_Sum(Q, fnow, Qnew, hh);
  1640.         fnow = f[++findex];
  1641.       }
  1642.       Q = Qnew;
  1643.       if (hh != 0.0) {
  1644.         h[hindex++] = hh;
  1645.       }
  1646.     }
  1647.   }
  1648.   while (eindex < elen) {
  1649.     Two_Sum(Q, enow, Qnew, hh);
  1650.     enow = e[++eindex];
  1651.     Q = Qnew;
  1652.     if (hh != 0.0) {
  1653.       h[hindex++] = hh;
  1654.     }
  1655.   }
  1656.   while (findex < flen) {
  1657.     Two_Sum(Q, fnow, Qnew, hh);
  1658.     fnow = f[++findex];
  1659.     Q = Qnew;
  1660.     if (hh != 0.0) {
  1661.       h[hindex++] = hh;
  1662.     }
  1663.   }
  1664.   if ((Q != 0.0) || (hindex == 0)) {
  1665.     h[hindex++] = Q;
  1666.   }
  1667.   return hindex;
  1668. }
  1669. /*****************************************************************************/
  1670. /*                                                                           */
  1671. /*  scale_expansion_zeroelim()   Multiply an expansion by a scalar,          */
  1672. /*                               eliminating zero components from the        */
  1673. /*                               output expansion.                           */
  1674. /*                                                                           */
  1675. /*  Sets h = be.  See my Robust Predicates paper for details.                */
  1676. /*                                                                           */
  1677. /*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
  1678. /*  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent    */
  1679. /*  properties as well.  (That is, if e has one of these properties, so      */
  1680. /*  will h.)                                                                 */
  1681. /*                                                                           */
  1682. /*****************************************************************************/
  1683. #ifdef ANSI_DECLARATORS
  1684. int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h)
  1685. #else /* not ANSI_DECLARATORS */
  1686. int scale_expansion_zeroelim(elen, e, b, h)   /* e and h cannot be the same. */
  1687. int elen;
  1688. REAL *e;
  1689. REAL b;
  1690. REAL *h;
  1691. #endif /* not ANSI_DECLARATORS */
  1692. {
  1693.   INEXACT REAL Q, sum;
  1694.   REAL hh;
  1695.   INEXACT REAL product1;
  1696.   REAL product0;
  1697.   int eindex, hindex;
  1698.   REAL enow;
  1699.   INEXACT REAL bvirt;
  1700.   REAL avirt, bround, around;
  1701.   INEXACT REAL c;
  1702.   INEXACT REAL abig;
  1703.   REAL ahi, alo, bhi, blo;
  1704.   REAL err1, err2, err3;
  1705.   Split(b, bhi, blo);
  1706.   Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
  1707.   hindex = 0;
  1708.   if (hh != 0) {
  1709.     h[hindex++] = hh;
  1710.   }
  1711.   for (eindex = 1; eindex < elen; eindex++) {
  1712.     enow = e[eindex];
  1713.     Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
  1714.     Two_Sum(Q, product0, sum, hh);
  1715.     if (hh != 0) {
  1716.       h[hindex++] = hh;
  1717.     }
  1718.     Fast_Two_Sum(product1, sum, Q, hh);
  1719.     if (hh != 0) {
  1720.       h[hindex++] = hh;
  1721.     }
  1722.   }
  1723.   if ((Q != 0.0) || (hindex == 0)) {
  1724.     h[hindex++] = Q;
  1725.   }
  1726.   return hindex;
  1727. }
  1728. /*****************************************************************************/
  1729. /*                                                                           */
  1730. /*  estimate()   Produce a one-word estimate of an expansion's value.        */
  1731. /*                                                                           */
  1732. /*  See my Robust Predicates paper for details.                              */
  1733. /*                                                                           */
  1734. /*****************************************************************************/
  1735. #ifdef ANSI_DECLARATORS
  1736. REAL estimate(int elen, REAL *e)
  1737. #else /* not ANSI_DECLARATORS */
  1738. REAL estimate(elen, e)
  1739. int elen;
  1740. REAL *e;
  1741. #endif /* not ANSI_DECLARATORS */
  1742. {
  1743.   REAL Q;
  1744.   int eindex;
  1745.   Q = e[0];
  1746.   for (eindex = 1; eindex < elen; eindex++) {
  1747.     Q += e[eindex];
  1748.   }
  1749.   return Q;
  1750. }
  1751. /*****************************************************************************/
  1752. /*                                                                           */
  1753. /*  counterclockwise()   Return a positive value if the points pa, pb, and   */
  1754. /*                       pc occur in counterclockwise order; a negative      */
  1755. /*                       value if they occur in clockwise order; and zero    */
  1756. /*                       if they are collinear.  The result is also a rough  */
  1757. /*                       approximation of twice the signed area of the       */
  1758. /*                       triangle defined by the three points.               */
  1759. /*                                                                           */
  1760. /*  Uses exact arithmetic if necessary to ensure a correct answer.  The      */
  1761. /*  result returned is the determinant of a matrix.  This determinant is     */
  1762. /*  computed adaptively, in the sense that exact arithmetic is used only to  */
  1763. /*  the degree it is needed to ensure that the returned value has the        */
  1764. /*  correct sign.  Hence, this function is usually quite fast, but will run  */
  1765. /*  more slowly when the input points are collinear or nearly so.            */
  1766. /*                                                                           */
  1767. /*  See my Robust Predicates paper for details.                              */
  1768. /*                                                                           */
  1769. /*****************************************************************************/
  1770. #ifdef ANSI_DECLARATORS
  1771. REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum)
  1772. #else /* not ANSI_DECLARATORS */
  1773. REAL counterclockwiseadapt(pa, pb, pc, detsum)
  1774. vertex pa;
  1775. vertex pb;
  1776. vertex pc;
  1777. REAL detsum;
  1778. #endif /* not ANSI_DECLARATORS */
  1779. {
  1780.   INEXACT REAL acx, acy, bcx, bcy;
  1781.   REAL acxtail, acytail, bcxtail, bcytail;
  1782.   INEXACT REAL detleft, detright;
  1783.   REAL detlefttail, detrighttail;
  1784.   REAL det, errbound;
  1785.   REAL B[4], C1[8], C2[12], D[16];
  1786.   INEXACT REAL B3;
  1787.   int C1length, C2length, Dlength;
  1788.   REAL u[4];
  1789.   INEXACT REAL u3;
  1790.   INEXACT REAL s1, t1;
  1791.   REAL s0, t0;
  1792.   INEXACT REAL bvirt;
  1793.   REAL avirt, bround, around;
  1794.   INEXACT REAL c;
  1795.   INEXACT REAL abig;
  1796.   REAL ahi, alo, bhi, blo;
  1797.   REAL err1, err2, err3;
  1798.   INEXACT REAL _i, _j;
  1799.   REAL _0;
  1800.   acx = (REAL) (pa[0] - pc[0]);
  1801.   bcx = (REAL) (pb[0] - pc[0]);
  1802.   acy = (REAL) (pa[1] - pc[1]);
  1803.   bcy = (REAL) (pb[1] - pc[1]);
  1804.   Two_Product(acx, bcy, detleft, detlefttail);
  1805.   Two_Product(acy, bcx, detright, detrighttail);
  1806.   Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
  1807.                B3, B[2], B[1], B[0]);
  1808.   B[3] = B3;
  1809.   det = estimate(4, B);
  1810.   errbound = ccwerrboundB * detsum;
  1811.   if ((det >= errbound) || (-det >= errbound)) {
  1812.     return det;
  1813.   }
  1814.   Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
  1815.   Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
  1816.   Two_Diff_Tail(pa[1], pc[1], acy, acytail);
  1817.   Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
  1818.   if ((acxtail == 0.0) && (acytail == 0.0)
  1819.       && (bcxtail == 0.0) && (bcytail == 0.0)) {
  1820.     return det;
  1821.   }
  1822.   errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
  1823.   det += (acx * bcytail + bcy * acxtail)
  1824.        - (acy * bcxtail + bcx * acytail);
  1825.   if ((det >= errbound) || (-det >= errbound)) {
  1826.     return det;
  1827.   }
  1828.   Two_Product(acxtail, bcy, s1, s0);
  1829.   Two_Product(acytail, bcx, t1, t0);
  1830.   Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
  1831.   u[3] = u3;
  1832.   C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
  1833.   Two_Product(acx, bcytail, s1, s0);
  1834.   Two_Product(acy, bcxtail, t1, t0);
  1835.   Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
  1836.   u[3] = u3;
  1837.   C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
  1838.   Two_Product(acxtail, bcytail, s1, s0);
  1839.   Two_Product(acytail, bcxtail, t1, t0);
  1840.   Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
  1841.   u[3] = u3;
  1842.   Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
  1843.   return(D[Dlength - 1]);
  1844. }
  1845. #ifdef ANSI_DECLARATORS
  1846. REAL counterclockwise(struct mesh *m, struct behavior *b,
  1847.                       vertex pa, vertex pb, vertex pc)
  1848. #else /* not ANSI_DECLARATORS */
  1849. REAL counterclockwise(m, b, pa, pb, pc)
  1850. struct mesh *m;
  1851. struct behavior *b;
  1852. vertex pa;
  1853. vertex pb;
  1854. vertex pc;
  1855. #endif /* not ANSI_DECLARATORS */
  1856. {
  1857.   REAL detleft, detright, det;
  1858.   REAL detsum, errbound;
  1859.   m->counterclockcount++;
  1860.   detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
  1861.   detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
  1862.   det = detleft - detright;
  1863.   if (b->noexact) {
  1864.     return det;
  1865.   }
  1866.   if (detleft > 0.0) {
  1867.     if (detright <= 0.0) {
  1868.       return det;
  1869.     } else {
  1870.       detsum = detleft + detright;
  1871.     }
  1872.   } else if (detleft < 0.0) {
  1873.     if (detright >= 0.0) {
  1874.       return det;
  1875.     } else {
  1876.       detsum = -detleft - detright;
  1877.     }
  1878.   } else {
  1879.     return det;
  1880.   }
  1881.   errbound = ccwerrboundA * detsum;
  1882.   if ((det >= errbound) || (-det >= errbound)) {
  1883.     return det;
  1884.   }
  1885.   return counterclockwiseadapt(pa, pb, pc, detsum);
  1886. }
  1887. /*****************************************************************************/
  1888. /*                                                                           */
  1889. /*  incircle()   Return a positive value if the point pd lies inside the     */
  1890. /*               circle passing through pa, pb, and pc; a negative value if  */
  1891. /*               it lies outside; and zero if the four points are cocircular.*/
  1892. /*               The points pa, pb, and pc must be in counterclockwise       */
  1893. /*               order, or the sign of the result will be reversed.          */
  1894. /*                                                                           */
  1895. /*  Uses exact arithmetic if necessary to ensure a correct answer.  The      */
  1896. /*  result returned is the determinant of a matrix.  This determinant is     */
  1897. /*  computed adaptively, in the sense that exact arithmetic is used only to  */
  1898. /*  the degree it is needed to ensure that the returned value has the        */
  1899. /*  correct sign.  Hence, this function is usually quite fast, but will run  */
  1900. /*  more slowly when the input points are cocircular or nearly so.           */
  1901. /*                                                                           */
  1902. /*  See my Robust Predicates paper for details.                              */
  1903. /*                                                                           */
  1904. /*****************************************************************************/
  1905. #ifdef ANSI_DECLARATORS
  1906. REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent)
  1907. #else /* not ANSI_DECLARATORS */
  1908. REAL incircleadapt(pa, pb, pc, pd, permanent)
  1909. vertex pa;
  1910. vertex pb;
  1911. vertex pc;
  1912. vertex pd;
  1913. REAL permanent;
  1914. #endif /* not ANSI_DECLARATORS */
  1915. {
  1916.   INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
  1917.   REAL det, errbound;
  1918.   INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
  1919.   REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
  1920.   REAL bc[4], ca[4], ab[4];
  1921.   INEXACT REAL bc3, ca3, ab3;
  1922.   REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
  1923.   int axbclen, axxbclen, aybclen, ayybclen, alen;
  1924.   REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
  1925.   int bxcalen, bxxcalen, bycalen, byycalen, blen;
  1926.   REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
  1927.   int cxablen, cxxablen, cyablen, cyyablen, clen;
  1928.   REAL abdet[64];
  1929.   int ablen;
  1930.   REAL fin1[1152], fin2[1152];
  1931.   REAL *finnow, *finother, *finswap;
  1932.   int finlength;
  1933.   REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
  1934.   INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
  1935.   REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
  1936.   REAL aa[4], bb[4], cc[4];
  1937.   INEXACT REAL aa3, bb3, cc3;
  1938.   INEXACT REAL ti1, tj1;
  1939.   REAL ti0, tj0;
  1940.   REAL u[4], v[4];
  1941.   INEXACT REAL u3, v3;
  1942.   REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
  1943.   REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
  1944.   int temp8len, temp16alen, temp16blen, temp16clen;
  1945.   int temp32alen, temp32blen, temp48len, temp64len;
  1946.   REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
  1947.   int axtbblen, axtcclen, aytbblen, aytcclen;
  1948.   REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
  1949.   int bxtaalen, bxtcclen, bytaalen, bytcclen;
  1950.   REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
  1951.   int cxtaalen, cxtbblen, cytaalen, cytbblen;
  1952.   REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
  1953.   int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
  1954.   REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
  1955.   int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
  1956.   REAL axtbctt[8], aytbctt[8], bxtcatt[8];
  1957.   REAL bytcatt[8], cxtabtt[8], cytabtt[8];
  1958.   int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
  1959.   REAL abt[8], bct[8], cat[8];
  1960.   int abtlen, bctlen, catlen;
  1961.   REAL abtt[4], bctt[4], catt[4];
  1962.   int abttlen, bcttlen, cattlen;
  1963.   INEXACT REAL abtt3, bctt3, catt3;
  1964.   REAL negate;
  1965.   INEXACT REAL bvirt;
  1966.   REAL avirt, bround, around;
  1967.   INEXACT REAL c;
  1968.   INEXACT REAL abig;
  1969.   REAL ahi, alo, bhi, blo;
  1970.   REAL err1, err2, err3;
  1971.   INEXACT REAL _i, _j;
  1972.   REAL _0;
  1973.   adx = (REAL) (pa[0] - pd[0]);
  1974.   bdx = (REAL) (pb[0] - pd[0]);
  1975.   cdx = (REAL) (pc[0] - pd[0]);
  1976.   ady = (REAL) (pa[1] - pd[1]);
  1977.   bdy = (REAL) (pb[1] - pd[1]);
  1978.   cdy = (REAL) (pc[1] - pd[1]);
  1979.   Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
  1980.   Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
  1981.   Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
  1982.   bc[3] = bc3;
  1983.   axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
  1984.   axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
  1985.   aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
  1986.   ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
  1987.   alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
  1988.   Two_Product(cdx, ady, cdxady1, cdxady0);
  1989.   Two_Product(adx, cdy, adxcdy1, adxcdy0);
  1990.   Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
  1991.   ca[3] = ca3;
  1992.   bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
  1993.   bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
  1994.   bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
  1995.   byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
  1996.   blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
  1997.   Two_Product(adx, bdy, adxbdy1, adxbdy0);
  1998.   Two_Product(bdx, ady, bdxady1, bdxady0);
  1999.   Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
  2000.   ab[3] = ab3;
  2001.   cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
  2002.   cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
  2003.   cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
  2004.   cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
  2005.   clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
  2006.   ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
  2007.   finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
  2008.   det = estimate(finlength, fin1);
  2009.   errbound = iccerrboundB * permanent;
  2010.   if ((det >= errbound) || (-det >= errbound)) {
  2011.     return det;
  2012.   }
  2013.   Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
  2014.   Two_Diff_Tail(pa[1], pd[1], ady, adytail);
  2015.   Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
  2016.   Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
  2017.   Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
  2018.   Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
  2019.   if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
  2020.       && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
  2021.     return det;
  2022.   }
  2023.   errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
  2024.   det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
  2025.                                      - (bdy * cdxtail + cdx * bdytail))
  2026.           + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
  2027.        + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
  2028.                                      - (cdy * adxtail + adx * cdytail))
  2029.           + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
  2030.        + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
  2031.                                      - (ady * bdxtail + bdx * adytail))
  2032.           + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
  2033.   if ((det >= errbound) || (-det >= errbound)) {
  2034.     return det;
  2035.   }
  2036.   finnow = fin1;
  2037.   finother = fin2;
  2038.   if ((bdxtail != 0.0) || (bdytail != 0.0)
  2039.       || (cdxtail != 0.0) || (cdytail != 0.0)) {
  2040.     Square(adx, adxadx1, adxadx0);
  2041.     Square(ady, adyady1, adyady0);
  2042.     Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
  2043.     aa[3] = aa3;
  2044.   }
  2045.   if ((cdxtail != 0.0) || (cdytail != 0.0)
  2046.       || (adxtail != 0.0) || (adytail != 0.0)) {
  2047.     Square(bdx, bdxbdx1, bdxbdx0);
  2048.     Square(bdy, bdybdy1, bdybdy0);
  2049.     Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
  2050.     bb[3] = bb3;
  2051.   }
  2052.   if ((adxtail != 0.0) || (adytail != 0.0)
  2053.       || (bdxtail != 0.0) || (bdytail != 0.0)) {
  2054.     Square(cdx, cdxcdx1, cdxcdx0);
  2055.     Square(cdy, cdycdy1, cdycdy0);
  2056.     Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
  2057.     cc[3] = cc3;
  2058.   }
  2059.   if (adxtail != 0.0) {
  2060.     axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
  2061.     temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
  2062.                                           temp16a);
  2063.     axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
  2064.     temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
  2065.     axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
  2066.     temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
  2067.     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2068.                                             temp16blen, temp16b, temp32a);
  2069.     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
  2070.                                             temp32alen, temp32a, temp48);
  2071.     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
  2072.                                             temp48, finother);
  2073.     finswap = finnow; finnow = finother; finother = finswap;
  2074.   }
  2075.   if (adytail != 0.0) {
  2076.     aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
  2077.     temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
  2078.                                           temp16a);
  2079.     aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
  2080.     temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
  2081.     aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
  2082.     temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
  2083.     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2084.                                             temp16blen, temp16b, temp32a);
  2085.     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
  2086.                                             temp32alen, temp32a, temp48);
  2087.     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
  2088.                                             temp48, finother);
  2089.     finswap = finnow; finnow = finother; finother = finswap;
  2090.   }
  2091.   if (bdxtail != 0.0) {
  2092.     bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
  2093.     temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
  2094.                                           temp16a);
  2095.     bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
  2096.     temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
  2097.     bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
  2098.     temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
  2099.     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2100.                                             temp16blen, temp16b, temp32a);
  2101.     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
  2102.                                             temp32alen, temp32a, temp48);
  2103.     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
  2104.                                             temp48, finother);
  2105.     finswap = finnow; finnow = finother; finother = finswap;
  2106.   }
  2107.   if (bdytail != 0.0) {
  2108.     bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
  2109.     temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
  2110.                                           temp16a);
  2111.     bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
  2112.     temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
  2113.     bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
  2114.     temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
  2115.     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2116.                                             temp16blen, temp16b, temp32a);
  2117.     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
  2118.                                             temp32alen, temp32a, temp48);
  2119.     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
  2120.                                             temp48, finother);
  2121.     finswap = finnow; finnow = finother; finother = finswap;
  2122.   }
  2123.   if (cdxtail != 0.0) {
  2124.     cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
  2125.     temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
  2126.                                           temp16a);
  2127.     cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
  2128.     temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
  2129.     cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
  2130.     temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
  2131.     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2132.                                             temp16blen, temp16b, temp32a);
  2133.     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
  2134.                                             temp32alen, temp32a, temp48);
  2135.     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
  2136.                                             temp48, finother);
  2137.     finswap = finnow; finnow = finother; finother = finswap;
  2138.   }
  2139.   if (cdytail != 0.0) {
  2140.     cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
  2141.     temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
  2142.                                           temp16a);
  2143.     cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
  2144.     temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
  2145.     cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
  2146.     temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
  2147.     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2148.                                             temp16blen, temp16b, temp32a);
  2149.     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
  2150.                                             temp32alen, temp32a, temp48);
  2151.     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
  2152.                                             temp48, finother);
  2153.     finswap = finnow; finnow = finother; finother = finswap;
  2154.   }
  2155.   if ((adxtail != 0.0) || (adytail != 0.0)) {
  2156.     if ((bdxtail != 0.0) || (bdytail != 0.0)
  2157.         || (cdxtail != 0.0) || (cdytail != 0.0)) {
  2158.       Two_Product(bdxtail, cdy, ti1, ti0);
  2159.       Two_Product(bdx, cdytail, tj1, tj0);
  2160.       Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
  2161.       u[3] = u3;
  2162.       negate = -bdy;
  2163.       Two_Product(cdxtail, negate, ti1, ti0);
  2164.       negate = -bdytail;
  2165.       Two_Product(cdx, negate, tj1, tj0);
  2166.       Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
  2167.       v[3] = v3;
  2168.       bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
  2169.       Two_Product(bdxtail, cdytail, ti1, ti0);
  2170.       Two_Product(cdxtail, bdytail, tj1, tj0);
  2171.       Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
  2172.       bctt[3] = bctt3;
  2173.       bcttlen = 4;
  2174.     } else {
  2175.       bct[0] = 0.0;
  2176.       bctlen = 1;
  2177.       bctt[0] = 0.0;
  2178.       bcttlen = 1;
  2179.     }
  2180.     if (adxtail != 0.0) {
  2181.       temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
  2182.       axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
  2183.       temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
  2184.                                             temp32a);
  2185.       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2186.                                               temp32alen, temp32a, temp48);
  2187.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
  2188.                                               temp48, finother);
  2189.       finswap = finnow; finnow = finother; finother = finswap;
  2190.       if (bdytail != 0.0) {
  2191.         temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
  2192.         temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
  2193.                                               temp16a);
  2194.         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
  2195.                                                 temp16a, finother);
  2196.         finswap = finnow; finnow = finother; finother = finswap;
  2197.       }
  2198.       if (cdytail != 0.0) {
  2199.         temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
  2200.         temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
  2201.                                               temp16a);
  2202.         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
  2203.                                                 temp16a, finother);
  2204.         finswap = finnow; finnow = finother; finother = finswap;
  2205.       }
  2206.       temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
  2207.                                             temp32a);
  2208.       axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
  2209.       temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
  2210.                                             temp16a);
  2211.       temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
  2212.                                             temp16b);
  2213.       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2214.                                               temp16blen, temp16b, temp32b);
  2215.       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
  2216.                                               temp32blen, temp32b, temp64);
  2217.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
  2218.                                               temp64, finother);
  2219.       finswap = finnow; finnow = finother; finother = finswap;
  2220.     }
  2221.     if (adytail != 0.0) {
  2222.       temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
  2223.       aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
  2224.       temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
  2225.                                             temp32a);
  2226.       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2227.                                               temp32alen, temp32a, temp48);
  2228.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
  2229.                                               temp48, finother);
  2230.       finswap = finnow; finnow = finother; finother = finswap;
  2231.       temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
  2232.                                             temp32a);
  2233.       aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
  2234.       temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
  2235.                                             temp16a);
  2236.       temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
  2237.                                             temp16b);
  2238.       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2239.                                               temp16blen, temp16b, temp32b);
  2240.       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
  2241.                                               temp32blen, temp32b, temp64);
  2242.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
  2243.                                               temp64, finother);
  2244.       finswap = finnow; finnow = finother; finother = finswap;
  2245.     }
  2246.   }
  2247.   if ((bdxtail != 0.0) || (bdytail != 0.0)) {
  2248.     if ((cdxtail != 0.0) || (cdytail != 0.0)
  2249.         || (adxtail != 0.0) || (adytail != 0.0)) {
  2250.       Two_Product(cdxtail, ady, ti1, ti0);
  2251.       Two_Product(cdx, adytail, tj1, tj0);
  2252.       Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
  2253.       u[3] = u3;
  2254.       negate = -cdy;
  2255.       Two_Product(adxtail, negate, ti1, ti0);
  2256.       negate = -cdytail;
  2257.       Two_Product(adx, negate, tj1, tj0);
  2258.       Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
  2259.       v[3] = v3;
  2260.       catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
  2261.       Two_Product(cdxtail, adytail, ti1, ti0);
  2262.       Two_Product(adxtail, cdytail, tj1, tj0);
  2263.       Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
  2264.       catt[3] = catt3;
  2265.       cattlen = 4;
  2266.     } else {
  2267.       cat[0] = 0.0;
  2268.       catlen = 1;
  2269.       catt[0] = 0.0;
  2270.       cattlen = 1;
  2271.     }
  2272.     if (bdxtail != 0.0) {
  2273.       temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
  2274.       bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
  2275.       temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
  2276.                                             temp32a);
  2277.       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2278.                                               temp32alen, temp32a, temp48);
  2279.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
  2280.                                               temp48, finother);
  2281.       finswap = finnow; finnow = finother; finother = finswap;
  2282.       if (cdytail != 0.0) {
  2283.         temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
  2284.         temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
  2285.                                               temp16a);
  2286.         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
  2287.                                                 temp16a, finother);
  2288.         finswap = finnow; finnow = finother; finother = finswap;
  2289.       }
  2290.       if (adytail != 0.0) {
  2291.         temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
  2292.         temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
  2293.                                               temp16a);
  2294.         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
  2295.                                                 temp16a, finother);
  2296.         finswap = finnow; finnow = finother; finother = finswap;
  2297.       }
  2298.       temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
  2299.                                             temp32a);
  2300.       bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
  2301.       temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
  2302.                                             temp16a);
  2303.       temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
  2304.                                             temp16b);
  2305.       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2306.                                               temp16blen, temp16b, temp32b);
  2307.       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
  2308.                                               temp32blen, temp32b, temp64);
  2309.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
  2310.                                               temp64, finother);
  2311.       finswap = finnow; finnow = finother; finother = finswap;
  2312.     }
  2313.     if (bdytail != 0.0) {
  2314.       temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
  2315.       bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
  2316.       temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
  2317.                                             temp32a);
  2318.       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2319.                                               temp32alen, temp32a, temp48);
  2320.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
  2321.                                               temp48, finother);
  2322.       finswap = finnow; finnow = finother; finother = finswap;
  2323.       temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
  2324.                                             temp32a);
  2325.       bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
  2326.       temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
  2327.                                             temp16a);
  2328.       temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
  2329.                                             temp16b);
  2330.       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2331.                                               temp16blen, temp16b, temp32b);
  2332.       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
  2333.                                               temp32blen, temp32b, temp64);
  2334.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
  2335.                                               temp64, finother);
  2336.       finswap = finnow; finnow = finother; finother = finswap;
  2337.     }
  2338.   }
  2339.   if ((cdxtail != 0.0) || (cdytail != 0.0)) {
  2340.     if ((adxtail != 0.0) || (adytail != 0.0)
  2341.         || (bdxtail != 0.0) || (bdytail != 0.0)) {
  2342.       Two_Product(adxtail, bdy, ti1, ti0);
  2343.       Two_Product(adx, bdytail, tj1, tj0);
  2344.       Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
  2345.       u[3] = u3;
  2346.       negate = -ady;
  2347.       Two_Product(bdxtail, negate, ti1, ti0);
  2348.       negate = -adytail;
  2349.       Two_Product(bdx, negate, tj1, tj0);
  2350.       Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
  2351.       v[3] = v3;
  2352.       abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
  2353.       Two_Product(adxtail, bdytail, ti1, ti0);
  2354.       Two_Product(bdxtail, adytail, tj1, tj0);
  2355.       Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
  2356.       abtt[3] = abtt3;
  2357.       abttlen = 4;
  2358.     } else {
  2359.       abt[0] = 0.0;
  2360.       abtlen = 1;
  2361.       abtt[0] = 0.0;
  2362.       abttlen = 1;
  2363.     }
  2364.     if (cdxtail != 0.0) {
  2365.       temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
  2366.       cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
  2367.       temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
  2368.                                             temp32a);
  2369.       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2370.                                               temp32alen, temp32a, temp48);
  2371.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
  2372.                                               temp48, finother);
  2373.       finswap = finnow; finnow = finother; finother = finswap;
  2374.       if (adytail != 0.0) {
  2375.         temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
  2376.         temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
  2377.                                               temp16a);
  2378.         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
  2379.                                                 temp16a, finother);
  2380.         finswap = finnow; finnow = finother; finother = finswap;
  2381.       }
  2382.       if (bdytail != 0.0) {
  2383.         temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
  2384.         temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
  2385.                                               temp16a);
  2386.         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
  2387.                                                 temp16a, finother);
  2388.         finswap = finnow; finnow = finother; finother = finswap;
  2389.       }
  2390.       temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
  2391.                                             temp32a);
  2392.       cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
  2393.       temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
  2394.                                             temp16a);
  2395.       temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
  2396.                                             temp16b);
  2397.       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2398.                                               temp16blen, temp16b, temp32b);
  2399.       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
  2400.                                               temp32blen, temp32b, temp64);
  2401.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
  2402.                                               temp64, finother);
  2403.       finswap = finnow; finnow = finother; finother = finswap;
  2404.     }
  2405.     if (cdytail != 0.0) {
  2406.       temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
  2407.       cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
  2408.       temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
  2409.                                             temp32a);
  2410.       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2411.                                               temp32alen, temp32a, temp48);
  2412.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
  2413.                                               temp48, finother);
  2414.       finswap = finnow; finnow = finother; finother = finswap;
  2415.       temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
  2416.                                             temp32a);
  2417.       cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
  2418.       temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
  2419.                                             temp16a);
  2420.       temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
  2421.                                             temp16b);
  2422.       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
  2423.                                               temp16blen, temp16b, temp32b);
  2424.       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
  2425.                                               temp32blen, temp32b, temp64);
  2426.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
  2427.                                               temp64, finother);
  2428.       finswap = finnow; finnow = finother; finother = finswap;
  2429.     }
  2430.   }
  2431.   return finnow[finlength - 1];
  2432. }
  2433. #ifdef ANSI_DECLARATORS
  2434. REAL incircle(struct mesh *m, struct behavior *b,
  2435.               vertex pa, vertex pb, vertex pc, vertex pd)
  2436. #else /* not ANSI_DECLARATORS */
  2437. REAL incircle(m, b, pa, pb, pc, pd)
  2438. struct mesh *m;
  2439. struct behavior *b;
  2440. vertex pa;
  2441. vertex pb;
  2442. vertex pc;
  2443. vertex pd;
  2444. #endif /* not ANSI_DECLARATORS */
  2445. {
  2446.   REAL adx, bdx, cdx, ady, bdy, cdy;
  2447.   REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
  2448.   REAL alift, blift, clift;
  2449.   REAL det;
  2450.   REAL permanent, errbound;
  2451.   m->incirclecount++;
  2452.   adx = pa[0] - pd[0];
  2453.   bdx = pb[0] - pd[0];
  2454.   cdx = pc[0] - pd[0];
  2455.   ady = pa[1] - pd[1];
  2456.   bdy = pb[1] - pd[1];
  2457.   cdy = pc[1] - pd[1];
  2458.   bdxcdy = bdx * cdy;
  2459.   cdxbdy = cdx * bdy;
  2460.   alift = adx * adx + ady * ady;
  2461.   cdxady = cdx * ady;
  2462.   adxcdy = adx * cdy;
  2463.   blift = bdx * bdx + bdy * bdy;
  2464.   adxbdy = adx * bdy;
  2465.   bdxady = bdx * ady;
  2466.   clift = cdx * cdx + cdy * cdy;
  2467.   det = alift * (bdxcdy - cdxbdy)
  2468.       + blift * (cdxady - adxcdy)
  2469.       + clift * (adxbdy - bdxady);
  2470.   if (b->noexact) {
  2471.     return det;
  2472.   }
  2473.   permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
  2474.             + (Absolute(cdxady) + Absolute(adxcdy)) * blift
  2475.             + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
  2476.   errbound = iccerrboundA * permanent;
  2477.   if ((det > errbound) || (-det > errbound)) {
  2478.     return det;
  2479.   }
  2480.   return incircleadapt(pa, pb, pc, pd, permanent);
  2481. }
  2482. /*****************************************************************************/
  2483. /*                                                                           */
  2484. /*  orient3d()   Return a positive value if the point pd lies below the      */
  2485. /*               plane passing through pa, pb, and pc; "below" is defined so */
  2486. /*               that pa, pb, and pc appear in counterclockwise order when   */
  2487. /*               viewed from above the plane.  Returns a negative value if   */
  2488. /*               pd lies above the plane.  Returns zero if the points are    */
  2489. /*               coplanar.  The result is also a rough approximation of six  */
  2490. /*               times the signed volume of the tetrahedron defined by the   */
  2491. /*               four points.                                                */
  2492. /*                                                                           */
  2493. /*  Uses exact arithmetic if necessary to ensure a correct answer.  The      */
  2494. /*  result returned is the determinant of a matrix.  This determinant is     */
  2495. /*  computed adaptively, in the sense that exact arithmetic is used only to  */
  2496. /*  the degree it is needed to ensure that the returned value has the        */
  2497. /*  correct sign.  Hence, this function is usually quite fast, but will run  */
  2498. /*  more slowly when the input points are coplanar or nearly so.             */
  2499. /*                                                                           */
  2500. /*  See my Robust Predicates paper for details.                              */
  2501. /*                                                                           */
  2502. /*****************************************************************************/
  2503. #ifdef ANSI_DECLARATORS
  2504. REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd,
  2505.                    REAL aheight, REAL bheight, REAL cheight, REAL dheight,
  2506.                    REAL permanent)
  2507. #else /* not ANSI_DECLARATORS */
  2508. REAL orient3dadapt(pa, pb, pc, pd,
  2509.                    aheight, bheight, cheight, dheight, permanent)
  2510. vertex pa;
  2511. vertex pb;
  2512. vertex pc;
  2513. vertex pd;
  2514. REAL aheight;
  2515. REAL bheight;
  2516. REAL cheight;
  2517. REAL dheight;
  2518. REAL permanent;
  2519. #endif /* not ANSI_DECLARATORS */
  2520. {
  2521.   INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
  2522.   REAL det, errbound;
  2523.   INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
  2524.   REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
  2525.   REAL bc[4], ca[4], ab[4];
  2526.   INEXACT REAL bc3, ca3, ab3;
  2527.   REAL adet[8], bdet[8], cdet[8];
  2528.   int alen, blen, clen;
  2529.   REAL abdet[16];
  2530.   int ablen;
  2531.   REAL *finnow, *finother, *finswap;
  2532.   REAL fin1[192], fin2[192];
  2533.   int finlength;
  2534.   REAL adxtail, bdxtail, cdxtail;
  2535.   REAL adytail, bdytail, cdytail;
  2536.   REAL adheighttail, bdheighttail, cdheighttail;
  2537.   INEXACT REAL at_blarge, at_clarge;
  2538.   INEXACT REAL bt_clarge, bt_alarge;
  2539.   INEXACT REAL ct_alarge, ct_blarge;
  2540.   REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
  2541.   int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
  2542.   INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1;
  2543.   INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1;
  2544.   REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
  2545.   REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
  2546.   INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1;
  2547.   INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1;
  2548.   REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
  2549.   REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
  2550.   REAL bct[8], cat[8], abt[8];
  2551.   int bctlen, catlen, abtlen;
  2552.   INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
  2553.   INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1;
  2554.   REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
  2555.   REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
  2556.   REAL u[4], v[12], w[16];
  2557.   INEXACT REAL u3;
  2558.   int vlength, wlength;
  2559.   REAL negate;
  2560.   INEXACT REAL bvirt;
  2561.   REAL avirt, bround, around;
  2562.   INEXACT REAL c;
  2563.   INEXACT REAL abig;
  2564.   REAL ahi, alo, bhi, blo;
  2565.   REAL err1, err2, err3;
  2566.   INEXACT REAL _i, _j, _k;
  2567.   REAL _0;
  2568.   adx = (REAL) (pa[0] - pd[0]);
  2569.   bdx = (REAL) (pb[0] - pd[0]);
  2570.   cdx = (REAL) (pc[0] - pd[0]);
  2571.   ady = (REAL) (pa[1] - pd[1]);
  2572.   bdy = (REAL) (pb[1] - pd[1]);
  2573.   cdy = (REAL) (pc[1] - pd[1]);
  2574.   adheight = (REAL) (aheight - dheight);
  2575.   bdheight = (REAL) (bheight - dheight);
  2576.   cdheight = (REAL) (cheight - dheight);
  2577.   Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
  2578.   Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
  2579.   Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
  2580.   bc[3] = bc3;
  2581.   alen = scale_expansion_zeroelim(4, bc, adheight, adet);
  2582.   Two_Product(cdx, ady, cdxady1, cdxady0);
  2583.   Two_Product(adx, cdy, adxcdy1, adxcdy0);
  2584.   Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
  2585.   ca[3] = ca3;
  2586.   blen = scale_expansion_zeroelim(4, ca, bdheight, bdet);
  2587.   Two_Product(adx, bdy, adxbdy1, adxbdy0);
  2588.   Two_Product(bdx, ady, bdxady1, bdxady0);
  2589.   Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
  2590.   ab[3] = ab3;
  2591.   clen = scale_expansion_zeroelim(4, ab, cdheight, cdet);
  2592.   ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
  2593.   finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
  2594.   det = estimate(finlength, fin1);
  2595.   errbound = o3derrboundB * permanent;
  2596.   if ((det >= errbound) || (-det >= errbound)) {
  2597.     return det;
  2598.   }
  2599.   Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
  2600.   Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
  2601.   Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
  2602.   Two_Diff_Tail(pa[1], pd[1], ady, adytail);
  2603.   Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
  2604.   Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
  2605.   Two_Diff_Tail(aheight, dheight, adheight, adheighttail);
  2606.   Two_Diff_Tail(bheight, dheight, bdheight, bdheighttail);
  2607.   Two_Diff_Tail(cheight, dheight, cdheight, cdheighttail);
  2608.   if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
  2609.       (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) &&
  2610.       (adheighttail == 0.0) &&
  2611.       (bdheighttail == 0.0) &&
  2612.       (cdheighttail == 0.0)) {
  2613.     return det;
  2614.   }
  2615.   errbound = o3derrboundC * permanent + resulterrbound * Absolute(det);
  2616.   det += (adheight * ((bdx * cdytail + cdy * bdxtail) -
  2617.                       (bdy * cdxtail + cdx * bdytail)) +
  2618.           adheighttail * (bdx * cdy - bdy * cdx)) +
  2619.          (bdheight * ((cdx * adytail + ady * cdxtail) -
  2620.                       (cdy * adxtail + adx * cdytail)) +
  2621.           bdheighttail * (cdx * ady - cdy * adx)) +
  2622.          (cdheight * ((adx * bdytail + bdy * adxtail) -
  2623.                       (ady * bdxtail + bdx * adytail)) +
  2624.           cdheighttail * (adx * bdy - ady * bdx));
  2625.   if ((det >= errbound) || (-det >= errbound)) {
  2626.     return det;
  2627.   }
  2628.   finnow = fin1;
  2629.   finother = fin2;
  2630.   if (adxtail == 0.0) {
  2631.     if (adytail == 0.0) {
  2632.       at_b[0] = 0.0;
  2633.       at_blen = 1;
  2634.       at_c[0] = 0.0;
  2635.       at_clen = 1;
  2636.     } else {
  2637.       negate = -adytail;
  2638.       Two_Product(negate, bdx, at_blarge, at_b[0]);
  2639.       at_b[1] = at_blarge;
  2640.       at_blen = 2;
  2641.       Two_Product(adytail, cdx, at_clarge, at_c[0]);
  2642.       at_c[1] = at_clarge;
  2643.       at_clen = 2;
  2644.     }
  2645.   } else {
  2646.     if (adytail == 0.0) {
  2647.       Two_Product(adxtail, bdy, at_blarge, at_b[0]);
  2648.       at_b[1] = at_blarge;
  2649.       at_blen = 2;
  2650.       negate = -adxtail;
  2651.       Two_Product(negate, cdy, at_clarge, at_c[0]);
  2652.       at_c[1] = at_clarge;
  2653.       at_clen = 2;
  2654.     } else {
  2655.       Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0);
  2656.       Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0);
  2657.       Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
  2658.                    at_blarge, at_b[2], at_b[1], at_b[0]);
  2659.       at_b[3] = at_blarge;
  2660.       at_blen = 4;
  2661.       Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0);
  2662.       Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0);
  2663.       Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
  2664.                    at_clarge, at_c[2], at_c[1], at_c[0]);
  2665.       at_c[3] = at_clarge;
  2666.       at_clen = 4;
  2667.     }
  2668.   }
  2669.   if (bdxtail == 0.0) {
  2670.     if (bdytail == 0.0) {
  2671.       bt_c[0] = 0.0;
  2672.       bt_clen = 1;
  2673.       bt_a[0] = 0.0;
  2674.       bt_alen = 1;
  2675.     } else {
  2676.       negate = -bdytail;
  2677.       Two_Product(negate, cdx, bt_clarge, bt_c[0]);
  2678.       bt_c[1] = bt_clarge;
  2679.       bt_clen = 2;
  2680.       Two_Product(bdytail, adx, bt_alarge, bt_a[0]);
  2681.       bt_a[1] = bt_alarge;
  2682.       bt_alen = 2;
  2683.     }
  2684.   } else {
  2685.     if (bdytail == 0.0) {
  2686.       Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]);
  2687.       bt_c[1] = bt_clarge;
  2688.       bt_clen = 2;
  2689.       negate = -bdxtail;
  2690.       Two_Product(negate, ady, bt_alarge, bt_a[0]);
  2691.       bt_a[1] = bt_alarge;
  2692.       bt_alen = 2;
  2693.     } else {
  2694.       Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
  2695.       Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
  2696.       Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
  2697.                    bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
  2698.       bt_c[3] = bt_clarge;
  2699.       bt_clen = 4;
  2700.       Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0);
  2701.       Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0);
  2702.       Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
  2703.                   bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
  2704.       bt_a[3] = bt_alarge;
  2705.       bt_alen = 4;
  2706.     }
  2707.   }
  2708.   if (cdxtail == 0.0) {
  2709.     if (cdytail == 0.0) {
  2710.       ct_a[0] = 0.0;
  2711.       ct_alen = 1;
  2712.       ct_b[0] = 0.0;
  2713.       ct_blen = 1;
  2714.     } else {
  2715.       negate = -cdytail;
  2716.       Two_Product(negate, adx, ct_alarge, ct_a[0]);
  2717.       ct_a[1] = ct_alarge;
  2718.       ct_alen = 2;
  2719.       Two_Product(cdytail, bdx, ct_blarge, ct_b[0]);
  2720.       ct_b[1] = ct_blarge;
  2721.       ct_blen = 2;
  2722.     }
  2723.   } else {
  2724.     if (cdytail == 0.0) {
  2725.       Two_Product(cdxtail, ady, ct_alarge, ct_a[0]);
  2726.       ct_a[1] = ct_alarge;
  2727.       ct_alen = 2;
  2728.       negate = -cdxtail;
  2729.       Two_Product(negate, bdy, ct_blarge, ct_b[0]);
  2730.       ct_b[1] = ct_blarge;
  2731.       ct_blen = 2;
  2732.     } else {
  2733.       Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0);
  2734.       Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0);
  2735.       Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
  2736.                    ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
  2737.       ct_a[3] = ct_alarge;
  2738.       ct_alen = 4;
  2739.       Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
  2740.       Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
  2741.       Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
  2742.                    ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
  2743.       ct_b[3] = ct_blarge;
  2744.       ct_blen = 4;
  2745.     }
  2746.   }
  2747.   bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct);
  2748.   wlength = scale_expansion_zeroelim(bctlen, bct, adheight, w);
  2749.   finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
  2750.                                           finother);
  2751.   finswap = finnow; finnow = finother; finother = finswap;
  2752.   catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat);
  2753.   wlength = scale_expansion_zeroelim(catlen, cat, bdheight, w);
  2754.   finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
  2755.                                           finother);
  2756.   finswap = finnow; finnow = finother; finother = finswap;
  2757.   abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt);
  2758.   wlength = scale_expansion_zeroelim(abtlen, abt, cdheight, w);
  2759.   finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
  2760.                                           finother);
  2761.   finswap = finnow; finnow = finother; finother = finswap;
  2762.   if (adheighttail != 0.0) {
  2763.     vlength = scale_expansion_zeroelim(4, bc, adheighttail, v);
  2764.     finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
  2765.                                             finother);
  2766.     finswap = finnow; finnow = finother; finother = finswap;
  2767.   }
  2768.   if (bdheighttail != 0.0) {
  2769.     vlength = scale_expansion_zeroelim(4, ca, bdheighttail, v);
  2770.     finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
  2771.                                             finother);
  2772.     finswap = finnow; finnow = finother; finother = finswap;
  2773.   }
  2774.   if (cdheighttail != 0.0) {
  2775.     vlength = scale_expansion_zeroelim(4, ab, cdheighttail, v);
  2776.     finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
  2777.                                             finother);
  2778.     finswap = finnow; finnow = finother; finother = finswap;
  2779.   }
  2780.   if (adxtail != 0.0) {
  2781.     if (bdytail != 0.0) {
  2782.       Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
  2783.       Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]);
  2784.       u[3] = u3;
  2785.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
  2786.                                               finother);
  2787.       finswap = finnow; finnow = finother; finother = finswap;
  2788.       if (cdheighttail != 0.0) {
  2789.         Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheighttail,
  2790.                         u3, u[2], u[1], u[0]);
  2791.         u[3] = u3;
  2792.         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
  2793.                                                 finother);
  2794.         finswap = finnow; finnow = finother; finother = finswap;
  2795.       }
  2796.     }
  2797.     if (cdytail != 0.0) {
  2798.       negate = -adxtail;
  2799.       Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
  2800.       Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]);
  2801.       u[3] = u3;
  2802.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
  2803.                                               finother);
  2804.       finswap = finnow; finnow = finother; finother = finswap;
  2805.       if (bdheighttail != 0.0) {
  2806.         Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheighttail,
  2807.                         u3, u[2], u[1], u[0]);
  2808.         u[3] = u3;
  2809.         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
  2810.                                                 finother);
  2811.         finswap = finnow; finnow = finother; finother = finswap;
  2812.       }
  2813.     }
  2814.   }
  2815.   if (bdxtail != 0.0) {
  2816.     if (cdytail != 0.0) {
  2817.       Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
  2818.       Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]);
  2819.       u[3] = u3;
  2820.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
  2821.                                               finother);
  2822.       finswap = finnow; finnow = finother; finother = finswap;
  2823.       if (adheighttail != 0.0) {
  2824.         Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheighttail,
  2825.                         u3, u[2], u[1], u[0]);
  2826.         u[3] = u3;
  2827.         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
  2828.                                                 finother);
  2829.         finswap = finnow; finnow = finother; finother = finswap;
  2830.       }
  2831.     }
  2832.     if (adytail != 0.0) {
  2833.       negate = -bdxtail;
  2834.       Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
  2835.       Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]);
  2836.       u[3] = u3;
  2837.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
  2838.                                               finother);
  2839.       finswap = finnow; finnow = finother; finother = finswap;
  2840.       if (cdheighttail != 0.0) {
  2841.         Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheighttail,
  2842.                         u3, u[2], u[1], u[0]);
  2843.         u[3] = u3;
  2844.         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
  2845.                                                 finother);
  2846.         finswap = finnow; finnow = finother; finother = finswap;
  2847.       }
  2848.     }
  2849.   }
  2850.   if (cdxtail != 0.0) {
  2851.     if (adytail != 0.0) {
  2852.       Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
  2853.       Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]);
  2854.       u[3] = u3;
  2855.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
  2856.                                               finother);
  2857.       finswap = finnow; finnow = finother; finother = finswap;
  2858.       if (bdheighttail != 0.0) {
  2859.         Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheighttail,
  2860.                         u3, u[2], u[1], u[0]);
  2861.         u[3] = u3;
  2862.         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
  2863.                                                 finother);
  2864.         finswap = finnow; finnow = finother; finother = finswap;
  2865.       }
  2866.     }
  2867.     if (bdytail != 0.0) {
  2868.       negate = -cdxtail;
  2869.       Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
  2870.       Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]);
  2871.       u[3] = u3;
  2872.       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
  2873.                                               finother);
  2874.       finswap = finnow; finnow = finother; finother = finswap;
  2875.       if (adheighttail != 0.0) {
  2876.         Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheighttail,
  2877.                         u3, u[2], u[1], u[0]);
  2878.         u[3] = u3;
  2879.         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
  2880.                                                 finother);
  2881.         finswap = finnow; finnow = finother; finother = finswap;
  2882.       }
  2883.     }
  2884.   }
  2885.   if (adheighttail != 0.0) {
  2886.     wlength = scale_expansion_zeroelim(bctlen, bct, adheighttail, w);
  2887.     finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
  2888.                                             finother);
  2889.     finswap = finnow; finnow = finother; finother = finswap;
  2890.   }
  2891.   if (bdheighttail != 0.0) {
  2892.     wlength = scale_expansion_zeroelim(catlen, cat, bdheighttail, w);
  2893.     finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
  2894.                                             finother);
  2895.     finswap = finnow; finnow = finother; finother = finswap;
  2896.   }
  2897.   if (cdheighttail != 0.0) {
  2898.     wlength = scale_expansion_zeroelim(abtlen, abt, cdheighttail, w);
  2899.     finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
  2900.                                             finother);
  2901.     finswap = finnow; finnow = finother; finother = finswap;
  2902.   }
  2903.   return finnow[finlength - 1];
  2904. }
  2905. #ifdef ANSI_DECLARATORS
  2906. REAL orient3d(struct mesh *m, struct behavior *b,
  2907.               vertex pa, vertex pb, vertex pc, vertex pd,
  2908.               REAL aheight, REAL bheight, REAL cheight, REAL dheight)
  2909. #else /* not ANSI_DECLARATORS */
  2910. REAL orient3d(m, b, pa, pb, pc, pd, aheight, bheight, cheight, dheight)
  2911. struct mesh *m;
  2912. struct behavior *b;
  2913. vertex pa;
  2914. vertex pb;
  2915. vertex pc;
  2916. vertex pd;
  2917. REAL aheight;