1570af302Sopenharmony_ci#include "libm.h"
2570af302Sopenharmony_ci
3570af302Sopenharmony_ci#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1
4570af302Sopenharmony_ci#define EPS DBL_EPSILON
5570af302Sopenharmony_ci#elif FLT_EVAL_METHOD==2
6570af302Sopenharmony_ci#define EPS LDBL_EPSILON
7570af302Sopenharmony_ci#endif
8570af302Sopenharmony_cistatic const double_t toint = 1/EPS;
9570af302Sopenharmony_ci
10570af302Sopenharmony_cidouble round(double x)
11570af302Sopenharmony_ci{
12570af302Sopenharmony_ci	union {double f; uint64_t i;} u = {x};
13570af302Sopenharmony_ci	int e = u.i >> 52 & 0x7ff;
14570af302Sopenharmony_ci	double_t y;
15570af302Sopenharmony_ci
16570af302Sopenharmony_ci	if (e >= 0x3ff+52)
17570af302Sopenharmony_ci		return x;
18570af302Sopenharmony_ci	if (u.i >> 63)
19570af302Sopenharmony_ci		x = -x;
20570af302Sopenharmony_ci	if (e < 0x3ff-1) {
21570af302Sopenharmony_ci		/* raise inexact if x!=0 */
22570af302Sopenharmony_ci		FORCE_EVAL(x + toint);
23570af302Sopenharmony_ci		return 0*u.f;
24570af302Sopenharmony_ci	}
25570af302Sopenharmony_ci	y = x + toint - toint - x;
26570af302Sopenharmony_ci	if (y > 0.5)
27570af302Sopenharmony_ci		y = y + x - 1;
28570af302Sopenharmony_ci	else if (y <= -0.5)
29570af302Sopenharmony_ci		y = y + x + 1;
30570af302Sopenharmony_ci	else
31570af302Sopenharmony_ci		y = y + x;
32570af302Sopenharmony_ci	if (u.i >> 63)
33570af302Sopenharmony_ci		y = -y;
34570af302Sopenharmony_ci	return y;
35570af302Sopenharmony_ci}
36