FDL Core Library
ASC Framing Decision List — C/C++ Reference Implementation
Loading...
Searching...
No Matches
fdl_rounding.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2024-present American Society Of Cinematographers
2// SPDX-License-Identifier: Apache-2.0
10#ifndef FDL_ROUNDING_INTERNAL_H
11#define FDL_ROUNDING_INTERNAL_H
12
13#include <cmath>
14#include <cstdint>
15#include <limits>
16
17#include "fdl_constants.h"
18
19namespace fdl::detail {
20
30inline int64_t safe_to_int64(double value) {
31 // Doubles beyond int64_t range would cause UB in static_cast.
32 constexpr auto kMax = static_cast<double>(std::numeric_limits<int64_t>::max());
33 constexpr auto kMin = static_cast<double>(std::numeric_limits<int64_t>::min());
34 if (value >= kMax) {
35 return std::numeric_limits<int64_t>::max();
36 }
37 if (value <= kMin) {
38 return std::numeric_limits<int64_t>::min();
39 }
40 return static_cast<int64_t>(value);
41}
42
52inline int64_t bankers_round(double value) {
53 double rounded = std::round(value);
54 // Check if we're exactly at the halfway point
55 double const remainder = value - std::floor(value);
56 if (std::abs(remainder - constants::kHalfway) < constants::kFpHalfwayTolerance) {
57 // Halfway case: round to even
58 auto r = safe_to_int64(rounded);
59 if (r % constants::kEvenDivisor != 0) {
60 // rounded is odd, go the other way
61 rounded = std::floor(value + constants::kHalfway);
62 if (safe_to_int64(rounded) % constants::kEvenDivisor != 0) {
63 rounded = std::ceil(value - constants::kHalfway);
64 }
65 }
66 }
67 return safe_to_int64(rounded);
68}
69
70} // namespace fdl::detail
71
72#endif // FDL_ROUNDING_INTERNAL_H
Named constants replacing magic numbers throughout the FDL core library.
int64_t safe_to_int64(double value)
Safely cast a double to int64_t, clamping to [INT64_MIN, INT64_MAX].
Definition fdl_rounding.h:30
int64_t bankers_round(double value)
Banker's rounding (half-to-even), matching Python's built-in round().
Definition fdl_rounding.h:52