mirror of
https://github.com/postgres/postgres.git
synced 2026-03-31 23:07:04 -04:00
Make geometry cast functions error safe
This adjusts cast functions of the geometry types to support soft errors. This requires refactoring of various helper functions to support error contexts. Also make the float8 to float4 cast error safe. It requires some of the same helper functions. This is in preparation for a future feature where conversion errors in casts can be caught. (The function casting type circle to type polygon is not yet made error safe, because it is an SQL language function.) Author: jian he <jian.universality@gmail.com> Reviewed-by: Amul Sul <sulamul@gmail.com> Reviewed-by: Corey Huinker <corey.huinker@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/CADkLM%3Dfv1JfY4Ufa-jcwwNbjQixNViskQ8jZu3Tz_p656i_4hQ%40mail.gmail.com
This commit is contained in:
parent
d4cb9c3776
commit
45cdaf3665
3 changed files with 254 additions and 84 deletions
|
|
@ -123,6 +123,30 @@ float_zero_divide_error(void)
|
|||
errmsg("division by zero")));
|
||||
}
|
||||
|
||||
float8
|
||||
float_overflow_error_ext(struct Node *escontext)
|
||||
{
|
||||
ereturn(escontext, 0.0,
|
||||
errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("value out of range: overflow"));
|
||||
}
|
||||
|
||||
float8
|
||||
float_underflow_error_ext(struct Node *escontext)
|
||||
{
|
||||
ereturn(escontext, 0.0,
|
||||
errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||
errmsg("value out of range: underflow"));
|
||||
}
|
||||
|
||||
float8
|
||||
float_zero_divide_error_ext(struct Node *escontext)
|
||||
{
|
||||
ereturn(escontext, 0.0,
|
||||
(errcode(ERRCODE_DIVISION_BY_ZERO),
|
||||
errmsg("division by zero")));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns -1 if 'val' represents negative infinity, 1 if 'val'
|
||||
|
|
@ -1216,9 +1240,9 @@ dtof(PG_FUNCTION_ARGS)
|
|||
|
||||
result = (float4) num;
|
||||
if (unlikely(isinf(result)) && !isinf(num))
|
||||
float_overflow_error();
|
||||
float_overflow_error_ext(fcinfo->context);
|
||||
if (unlikely(result == 0.0f) && num != 0.0)
|
||||
float_underflow_error();
|
||||
float_underflow_error_ext(fcinfo->context);
|
||||
|
||||
PG_RETURN_FLOAT4(result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,12 +77,12 @@ enum path_delim
|
|||
|
||||
/* Routines for points */
|
||||
static inline void point_construct(Point *result, float8 x, float8 y);
|
||||
static inline void point_add_point(Point *result, Point *pt1, Point *pt2);
|
||||
static inline void point_add_point(Point *result, Point *pt1, Point *pt2, Node *escontext);
|
||||
static inline void point_sub_point(Point *result, Point *pt1, Point *pt2);
|
||||
static inline void point_mul_point(Point *result, Point *pt1, Point *pt2);
|
||||
static inline void point_div_point(Point *result, Point *pt1, Point *pt2);
|
||||
static inline bool point_eq_point(Point *pt1, Point *pt2);
|
||||
static inline float8 point_dt(Point *pt1, Point *pt2);
|
||||
static inline float8 point_dt(Point *pt1, Point *pt2, Node *escontext);
|
||||
static inline float8 point_sl(Point *pt1, Point *pt2);
|
||||
static int point_inside(Point *p, int npts, Point *plist);
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ static float8 lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg);
|
|||
|
||||
/* Routines for boxes */
|
||||
static inline void box_construct(BOX *result, Point *pt1, Point *pt2);
|
||||
static void box_cn(Point *center, BOX *box);
|
||||
static void box_cn(Point *center, BOX *box, Node *escontext);
|
||||
static bool box_ov(BOX *box1, BOX *box2);
|
||||
static float8 box_ar(BOX *box);
|
||||
static float8 box_ht(BOX *box);
|
||||
|
|
@ -125,7 +125,7 @@ static float8 circle_ar(CIRCLE *circle);
|
|||
|
||||
/* Routines for polygons */
|
||||
static void make_bound_box(POLYGON *poly);
|
||||
static void poly_to_circle(CIRCLE *result, POLYGON *poly);
|
||||
static void poly_to_circle(CIRCLE *result, POLYGON *poly, Node *escontext);
|
||||
static bool lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start);
|
||||
static bool poly_contain_poly(POLYGON *contains_poly, POLYGON *contained_poly);
|
||||
static bool plist_same(int npts, Point *p1, Point *p2);
|
||||
|
|
@ -836,10 +836,10 @@ box_distance(PG_FUNCTION_ARGS)
|
|||
Point a,
|
||||
b;
|
||||
|
||||
box_cn(&a, box1);
|
||||
box_cn(&b, box2);
|
||||
box_cn(&a, box1, NULL);
|
||||
box_cn(&b, box2, NULL);
|
||||
|
||||
PG_RETURN_FLOAT8(point_dt(&a, &b));
|
||||
PG_RETURN_FLOAT8(point_dt(&a, &b, NULL));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -851,7 +851,9 @@ box_center(PG_FUNCTION_ARGS)
|
|||
BOX *box = PG_GETARG_BOX_P(0);
|
||||
Point *result = palloc_object(Point);
|
||||
|
||||
box_cn(result, box);
|
||||
box_cn(result, box, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
PG_RETURN_NULL();
|
||||
|
||||
PG_RETURN_POINT_P(result);
|
||||
}
|
||||
|
|
@ -869,12 +871,27 @@ box_ar(BOX *box)
|
|||
/* box_cn - stores the centerpoint of the box into *center.
|
||||
*/
|
||||
static void
|
||||
box_cn(Point *center, BOX *box)
|
||||
box_cn(Point *center, BOX *box, Node *escontext)
|
||||
{
|
||||
center->x = float8_div(float8_pl(box->high.x, box->low.x), 2.0);
|
||||
center->y = float8_div(float8_pl(box->high.y, box->low.y), 2.0);
|
||||
}
|
||||
float8 x;
|
||||
float8 y;
|
||||
|
||||
x = float8_pl_safe(box->high.x, box->low.x, escontext);
|
||||
if (SOFT_ERROR_OCCURRED(escontext))
|
||||
return;
|
||||
|
||||
center->x = float8_div_safe(x, 2.0, escontext);
|
||||
if (SOFT_ERROR_OCCURRED(escontext))
|
||||
return;
|
||||
|
||||
y = float8_pl_safe(box->high.y, box->low.y, escontext);
|
||||
if (SOFT_ERROR_OCCURRED(escontext))
|
||||
return;
|
||||
|
||||
center->y = float8_div_safe(y, 2.0, escontext);
|
||||
if (SOFT_ERROR_OCCURRED(escontext))
|
||||
return;
|
||||
}
|
||||
|
||||
/* box_wd - returns the width (length) of the box
|
||||
* (horizontal magnitude).
|
||||
|
|
@ -1808,7 +1825,7 @@ path_length(PG_FUNCTION_ARGS)
|
|||
iprev = path->npts - 1; /* include the closure segment */
|
||||
}
|
||||
|
||||
result = float8_pl(result, point_dt(&path->p[iprev], &path->p[i]));
|
||||
result = float8_pl(result, point_dt(&path->p[iprev], &path->p[i], NULL));
|
||||
}
|
||||
|
||||
PG_RETURN_FLOAT8(result);
|
||||
|
|
@ -1995,13 +2012,24 @@ point_distance(PG_FUNCTION_ARGS)
|
|||
Point *pt1 = PG_GETARG_POINT_P(0);
|
||||
Point *pt2 = PG_GETARG_POINT_P(1);
|
||||
|
||||
PG_RETURN_FLOAT8(point_dt(pt1, pt2));
|
||||
PG_RETURN_FLOAT8(point_dt(pt1, pt2, NULL));
|
||||
}
|
||||
|
||||
static inline float8
|
||||
point_dt(Point *pt1, Point *pt2)
|
||||
point_dt(Point *pt1, Point *pt2, Node *escontext)
|
||||
{
|
||||
return hypot(float8_mi(pt1->x, pt2->x), float8_mi(pt1->y, pt2->y));
|
||||
float8 x;
|
||||
float8 y;
|
||||
|
||||
x = float8_mi_safe(pt1->x, pt2->x, escontext);
|
||||
if (unlikely(SOFT_ERROR_OCCURRED(escontext)))
|
||||
return 0.0;
|
||||
|
||||
y = float8_mi_safe(pt1->y, pt2->y, escontext);
|
||||
if (unlikely(SOFT_ERROR_OCCURRED(escontext)))
|
||||
return 0.0;
|
||||
|
||||
return hypot(x, y);
|
||||
}
|
||||
|
||||
Datum
|
||||
|
|
@ -2173,7 +2201,7 @@ lseg_length(PG_FUNCTION_ARGS)
|
|||
{
|
||||
LSEG *lseg = PG_GETARG_LSEG_P(0);
|
||||
|
||||
PG_RETURN_FLOAT8(point_dt(&lseg->p[0], &lseg->p[1]));
|
||||
PG_RETURN_FLOAT8(point_dt(&lseg->p[0], &lseg->p[1], NULL));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------
|
||||
|
|
@ -2258,8 +2286,8 @@ lseg_lt(PG_FUNCTION_ARGS)
|
|||
LSEG *l1 = PG_GETARG_LSEG_P(0);
|
||||
LSEG *l2 = PG_GETARG_LSEG_P(1);
|
||||
|
||||
PG_RETURN_BOOL(FPlt(point_dt(&l1->p[0], &l1->p[1]),
|
||||
point_dt(&l2->p[0], &l2->p[1])));
|
||||
PG_RETURN_BOOL(FPlt(point_dt(&l1->p[0], &l1->p[1], NULL),
|
||||
point_dt(&l2->p[0], &l2->p[1], NULL)));
|
||||
}
|
||||
|
||||
Datum
|
||||
|
|
@ -2268,8 +2296,8 @@ lseg_le(PG_FUNCTION_ARGS)
|
|||
LSEG *l1 = PG_GETARG_LSEG_P(0);
|
||||
LSEG *l2 = PG_GETARG_LSEG_P(1);
|
||||
|
||||
PG_RETURN_BOOL(FPle(point_dt(&l1->p[0], &l1->p[1]),
|
||||
point_dt(&l2->p[0], &l2->p[1])));
|
||||
PG_RETURN_BOOL(FPle(point_dt(&l1->p[0], &l1->p[1], NULL),
|
||||
point_dt(&l2->p[0], &l2->p[1], NULL)));
|
||||
}
|
||||
|
||||
Datum
|
||||
|
|
@ -2278,8 +2306,8 @@ lseg_gt(PG_FUNCTION_ARGS)
|
|||
LSEG *l1 = PG_GETARG_LSEG_P(0);
|
||||
LSEG *l2 = PG_GETARG_LSEG_P(1);
|
||||
|
||||
PG_RETURN_BOOL(FPgt(point_dt(&l1->p[0], &l1->p[1]),
|
||||
point_dt(&l2->p[0], &l2->p[1])));
|
||||
PG_RETURN_BOOL(FPgt(point_dt(&l1->p[0], &l1->p[1], NULL),
|
||||
point_dt(&l2->p[0], &l2->p[1], NULL)));
|
||||
}
|
||||
|
||||
Datum
|
||||
|
|
@ -2288,8 +2316,8 @@ lseg_ge(PG_FUNCTION_ARGS)
|
|||
LSEG *l1 = PG_GETARG_LSEG_P(0);
|
||||
LSEG *l2 = PG_GETARG_LSEG_P(1);
|
||||
|
||||
PG_RETURN_BOOL(FPge(point_dt(&l1->p[0], &l1->p[1]),
|
||||
point_dt(&l2->p[0], &l2->p[1])));
|
||||
PG_RETURN_BOOL(FPge(point_dt(&l1->p[0], &l1->p[1], NULL),
|
||||
point_dt(&l2->p[0], &l2->p[1], NULL)));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2317,13 +2345,31 @@ lseg_center(PG_FUNCTION_ARGS)
|
|||
{
|
||||
LSEG *lseg = PG_GETARG_LSEG_P(0);
|
||||
Point *result;
|
||||
float8 x;
|
||||
float8 y;
|
||||
|
||||
result = palloc_object(Point);
|
||||
|
||||
result->x = float8_div(float8_pl(lseg->p[0].x, lseg->p[1].x), 2.0);
|
||||
result->y = float8_div(float8_pl(lseg->p[0].y, lseg->p[1].y), 2.0);
|
||||
x = float8_pl_safe(lseg->p[0].x, lseg->p[1].x, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
result->x = float8_div_safe(x, 2.0, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
y = float8_pl_safe(lseg->p[0].y, lseg->p[1].y, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
result->y = float8_div_safe(y, 2.0, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
PG_RETURN_POINT_P(result);
|
||||
|
||||
fail:
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2743,7 +2789,7 @@ line_closept_point(Point *result, LINE *line, Point *point)
|
|||
if (result != NULL)
|
||||
*result = closept;
|
||||
|
||||
return point_dt(&closept, point);
|
||||
return point_dt(&closept, point, NULL);
|
||||
}
|
||||
|
||||
Datum
|
||||
|
|
@ -2784,7 +2830,7 @@ lseg_closept_point(Point *result, LSEG *lseg, Point *pt)
|
|||
if (result != NULL)
|
||||
*result = closept;
|
||||
|
||||
return point_dt(&closept, pt);
|
||||
return point_dt(&closept, pt, NULL);
|
||||
}
|
||||
|
||||
Datum
|
||||
|
|
@ -3108,9 +3154,9 @@ on_pl(PG_FUNCTION_ARGS)
|
|||
static bool
|
||||
lseg_contain_point(LSEG *lseg, Point *pt)
|
||||
{
|
||||
return FPeq(point_dt(pt, &lseg->p[0]) +
|
||||
point_dt(pt, &lseg->p[1]),
|
||||
point_dt(&lseg->p[0], &lseg->p[1]));
|
||||
return FPeq(point_dt(pt, &lseg->p[0], NULL) +
|
||||
point_dt(pt, &lseg->p[1], NULL),
|
||||
point_dt(&lseg->p[0], &lseg->p[1], NULL));
|
||||
}
|
||||
|
||||
Datum
|
||||
|
|
@ -3176,11 +3222,11 @@ on_ppath(PG_FUNCTION_ARGS)
|
|||
if (!path->closed)
|
||||
{
|
||||
n = path->npts - 1;
|
||||
a = point_dt(pt, &path->p[0]);
|
||||
a = point_dt(pt, &path->p[0], NULL);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
b = point_dt(pt, &path->p[i + 1]);
|
||||
if (FPeq(float8_pl(a, b), point_dt(&path->p[i], &path->p[i + 1])))
|
||||
b = point_dt(pt, &path->p[i + 1], NULL);
|
||||
if (FPeq(float8_pl(a, b), point_dt(&path->p[i], &path->p[i + 1], NULL)))
|
||||
PG_RETURN_BOOL(true);
|
||||
a = b;
|
||||
}
|
||||
|
|
@ -3277,7 +3323,7 @@ box_interpt_lseg(Point *result, BOX *box, LSEG *lseg)
|
|||
|
||||
if (result != NULL)
|
||||
{
|
||||
box_cn(&point, box);
|
||||
box_cn(&point, box, NULL);
|
||||
lseg_closept_point(result, lseg, &point);
|
||||
}
|
||||
|
||||
|
|
@ -4108,11 +4154,20 @@ construct_point(PG_FUNCTION_ARGS)
|
|||
|
||||
|
||||
static inline void
|
||||
point_add_point(Point *result, Point *pt1, Point *pt2)
|
||||
point_add_point(Point *result, Point *pt1, Point *pt2, Node *escontext)
|
||||
{
|
||||
point_construct(result,
|
||||
float8_pl(pt1->x, pt2->x),
|
||||
float8_pl(pt1->y, pt2->y));
|
||||
float8 x;
|
||||
float8 y;
|
||||
|
||||
x = float8_pl_safe(pt1->x, pt2->x, escontext);
|
||||
if (SOFT_ERROR_OCCURRED(escontext))
|
||||
return;
|
||||
|
||||
y = float8_pl_safe(pt1->y, pt2->y, escontext);
|
||||
if (SOFT_ERROR_OCCURRED(escontext))
|
||||
return;
|
||||
|
||||
point_construct(result, x, y);
|
||||
}
|
||||
|
||||
Datum
|
||||
|
|
@ -4124,7 +4179,7 @@ point_add(PG_FUNCTION_ARGS)
|
|||
|
||||
result = palloc_object(Point);
|
||||
|
||||
point_add_point(result, p1, p2);
|
||||
point_add_point(result, p1, p2, NULL);
|
||||
|
||||
PG_RETURN_POINT_P(result);
|
||||
}
|
||||
|
|
@ -4236,8 +4291,8 @@ box_add(PG_FUNCTION_ARGS)
|
|||
|
||||
result = palloc_object(BOX);
|
||||
|
||||
point_add_point(&result->high, &box->high, p);
|
||||
point_add_point(&result->low, &box->low, p);
|
||||
point_add_point(&result->high, &box->high, p, NULL);
|
||||
point_add_point(&result->low, &box->low, p, NULL);
|
||||
|
||||
PG_RETURN_BOX_P(result);
|
||||
}
|
||||
|
|
@ -4400,7 +4455,7 @@ path_add_pt(PG_FUNCTION_ARGS)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < path->npts; i++)
|
||||
point_add_point(&path->p[i], &path->p[i], point);
|
||||
point_add_point(&path->p[i], &path->p[i], point, NULL);
|
||||
|
||||
PG_RETURN_PATH_P(path);
|
||||
}
|
||||
|
|
@ -4458,7 +4513,7 @@ path_poly(PG_FUNCTION_ARGS)
|
|||
|
||||
/* This is not very consistent --- other similar cases return NULL ... */
|
||||
if (!path->closed)
|
||||
ereport(ERROR,
|
||||
ereturn(fcinfo->context, (Datum) 0,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("open path cannot be converted to polygon")));
|
||||
|
||||
|
|
@ -4508,7 +4563,10 @@ poly_center(PG_FUNCTION_ARGS)
|
|||
|
||||
result = palloc_object(Point);
|
||||
|
||||
poly_to_circle(&circle, poly);
|
||||
poly_to_circle(&circle, poly, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
PG_RETURN_NULL();
|
||||
|
||||
*result = circle.center;
|
||||
|
||||
PG_RETURN_POINT_P(result);
|
||||
|
|
@ -4766,7 +4824,7 @@ circle_overlap(PG_FUNCTION_ARGS)
|
|||
CIRCLE *circle1 = PG_GETARG_CIRCLE_P(0);
|
||||
CIRCLE *circle2 = PG_GETARG_CIRCLE_P(1);
|
||||
|
||||
PG_RETURN_BOOL(FPle(point_dt(&circle1->center, &circle2->center),
|
||||
PG_RETURN_BOOL(FPle(point_dt(&circle1->center, &circle2->center, NULL),
|
||||
float8_pl(circle1->radius, circle2->radius)));
|
||||
}
|
||||
|
||||
|
|
@ -4828,7 +4886,7 @@ circle_contained(PG_FUNCTION_ARGS)
|
|||
CIRCLE *circle1 = PG_GETARG_CIRCLE_P(0);
|
||||
CIRCLE *circle2 = PG_GETARG_CIRCLE_P(1);
|
||||
|
||||
PG_RETURN_BOOL(FPle(point_dt(&circle1->center, &circle2->center),
|
||||
PG_RETURN_BOOL(FPle(point_dt(&circle1->center, &circle2->center, NULL),
|
||||
float8_mi(circle2->radius, circle1->radius)));
|
||||
}
|
||||
|
||||
|
|
@ -4840,7 +4898,7 @@ circle_contain(PG_FUNCTION_ARGS)
|
|||
CIRCLE *circle1 = PG_GETARG_CIRCLE_P(0);
|
||||
CIRCLE *circle2 = PG_GETARG_CIRCLE_P(1);
|
||||
|
||||
PG_RETURN_BOOL(FPle(point_dt(&circle1->center, &circle2->center),
|
||||
PG_RETURN_BOOL(FPle(point_dt(&circle1->center, &circle2->center, NULL),
|
||||
float8_mi(circle1->radius, circle2->radius)));
|
||||
}
|
||||
|
||||
|
|
@ -4970,7 +5028,7 @@ circle_add_pt(PG_FUNCTION_ARGS)
|
|||
|
||||
result = palloc_object(CIRCLE);
|
||||
|
||||
point_add_point(&result->center, &circle->center, point);
|
||||
point_add_point(&result->center, &circle->center, point, NULL);
|
||||
result->radius = circle->radius;
|
||||
|
||||
PG_RETURN_CIRCLE_P(result);
|
||||
|
|
@ -5069,7 +5127,7 @@ circle_distance(PG_FUNCTION_ARGS)
|
|||
CIRCLE *circle2 = PG_GETARG_CIRCLE_P(1);
|
||||
float8 result;
|
||||
|
||||
result = float8_mi(point_dt(&circle1->center, &circle2->center),
|
||||
result = float8_mi(point_dt(&circle1->center, &circle2->center, NULL),
|
||||
float8_pl(circle1->radius, circle2->radius));
|
||||
if (result < 0.0)
|
||||
result = 0.0;
|
||||
|
|
@ -5085,7 +5143,7 @@ circle_contain_pt(PG_FUNCTION_ARGS)
|
|||
Point *point = PG_GETARG_POINT_P(1);
|
||||
float8 d;
|
||||
|
||||
d = point_dt(&circle->center, point);
|
||||
d = point_dt(&circle->center, point, NULL);
|
||||
PG_RETURN_BOOL(d <= circle->radius);
|
||||
}
|
||||
|
||||
|
|
@ -5097,7 +5155,7 @@ pt_contained_circle(PG_FUNCTION_ARGS)
|
|||
CIRCLE *circle = PG_GETARG_CIRCLE_P(1);
|
||||
float8 d;
|
||||
|
||||
d = point_dt(&circle->center, point);
|
||||
d = point_dt(&circle->center, point, NULL);
|
||||
PG_RETURN_BOOL(d <= circle->radius);
|
||||
}
|
||||
|
||||
|
|
@ -5112,7 +5170,7 @@ dist_pc(PG_FUNCTION_ARGS)
|
|||
CIRCLE *circle = PG_GETARG_CIRCLE_P(1);
|
||||
float8 result;
|
||||
|
||||
result = float8_mi(point_dt(point, &circle->center),
|
||||
result = float8_mi(point_dt(point, &circle->center, NULL),
|
||||
circle->radius);
|
||||
if (result < 0.0)
|
||||
result = 0.0;
|
||||
|
|
@ -5130,7 +5188,7 @@ dist_cpoint(PG_FUNCTION_ARGS)
|
|||
Point *point = PG_GETARG_POINT_P(1);
|
||||
float8 result;
|
||||
|
||||
result = float8_mi(point_dt(point, &circle->center), circle->radius);
|
||||
result = float8_mi(point_dt(point, &circle->center, NULL), circle->radius);
|
||||
if (result < 0.0)
|
||||
result = 0.0;
|
||||
|
||||
|
|
@ -5191,14 +5249,30 @@ circle_box(PG_FUNCTION_ARGS)
|
|||
|
||||
box = palloc_object(BOX);
|
||||
|
||||
delta = float8_div(circle->radius, sqrt(2.0));
|
||||
delta = float8_div_safe(circle->radius, sqrt(2.0), fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
box->high.x = float8_pl(circle->center.x, delta);
|
||||
box->low.x = float8_mi(circle->center.x, delta);
|
||||
box->high.y = float8_pl(circle->center.y, delta);
|
||||
box->low.y = float8_mi(circle->center.y, delta);
|
||||
box->high.x = float8_pl_safe(circle->center.x, delta, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
box->low.x = float8_mi_safe(circle->center.x, delta, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
box->high.y = float8_pl_safe(circle->center.y, delta, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
box->low.y = float8_mi_safe(circle->center.y, delta, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
PG_RETURN_BOX_P(box);
|
||||
|
||||
fail:
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
/* box_circle()
|
||||
|
|
@ -5209,15 +5283,37 @@ box_circle(PG_FUNCTION_ARGS)
|
|||
{
|
||||
BOX *box = PG_GETARG_BOX_P(0);
|
||||
CIRCLE *circle;
|
||||
float8 x;
|
||||
float8 y;
|
||||
|
||||
circle = palloc_object(CIRCLE);
|
||||
|
||||
circle->center.x = float8_div(float8_pl(box->high.x, box->low.x), 2.0);
|
||||
circle->center.y = float8_div(float8_pl(box->high.y, box->low.y), 2.0);
|
||||
x = float8_pl_safe(box->high.x, box->low.x, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
circle->radius = point_dt(&circle->center, &box->high);
|
||||
circle->center.x = float8_div_safe(x, 2.0, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
y = float8_pl_safe(box->high.y, box->low.y, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
circle->center.y = float8_div_safe(y, 2.0, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
circle->radius = point_dt(&circle->center, &box->high,
|
||||
fcinfo->context);
|
||||
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
goto fail;
|
||||
|
||||
PG_RETURN_CIRCLE_P(circle);
|
||||
|
||||
fail:
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -5282,9 +5378,10 @@ circle_poly(PG_FUNCTION_ARGS)
|
|||
* rather than straight average values of points - tgl 97/01/21.
|
||||
*/
|
||||
static void
|
||||
poly_to_circle(CIRCLE *result, POLYGON *poly)
|
||||
poly_to_circle(CIRCLE *result, POLYGON *poly, Node *escontext)
|
||||
{
|
||||
int i;
|
||||
float8 x;
|
||||
|
||||
Assert(poly->npts > 0);
|
||||
|
||||
|
|
@ -5293,14 +5390,34 @@ poly_to_circle(CIRCLE *result, POLYGON *poly)
|
|||
result->radius = 0;
|
||||
|
||||
for (i = 0; i < poly->npts; i++)
|
||||
point_add_point(&result->center, &result->center, &poly->p[i]);
|
||||
result->center.x = float8_div(result->center.x, poly->npts);
|
||||
result->center.y = float8_div(result->center.y, poly->npts);
|
||||
{
|
||||
point_add_point(&result->center, &result->center, &poly->p[i], escontext);
|
||||
if (SOFT_ERROR_OCCURRED(escontext))
|
||||
return;
|
||||
}
|
||||
|
||||
result->center.x = float8_div_safe(result->center.x, poly->npts, escontext);
|
||||
if (SOFT_ERROR_OCCURRED(escontext))
|
||||
return;
|
||||
|
||||
result->center.y = float8_div_safe(result->center.y, poly->npts, escontext);
|
||||
if (SOFT_ERROR_OCCURRED(escontext))
|
||||
return;
|
||||
|
||||
for (i = 0; i < poly->npts; i++)
|
||||
result->radius = float8_pl(result->radius,
|
||||
point_dt(&poly->p[i], &result->center));
|
||||
result->radius = float8_div(result->radius, poly->npts);
|
||||
{
|
||||
x = point_dt(&poly->p[i], &result->center, escontext);
|
||||
if (SOFT_ERROR_OCCURRED(escontext))
|
||||
return;
|
||||
|
||||
result->radius = float8_pl_safe(result->radius, x, escontext);
|
||||
if (SOFT_ERROR_OCCURRED(escontext))
|
||||
return;
|
||||
}
|
||||
|
||||
result->radius = float8_div_safe(result->radius, poly->npts, escontext);
|
||||
if (SOFT_ERROR_OCCURRED(escontext))
|
||||
return;
|
||||
}
|
||||
|
||||
Datum
|
||||
|
|
@ -5311,7 +5428,9 @@ poly_circle(PG_FUNCTION_ARGS)
|
|||
|
||||
result = palloc_object(CIRCLE);
|
||||
|
||||
poly_to_circle(result, poly);
|
||||
poly_to_circle(result, poly, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
PG_RETURN_NULL();
|
||||
|
||||
PG_RETURN_CIRCLE_P(result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ extern PGDLLIMPORT int extra_float_digits;
|
|||
pg_noreturn extern void float_overflow_error(void);
|
||||
pg_noreturn extern void float_underflow_error(void);
|
||||
pg_noreturn extern void float_zero_divide_error(void);
|
||||
extern float8 float_overflow_error_ext(struct Node *escontext);
|
||||
extern float8 float_underflow_error_ext(struct Node *escontext);
|
||||
extern float8 float_zero_divide_error_ext(struct Node *escontext);
|
||||
extern int is_infinite(float8 val);
|
||||
extern float8 float8in_internal(char *num, char **endptr_p,
|
||||
const char *type_name, const char *orig_string,
|
||||
|
|
@ -110,17 +113,23 @@ float4_pl(const float4 val1, const float4 val2)
|
|||
}
|
||||
|
||||
static inline float8
|
||||
float8_pl(const float8 val1, const float8 val2)
|
||||
float8_pl_safe(const float8 val1, const float8 val2, struct Node *escontext)
|
||||
{
|
||||
float8 result;
|
||||
|
||||
result = val1 + val2;
|
||||
if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
|
||||
float_overflow_error();
|
||||
return float_overflow_error_ext(escontext);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline float8
|
||||
float8_pl(const float8 val1, const float8 val2)
|
||||
{
|
||||
return float8_pl_safe(val1, val2, NULL);
|
||||
}
|
||||
|
||||
static inline float4
|
||||
float4_mi(const float4 val1, const float4 val2)
|
||||
{
|
||||
|
|
@ -134,17 +143,23 @@ float4_mi(const float4 val1, const float4 val2)
|
|||
}
|
||||
|
||||
static inline float8
|
||||
float8_mi(const float8 val1, const float8 val2)
|
||||
float8_mi_safe(const float8 val1, const float8 val2, struct Node *escontext)
|
||||
{
|
||||
float8 result;
|
||||
|
||||
result = val1 - val2;
|
||||
if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
|
||||
float_overflow_error();
|
||||
return float_overflow_error_ext(escontext);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline float8
|
||||
float8_mi(const float8 val1, const float8 val2)
|
||||
{
|
||||
return float8_mi_safe(val1, val2, NULL);
|
||||
}
|
||||
|
||||
static inline float4
|
||||
float4_mul(const float4 val1, const float4 val2)
|
||||
{
|
||||
|
|
@ -160,19 +175,25 @@ float4_mul(const float4 val1, const float4 val2)
|
|||
}
|
||||
|
||||
static inline float8
|
||||
float8_mul(const float8 val1, const float8 val2)
|
||||
float8_mul_safe(const float8 val1, const float8 val2, struct Node *escontext)
|
||||
{
|
||||
float8 result;
|
||||
|
||||
result = val1 * val2;
|
||||
if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
|
||||
float_overflow_error();
|
||||
return float_overflow_error_ext(escontext);
|
||||
if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
|
||||
float_underflow_error();
|
||||
return float_underflow_error_ext(escontext);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline float8
|
||||
float8_mul(const float8 val1, const float8 val2)
|
||||
{
|
||||
return float8_mul_safe(val1, val2, NULL);
|
||||
}
|
||||
|
||||
static inline float4
|
||||
float4_div(const float4 val1, const float4 val2)
|
||||
{
|
||||
|
|
@ -190,21 +211,27 @@ float4_div(const float4 val1, const float4 val2)
|
|||
}
|
||||
|
||||
static inline float8
|
||||
float8_div(const float8 val1, const float8 val2)
|
||||
float8_div_safe(const float8 val1, const float8 val2, struct Node *escontext)
|
||||
{
|
||||
float8 result;
|
||||
|
||||
if (unlikely(val2 == 0.0) && !isnan(val1))
|
||||
float_zero_divide_error();
|
||||
return float_zero_divide_error_ext(escontext);
|
||||
result = val1 / val2;
|
||||
if (unlikely(isinf(result)) && !isinf(val1))
|
||||
float_overflow_error();
|
||||
return float_overflow_error_ext(escontext);
|
||||
if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
|
||||
float_underflow_error();
|
||||
return float_underflow_error_ext(escontext);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline float8
|
||||
float8_div(const float8 val1, const float8 val2)
|
||||
{
|
||||
return float8_div_safe(val1, val2, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Routines for NaN-aware comparisons
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in a new issue