| 80 | */ |
| 81 | template <typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type> |
| 82 | inline T round_half_even(T value, T epsilon = std::numeric_limits<T>::epsilon()) |
| 83 | { |
| 84 | T positive_value = std::abs(value); |
| 85 | T ipart = 0; |
| 86 | std::modf(positive_value, &ipart); |
| 87 | // If 'value' is exactly halfway between two integers |
| 88 | if (std::abs(positive_value - (ipart + 0.5f)) < epsilon) |
| 89 | { |
| 90 | // If 'ipart' is even then return 'ipart' |
| 91 | if (std::fmod(ipart, 2.f) < epsilon) |
| 92 | { |
| 93 | return support::cpp11::copysign(ipart, value); |
| 94 | } |
| 95 | // Else return the nearest even integer |
| 96 | return support::cpp11::copysign(std::ceil(ipart + 0.5f), value); |
| 97 | } |
| 98 | // Otherwise use the usual round to closest |
| 99 | return support::cpp11::copysign(support::cpp11::round(positive_value), value); |
| 100 | } |
| 101 | |
| 102 | namespace traits |
| 103 | { |