GeomPredicates-SSE-0.2: Numeric/Geometric/Predicates/Interval/IntervalFilterPrimitives.c
#include <math.h>
#include <emmintrin.h>
#include <stdio.h>
#include "IntervalSSE.h"
static inline
void fromInterval(double output[2], __m128d interval)
{
__m128d signmask = _mm_set_pd(0.0, -1.0 * 0.0);
_mm_storeu_pd(output, _mm_xor_pd(interval, signmask));
}
static inline
__m128d toInterval(double x)
{
__m128d signmask = _mm_set_pd(0.0, -1.0 * 0.0);
return _mm_xor_pd(_mm_set1_pd(x), signmask);
// return _mm_set_pd(x,-x);
}
////////////////////////////
static __m128d
ccw(__m128d x1, __m128d y1, __m128d x2, __m128d y2, __m128d x3, __m128d y3)
{
__m128d s1 = interval_add(interval_add(interval_mul(x1,y2),
interval_mul(x2,y3)),
interval_mul(x3,y1));
__m128d s2 = interval_add(interval_add(interval_mul(x1,y3),
interval_mul(x2,y1)),
interval_mul(x3,y2));
return interval_sub(s1,s2);
}
static __m128d
incircle(__m128d x1, __m128d y1, __m128d x2, __m128d y2, __m128d x3, __m128d y3, __m128d x4, __m128d y4)
{
#define DDD(x,y) interval_add(interval_mul(x,x),interval_mul(y,y))
__m128d a = interval_mul(DDD(x1,y1), ccw(x2,y2, x3,y3, x4,y4));
__m128d b = interval_mul(DDD(x2,y2), ccw(x1,y1, x3,y3, x4,y4));
__m128d c = interval_mul(DDD(x3,y3), ccw(x1,y1, x2,y2, x4,y4));
__m128d d = interval_mul(DDD(x4,y4), ccw(x1,y1, x2,y2, x3,y3));
return interval_add(interval_sub(a,b),interval_sub(c,d));
#undef DDD
}
static __m128d
cintt(__m128d lo, __m128d hi, __m128d p, int * error)
{
__m128d n = interval_sub(lo, p);
__m128d v = interval_sub(hi,lo);
return interval_div(n, interval_negate(v), error);
}
////////////////////////////
void
ccw_d(double ax, double ay, double bx, double by, double cx, double cy, double output[2])
{
int mode = _MM_GET_ROUNDING_MODE();
_MM_SET_ROUNDING_MODE(_MM_ROUND_DOWN);
__m128d x1 = toInterval(ax);
__m128d y1 = toInterval(ay);
__m128d x2 = toInterval(bx);
__m128d y2 = toInterval(by);
__m128d x3 = toInterval(cx);
__m128d y3 = toInterval(cy);
fromInterval(output, ccw(x1,y1,x2,y2,x3,y3));
_MM_SET_ROUNDING_MODE(mode);
}
void
incircle_d(double ax, double ay, double bx, double by, double cx, double cy, double dx, double dy, double output[2])
{
int mode = _MM_GET_ROUNDING_MODE();
_MM_SET_ROUNDING_MODE(_MM_ROUND_DOWN);
__m128d x1 = toInterval(ax);
__m128d y1 = toInterval(ay);
__m128d x2 = toInterval(bx);
__m128d y2 = toInterval(by);
__m128d x3 = toInterval(cx);
__m128d y3 = toInterval(cy);
__m128d x4 = toInterval(dx);
__m128d y4 = toInterval(dy);
fromInterval(output, incircle(x1,y1,x2,y2,x3,y3,x4,y4));
_MM_SET_ROUNDING_MODE(mode);
}
// Input interval must not be degenerate
int
cintt_d(double lo, double hi, double p, double output[2])
{
if (lo == hi)
return 0;
int mode = _MM_GET_ROUNDING_MODE();
int error = 0;
_MM_SET_ROUNDING_MODE(_MM_ROUND_DOWN);
__m128d result = cintt(toInterval(lo),toInterval(hi),toInterval(p),&error);
if (error == 1)
{
_MM_SET_ROUNDING_MODE(mode);
return 0;
} else
{
fromInterval(output, result);
_MM_SET_ROUNDING_MODE(mode);
return 1;
}
}
/*
void
main()
{
_MM_SET_ROUNDING_MODE(_MM_ROUND_DOWN);
double output[2];
__m128d x1 = toInterval(3);
__m128d y1 = toInterval(4);
fromInterval(output, interval_sub(x1,y1));
printf("x=%.16f,x2=%.16f\n", output[0],output[1]);
}
*/