Legend: ------- * = endpoint is included in range o = endpoint is excluded in range On intel SSE, there exists a CVTSD2SI insruction with rounding mode controllable using the MXCSR register. k are numbers in the set of all integers. Rounding to Nearest Integer (Symmetric Arithmetic Rounding) C++: floor(x+0.5), except when x=0.49999... [see JDK bug below] feature: almost ideal rounding, except for bias at k+0.5 where k is integer feature: this is probably what you learned in elementary school feature: symmetric about the origin Intel x64: not possible in single instruction, they prefer to use round to closest even ARM AArch64: FCVTAS round to nearest with ties to away ------------------------------------- rint(x) | | 3.0 + *=====o | | 2.0 + *=====o | | 1.0 + *=====o | | .--+--.--+--.--+--o=====o--+--.--+--.--+--. x -3.0 -2.0 -1.0 | 1.0 2.0 3.0 | o=====* + -1.0 | | o=====* + -2.0 | | o=====* + -3.0 | | Intel x87's Round to Closest (Nearest) Even Integer Also known as Banker's Rounding feature: default starting mode in Win32 apps feature: ideal rounding from a numerical perspective feature: MS DirectX uses this mode, along with single precision mode feature: almost the same as ideal rounding except at 0.5+k points where k is an integer. C++: difficult to implement correctly without relying on platform-specific behavior (see notes at the end) ARM NEON: int32x2_t vcvt_s32_f32(float32x2_t a); // VCVT.S32.F32 d0, d0 intel x64: _mm_round_sd(x, _MM_FROUND_TO_NEAREST_INT) ARM AArch64: FCVTNS ------------------------------------------------------------------ rint_even(x) | | 3.0 + o====o | | 2.0 + *=====* | | 1.0 + o=====o | | .--+--.--+--.--+--*=====*--+--.--+--.--+--. x -3.0 -2.0 -1.0 | 1.0 2.0 3.0 | o=====o + -1.0 | | *=====* -2.0 + | | o=====o -3.0 + | | Rounding to Nearest Integer, but biased towards positive infinity feature: easy to implement using floor feature: for integer arguments, use add and shift right C++: rint_pos(x) = floor(x+0.5), except when x= k + 0.49999... intel x64: _mm_round_sd(x, _MM_FROUND_TO_POS_INF) ARM AArch64: ??? -------------------------------------------------------------------- rint_pos(x) | | 3.0 + *=====o | | 2.0 + *=====o | | 1.0 + *=====o | | .--+--.--+--.--+--*=====o--+--.--+--.--+--. x -3.0 -2.0 -1.0 | 1.0 2.0 3.0 | *=====o + -1.0 | | *=====o + -2.0 | | *=====o + -3.0 | | Round Towards Zero (chop, fix, truncation) feature: default rounding mode in ANSI C C++: (int)x feature: toward minus infinity for positive numbers, toward positive infinity for negative numbers feature: has a larger deadzone at zero intel: Intel SSE3 has a FISTTP instruction for this. intel x64: _mm_round_sd(x, _MM_FROUND_TO_ZERO) ARM AArch64: FCVTZS -------------------------------------------------------- int_cast(x) | | 3.0 + | | 2.0 + *=====o | | 1.0 + *=====o | | .--+--.--+--.--o==.=====.==o--.--+--.--+--. x -3.0 -2.0 -1.0 | 1.0 2.0 3.0 | o=====* + -1.0 | | o====* -2.0 + | | -3.0 + | | Round towards Minus Infinity (floor) feature: for integer or fixed point arguments, this is easy in hardware (use arithmetic shift right) C++: floor(x) intel x64: _mm_round_sd(x, _MM_FROUND_TO_NEG_INF)? ARM AArch64: FCVTMS? -------------------------------------------------------------- floor(x) | | 3.0 + | | 2.0 + *=====o | | 1.0 + *=====o | | .--+--.--+--.--+--.--*=====o--.--+--.--+--. x -3.0 -2.0 -1.0 | 1.0 2.0 3.0 | *=====o -1.0 | | *=====o + -2.0 | | *=====o -3.0 + | | Ceiling (ceil) C++: ceil(x) = -floor(-x) feature: almost the mirror image of floor(x) intel x64: _mm_round_sd(x, _MM_FROUND_TO_POS_INF) ARM AArch64: FCVTPS(x) ---------------------------------------- ceil(x) | | 3.0 + o=====* | | 2.0 + o=====* | | 1.0 o=====* | | .--+--.--+--.--o==.==*--.--+--.--+--.--+--. x -3.0 -2.0 -1.0 | 1.0 2.0 3.0 | o=====* + -1.0 | | o====* -2.0 + | | -3.0 + | |General information on: Custom Rounding.
More information on: Speed Optimizations.
Pentium rounding unsignaled overflow bug documented at: Microsoft
More about C99 rounding modes at FreeBSD mailing list
It turns out that floor(x+0.5) is not equal to round(x) when x=0.4999...
... This was the cause of this Java JDK bug.
More information on rounding bugs are at here.