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:
Peter Eisentraut 2026-03-29 20:40:50 +02:00
parent d4cb9c3776
commit 45cdaf3665
3 changed files with 254 additions and 84 deletions

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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
*