Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

swh:1:snp:c78d7a14cc07423acb6a43d0e3059b9afd67996a
  • Code
  • Branches (1)
  • Releases (0)
    • Branches
    • Releases
    • HEAD
    • refs/heads/master
    No releases to show
  • f9aac5f
  • /
  • src
  • /
  • hand_optimized_predicates.hpp
Raw File Download

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
  • revision
  • snapshot
content badge
swh:1:cnt:2f0ac37ff1a7cffd8f103fdcfa22d0888705384d
directory badge
swh:1:dir:4f575ba51229ed8a439e690987eb7223782b67ec
revision badge
swh:1:rev:c5be799ee3dad53f5edf10eeb39527bbca5add11
snapshot badge
swh:1:snp:c78d7a14cc07423acb6a43d0e3059b9afd67996a

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
  • revision
  • snapshot
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Tip revision: c5be799ee3dad53f5edf10eeb39527bbca5add11 authored by LorenzoDiazzi on 29 May 2025, 10:15:58 UTC
Update README.md
Tip revision: c5be799
hand_optimized_predicates.hpp
/****************************************************************************
* Indirect predicates for geometric constructions					        *
*                                                                           *
* Consiglio Nazionale delle Ricerche                                        *
* Istituto di Matematica Applicata e Tecnologie Informatiche                *
* Sezione di Genova                                                         * 
* IMATI-GE / CNR                                                            * 
*                                                                           *
* Authors: Marco Attene                                                     * 
* Copyright(C) 2019: IMATI-GE / CNR                                         * 
* All rights reserved.                                                      * 
*                                                                           *
* This program is free software; you can redistribute it and/or modify      * 
* it under the terms of the GNU Lesser General Public License as published  * 
* by the Free Software Foundation; either version 3 of the License, or (at  * 
* your option) any later version.                                           * 
*                                                                           *
* This program is distributed in the hope that it will be useful, but       * 
* WITHOUT ANY WARRANTY; without even the implied warranty of                * 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser  * 
* General Public License for more details.                                  * 
*                                                                           *
* You should have received a copy of the GNU Lesser General Public License  * 
* along with this program.  If not, see http://www.gnu.org/licenses/.       *
*                                                                           *
****************************************************************************/ 

/* Should include incircle and insphere toexpansionObject:: */


#include "implicit_point.h"

#pragma intrinsic(fabs)


inline int orient2d_filtered(double p1x, double p1y, double p2x, double p2y, double p3x, double p3y)
{
	double dl = (p2x - p1x) * (p3y - p1y);
	double dr = (p2y - p1y) * (p3x - p1x);
	double det = dl - dr;
	double eb = 3.3306690738754706e-016 * (fabs(dl) + fabs(dr));
	return ((det >= eb) - (-det >= eb));
}

inline int orient2d_interval(interval_number p1x, interval_number p1y, interval_number p2x, interval_number p2y, interval_number p3x, interval_number p3y)
{
   setFPUModeToRoundUP();
   interval_number a11(p2x - p1x);
   interval_number a12(p2y - p1y);
   interval_number a21(p3x - p1x);
   interval_number a22(p3y - p1y);
   interval_number d1(a11 * a22);
   interval_number d2(a12 * a21);
   interval_number d(d1 - d2);
   setFPUModeToRoundNEAR();

   if (!d.signIsReliable()) return Filtered_Sign::UNCERTAIN;
   return d.sign();
}

inline int orient2d_exact(double p1x, double p1y, double p2x, double p2y, double p3x, double p3y)
{
    double acx[2], acy[2], bcx[2], bcy[2], dtl[2], dtr[2], B[4];
    double s[2], t[2], u[4], C1[8], C2[12], D[16];
    int C1l, C2l, Dl;
    

    acx[1] = (p1x - p3x);
    bcx[1] = (p2x - p3x);
    acy[1] = (p1y - p3y);
    bcy[1] = (p2y - p3y);

    expansionObject::Two_Prod(acx[1], bcy[1], dtl);
    expansionObject::Two_Prod(acy[1], bcx[1], dtr);
    expansionObject::Two_Two_Diff(dtl, dtr, B);

    double dsm = (fabs(dtl[1]) + fabs(dtr[1]));
    double det = expansionObject::To_Double(4, B);
    double eb = 2.2204460492503146e-16 * dsm;
    Dl = ((det >= eb) - (-det >= eb));
    if (Dl) return Dl;

    expansionObject::Two_Diff_Back(p1x, p3x, acx);
    expansionObject::Two_Diff_Back(p2x, p3x, bcx);
    expansionObject::Two_Diff_Back(p1y, p3y, acy);
    expansionObject::Two_Diff_Back(p2y, p3y, bcy);

    if ((acx[0] == 0.0) && (acy[0] == 0.0) && (bcx[0] == 0.0) && (bcy[0] == 0.0)) return ((det > 0) - (det < 0));

    eb = 1.1093356479670487e-31 * dsm + 3.3306690738754706e-16 * fabs(det);
    det += (acx[1] * bcy[0] + bcy[1] * acx[0]) - (acy[1] * bcx[0] + bcx[1] * acy[0]);
    Dl = ((det >= eb) - (-det >= eb));
    if (Dl) return Dl;

    expansionObject::Two_Prod(acx[0], bcy[1], s);
    expansionObject::Two_Prod(acy[0], bcx[1], t);
    expansionObject::Two_Two_Diff(s, t, u);
    C1l = expansionObject::Gen_Sum(4, B, 4, u, C1);

    expansionObject::Two_Prod(acx[1], bcy[0], s);
    expansionObject::Two_Prod(acy[1], bcx[0], t);
    expansionObject::Two_Two_Diff(s, t, u);
    C2l = expansionObject::Gen_Sum(C1l, C1, 4, u, C2);

    expansionObject::Two_Prod(acx[0], bcy[0], s);
    expansionObject::Two_Prod(acy[0], bcx[0], t);
    expansionObject::Two_Two_Diff(s, t, u);
    Dl = expansionObject::Gen_Sum(C2l, C2, 4, u, D);

    det = D[Dl - 1];
    return ((det >= eb) - (-det >= eb));
}

inline int orient2d(double p1x, double p1y, double p2x, double p2y, double p3x, double p3y)
{
   int ret = orient2d_filtered(p1x, p1y, p2x, p2y, p3x, p3y);
   if (ret) return ret;
   //ret = orient2d_interval(p1x, p1y, p2x, p2y, p3x, p3y);
   //if (ret != Filtered_Sign::UNCERTAIN) return ret;
   return orient2d_exact(p1x, p1y, p2x, p2y, p3x, p3y);
}

inline int orient3d_filtered(double px, double py, double pz, double qx, double qy, double qz, double rx, double ry, double rz, double sx, double sy, double sz)
{
	double fadx, fbdx, fcdx, fady, fbdy, fcdy, fadz, fbdz, fcdz, eb;
	double fbdxcdy, fcdxbdy, fcdxady, fadxcdy, fadxbdy, fbdxady, det;

	fadx = qx - px; fbdx = rx - px; fcdx = sx - px;
	fady = qy - py; fbdy = ry - py; fcdy = sy - py;
	fadz = qz - pz; fbdz = rz - pz; fcdz = sz - pz;

	fbdxcdy = fbdx * fcdy * fadz; fcdxbdy = fcdx * fbdy * fadz;
	fcdxady = fcdx * fady * fbdz; fadxcdy = fadx * fcdy * fbdz;
	fadxbdy = fadx * fbdy * fcdz; fbdxady = fbdx * fady * fcdz;

	det = (fbdxcdy - fcdxbdy) + (fcdxady - fadxcdy) + (fadxbdy - fbdxady);
	eb = 7.7715611723761027e-016 * (fabs(fbdxcdy) + fabs(fcdxbdy) + fabs(fcdxady) + fabs(fadxcdy) + fabs(fadxbdy) + fabs(fbdxady));
	return ((det >= eb) - (-det >= eb));
}

inline int orient3d_interval(interval_number px, interval_number py, interval_number pz, interval_number qx, interval_number qy, interval_number qz, interval_number rx, interval_number ry, interval_number rz, interval_number sx, interval_number sy, interval_number sz)
{
   setFPUModeToRoundUP();
   interval_number qx_px(qx - px);
   interval_number qy_py(qy - py);
   interval_number rx_px(rx - px);
   interval_number ry_py(ry - py);
   interval_number rz_pz(rz - pz);
   interval_number qz_pz(qz - pz);
   interval_number sx_px(sx - px);
   interval_number sy_py(sy - py);
   interval_number sz_pz(sz - pz);
   interval_number tmp_a(qx_px * ry_py);
   interval_number tmp_b(qy_py * rx_px);
   interval_number m01(tmp_a - tmp_b);
   interval_number tmq_a(qx_px * rz_pz);
   interval_number tmq_b(qz_pz * rx_px);
   interval_number m02(tmq_a - tmq_b);
   interval_number tmr_a(qy_py * rz_pz);
   interval_number tmr_b(qz_pz * ry_py);
   interval_number m12(tmr_a - tmr_b);
   interval_number mt1(m01 * sz_pz);
   interval_number mt2(m02 * sy_py);
   interval_number mt3(m12 * sx_px);
   interval_number mtt(mt1 - mt2);
   interval_number m012(mtt + mt3);
   setFPUModeToRoundNEAR();

   if (!m012.signIsReliable()) return Filtered_Sign::UNCERTAIN;
   return m012.sign();
}


inline void supo3d1(
	double* c1, double* c2, double* c3, double* c4, double* c5, double* c6,
	double* a1, double* a2, double& i, double* k1, double* k2, double* k3,
	double* k4, int& l1, int& l2)
{
	if (c1[0] == 0.0) {
		if (c2[0] == 0.0) {
			a1[0] = a2[0] = 0.0;
			l1 = l2 = 1;
		}
		else {
			i = -c2[0];
			expansionObject::Two_Prod(i, c3[1], a1);
			expansionObject::Two_Prod(c2[0], c4[1], a2);
			l1 = l2 = 2;
		}
	}
	else {
		if (c2[0] == 0.0) {
			i = -c1[0];
			expansionObject::Two_Prod(c1[0], c5[1], a1);
			expansionObject::Two_Prod(i, c6[1], a2);
			l1 = l2 = 2;
		}
		else {
			expansionObject::Two_Prod(c1[0], c5[1], k1);
			expansionObject::Two_Prod(c2[0], c3[1], k2);
			expansionObject::Two_Two_Diff(k1, k2, a1);
			expansionObject::Two_Prod(c2[0], c4[1], k3);
			expansionObject::Two_Prod(c1[0], c6[1], k4);
			expansionObject::Two_Two_Diff(k3, k4, a2);
			l1 = l2 = 4;
		}
	}
}

inline void supo3d2(
	double* c1, double* c2, double* c3, double* c4, double* u,
	int& fl, double fin[2][192], int& wh,
	double* c5, double& i, double* c6, double* c7)

{
	if (c1[0] != 0.0) {
		if (c2[0] != 0.0) {
			expansionObject::Two_Prod(c1[0], c2[0], c3);
			expansionObject::Two_One_Prod(c3, c4[1], u);
			fl = expansionObject::Gen_Sum(fl, fin[wh], 4, u, fin[!wh]);
			wh = !wh;
			if (c4[0] != 0.0) {
				expansionObject::Two_One_Prod(c3, c4[0], u);
				fl = expansionObject::Gen_Sum(fl, fin[wh], 4, u, fin[!wh]);
				wh = !wh;
			}
		}
		if (c5[0] != 0.0) {
			i = -c1[0];
			expansionObject::Two_Prod(i, c5[0], c6);
			expansionObject::Two_One_Prod(c6, c7[1], u);
			fl = expansionObject::Gen_Sum(fl, fin[wh], 4, u, fin[!wh]);
			wh = !wh;
			if (c7[0] != 0.0) {
				expansionObject::Two_One_Prod(c6, c7[0], u);
				fl = expansionObject::Gen_Sum(fl, fin[wh], 4, u, fin[!wh]);
				wh = !wh;
			}
		}
	}
}

inline int orient3d_exact(double pdx, double pdy, double pdz, double pax, double pay, double paz, double pbx, double pby, double pbz, double pcx, double pcy, double pcz)
{
	double eb, det;
	double adx[2], bdx[2], cdx[2], ady[2], bdy[2], cdy[2], adz[2], bdz[2], cdz[2];
	double bdxcdy[2], cdxbdy[2], cdxady[2], adxcdy[2], adxbdy[2], bdxady[2];
	double bc[4], ca[4], ab[4];
	double bdxt_cdy[2], cdxt_bdy[2], cdxt_ady[2];
	double adxt_cdy[2], adxt_bdy[2], bdxt_ady[2];
	double bdyt_cdx[2], cdyt_bdx[2], cdyt_adx[2];
	double adyt_cdx[2], adyt_bdx[2], bdyt_adx[2];
	double bdxt_cdyt[2], cdxt_bdyt[2], cdxt_adyt[2];
	double adxt_cdyt[2], adxt_bdyt[2], bdxt_adyt[2];
	double u[4], v[12], w[16];
	double adet[8], bdet[8], cdet[8], abdet[16];
	double fin[2][192];
	int wh = 0;
	double at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
	double bct[8], cat[8], abt[8];
	int alen, blen, clen, finlen, vlen, wlen;
	int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
	int bctlen, catlen, abtlen;
	int ablen;
	double inv;
	int ri;

	

	adx[1] = pax - pdx;
	bdx[1] = pbx - pdx;
	cdx[1] = pcx - pdx;
	ady[1] = pay - pdy;
	bdy[1] = pby - pdy;
	cdy[1] = pcy - pdy;
	adz[1] = paz - pdz;
	bdz[1] = pbz - pdz;
	cdz[1] = pcz - pdz;

	expansionObject::Two_Prod(bdx[1], cdy[1], bdxcdy);
	expansionObject::Two_Prod(cdx[1], bdy[1], cdxbdy);
	expansionObject::Two_Two_Diff(bdxcdy, cdxbdy, bc);
	alen = expansionObject::Gen_Scale(4, bc, adz[1], adet);

	expansionObject::Two_Prod(cdx[1], ady[1], cdxady);
	expansionObject::Two_Prod(adx[1], cdy[1], adxcdy);
	expansionObject::Two_Two_Diff(cdxady, adxcdy, ca);
	blen = expansionObject::Gen_Scale(4, ca, bdz[1], bdet);

	expansionObject::Two_Prod(adx[1], bdy[1], adxbdy);
	expansionObject::Two_Prod(bdx[1], ady[1], bdxady);
	expansionObject::Two_Two_Diff(adxbdy, bdxady, ab);
	clen = expansionObject::Gen_Scale(4, ab, cdz[1], cdet);

	ablen = expansionObject::Gen_Sum(alen, adet, blen, bdet, abdet);
	finlen = expansionObject::Gen_Sum(ablen, abdet, clen, cdet, fin[wh]);

	double xx1 = bdxcdy[1] * adz[1]; double xx2 = cdxbdy[1] * adz[1];
	double yy1 = cdxady[1] * bdz[1]; double yy2 = adxcdy[1] * bdz[1];
	double zz1 = adxbdy[1] * cdz[1]; double zz2 = bdxady[1] * cdz[1];
	double pm = fabs(xx1) + fabs(xx2) + fabs(yy1) + fabs(yy2) + fabs(zz1) + fabs(zz2);

	det = expansionObject::To_Double(finlen, fin[wh]);
	eb = 3.3306690738754731e-016 * pm;
	ri = (det >= eb) - (-det >= eb);
	if (ri) return ri;

	expansionObject::Two_Diff_Back(pax, pdx, adx);
	expansionObject::Two_Diff_Back(pbx, pdx, bdx);
	expansionObject::Two_Diff_Back(pcx, pdx, cdx);
	expansionObject::Two_Diff_Back(pay, pdy, ady);
	expansionObject::Two_Diff_Back(pby, pdy, bdy);
	expansionObject::Two_Diff_Back(pcy, pdy, cdy);
	expansionObject::Two_Diff_Back(paz, pdz, adz);
	expansionObject::Two_Diff_Back(pbz, pdz, bdz);
	expansionObject::Two_Diff_Back(pcz, pdz, cdz);

	if ((adx[0] == 0.0) && (bdx[0] == 0.0) && (cdx[0] == 0.0) &&
		(ady[0] == 0.0) && (bdy[0] == 0.0) && (cdy[0] == 0.0) &&
		(adz[0] == 0.0) && (bdz[0] == 0.0) && (cdz[0] == 0.0)) return (det > 0) - (det < 0);

	eb = 3.2047474274603644e-031 * pm + 1.1102230246251565e-016 * fabs(det);
	det += (adz[1] * ((bdx[1] * cdy[0] + cdy[1] * bdx[0])
		- (bdy[1] * cdx[0] + cdx[1] * bdy[0]))
		+ adz[0] * (bdx[1] * cdy[1] - bdy[1] * cdx[1]))
		+ (bdz[1] * ((cdx[1] * ady[0] + ady[1] * cdx[0])
			- (cdy[1] * adx[0] + adx[1] * cdy[0]))
			+ bdz[0] * (cdx[1] * ady[1] - cdy[1] * adx[1]))
		+ (cdz[1] * ((adx[1] * bdy[0] + bdy[1] * adx[0])
			- (ady[1] * bdx[0] + bdx[1] * ady[0]))
			+ cdz[0] * (adx[1] * bdy[1] - ady[1] * bdx[1]));
	ri = (det >= eb) - (-det >= eb);
	if (ri) return ri;

	// Filters did not work. Compute exactly...
	supo3d1(adx, ady, bdx, cdx, bdy, cdy, at_b, at_c, inv,
		adxt_bdy, adyt_bdx, adyt_cdx, adxt_cdy, at_blen, at_clen);

	supo3d1(bdx, bdy, cdx, adx, cdy, ady, bt_c, bt_a, inv,
		bdxt_cdy, bdyt_cdx, bdyt_adx, bdxt_ady, bt_alen, bt_clen);

	supo3d1(cdx, cdy, adx, bdx, ady, bdy, ct_a, ct_b, inv,
		cdxt_ady, cdyt_adx, cdyt_bdx, cdxt_bdy, ct_alen, ct_blen);

	bctlen = expansionObject::Gen_Sum(bt_clen, bt_c, ct_blen, ct_b, bct);
	wlen = expansionObject::Gen_Scale(bctlen, bct, adz[1], w);
	finlen = expansionObject::Gen_Sum(finlen, fin[wh], wlen, w, fin[(!wh)]); wh = !wh;

	catlen = expansionObject::Gen_Sum(ct_alen, ct_a, at_clen, at_c, cat);
	wlen = expansionObject::Gen_Scale(catlen, cat, bdz[1], w);
	finlen = expansionObject::Gen_Sum(finlen, fin[wh], wlen, w, fin[(!wh)]); wh = !wh;

	abtlen = expansionObject::Gen_Sum(at_blen, at_b, bt_alen, bt_a, abt);
	wlen = expansionObject::Gen_Scale(abtlen, abt, cdz[1], w);
	finlen = expansionObject::Gen_Sum(finlen, fin[wh], wlen, w, fin[(!wh)]); wh = !wh;

	if (adz[0] != 0.0) {
		vlen = expansionObject::Gen_Scale(4, bc, adz[0], v);
		finlen = expansionObject::Gen_Sum(finlen, fin[wh], vlen, v, fin[(!wh)]); wh = !wh;
	}
	if (bdz[0] != 0.0) {
		vlen = expansionObject::Gen_Scale(4, ca, bdz[0], v);
		finlen = expansionObject::Gen_Sum(finlen, fin[wh], vlen, v, fin[(!wh)]); wh = !wh;
	}
	if (cdz[0] != 0.0) {
		vlen = expansionObject::Gen_Scale(4, ab, cdz[0], v);
		finlen = expansionObject::Gen_Sum(finlen, fin[wh], vlen, v, fin[(!wh)]); wh = !wh;
	}

	supo3d2(adx, bdy, adxt_bdyt, cdz, u, finlen, fin, wh, cdy, inv, adxt_cdyt, bdz);
	supo3d2(bdx, cdy, bdxt_cdyt, adz, u, finlen, fin, wh, ady, inv, bdxt_adyt, cdz);
	supo3d2(cdx, ady, cdxt_adyt, bdz, u, finlen, fin, wh, bdy, inv, cdxt_bdyt, adz);

	if (adz[0] != 0.0) {
		wlen = expansionObject::Gen_Scale(bctlen, bct, adz[0], w);
		finlen = expansionObject::Gen_Sum(finlen, fin[wh], wlen, w, fin[!wh]); wh = !wh;
	}
	if (bdz[0] != 0.0) {
		wlen = expansionObject::Gen_Scale(catlen, cat, bdz[0], w);
		finlen = expansionObject::Gen_Sum(finlen, fin[wh], wlen, w, fin[!wh]); wh = !wh;
	}
	if (cdz[0] != 0.0) {
		wlen = expansionObject::Gen_Scale(abtlen, abt, cdz[0], w);
		finlen = expansionObject::Gen_Sum(finlen, fin[wh], wlen, w, fin[!wh]);	wh = !wh;
	}

	det = fin[wh][finlen - 1];
	return (det > 0) - (det < 0);
}

inline int orient3d(double px, double py, double pz, double qx, double qy, double qz, double rx, double ry, double rz, double sx, double sy, double sz)
{
   int ret;
   ret = orient3d_filtered(px, py, pz, qx, qy, qz, rx, ry, rz, sx, sy, sz);
   if (ret) return ret;
   //ret = orient3d_interval(px, py, pz, qx, qy, qz, rx, ry, rz, sx, sy, sz);
   //if (ret != Filtered_Sign::UNCERTAIN) return ret;
   return orient3d_exact(px, py, pz, qx, qy, qz, rx, ry, rz, sx, sy, sz);
}

back to top

Software Heritage — Copyright (C) 2015–2025, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API