diff options
| author | imunkin <[email protected]> | 2024-11-08 10:00:23 +0300 |
|---|---|---|
| committer | imunkin <[email protected]> | 2024-11-08 10:12:13 +0300 |
| commit | a784a2f943d6e15caa6241e2e96d80aac6dbf375 (patch) | |
| tree | 05f1e5366c916b988a8afb75bdab8ddeee0f6e6d /yql/essentials/udfs/common/math/lib/round.h | |
| parent | d70137a7b530ccaa52834274913bbb5a3d1ca06e (diff) | |
Move yql/udfs/common/ to /yql/essentials YQL-19206
Except the following directories:
* clickhouse/client
* datetime
* knn
* roaring
commit_hash:c7da95636144d28db109d6b17ddc762e9bacb59f
Diffstat (limited to 'yql/essentials/udfs/common/math/lib/round.h')
| -rw-r--r-- | yql/essentials/udfs/common/math/lib/round.h | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/yql/essentials/udfs/common/math/lib/round.h b/yql/essentials/udfs/common/math/lib/round.h new file mode 100644 index 00000000000..f59700da88f --- /dev/null +++ b/yql/essentials/udfs/common/math/lib/round.h @@ -0,0 +1,77 @@ +#pragma once + +#include <util/system/types.h> +#include <cmath> +#include <optional> +#include <fenv.h> + +namespace NMathUdf { + +template <class T> +inline T RoundToDecimal(T v, int decShift) { + T div = std::pow(T(10), decShift); + return std::floor(v / div + T(0.5)) * div; +} + +inline std::optional<i64> Mod(i64 value, i64 m) { + if (!m) { + return {}; + } + + const i64 result = value % m; + if ((result < 0 && m > 0) || (result > 0 && m < 0)) { + return result + m; + } + return result; +} + +inline std::optional<i64> Rem(i64 value, i64 m) { + if (!m) { + return {}; + } + + const i64 result = value % m; + if (result < 0 && value > 0) { + return result + m; + } + + if (result > 0 && value < 0) { + return result - m; + } + return result; +} + +inline std::optional<i64> NearbyIntImpl(double value, decltype(FE_DOWNWARD) mode) { + if (!::isfinite(value)) { + return {}; + } + + auto prevMode = ::fegetround(); + ::fesetround(mode); + auto res = ::nearbyint(value); + ::fesetround(prevMode); + // cast to i64 gives wrong sign above 9223372036854774784 + // lower bound is adjusted to -9223372036854774784 as well + if (res < double(std::numeric_limits<i64>::min() + 513) || res > double(std::numeric_limits<i64>::max() - 512)) { + return {}; + } + + return static_cast<i64>(res); +} + +inline std::optional<i64> NearbyInt(double value, ui32 mode) { + switch (mode) { + case 0: + return NearbyIntImpl(value, FE_DOWNWARD); + case 1: + return NearbyIntImpl(value, FE_TONEAREST); + case 2: + return NearbyIntImpl(value, FE_TOWARDZERO); + case 3: + return NearbyIntImpl(value, FE_UPWARD); + default: + return {}; + } +} + +} |
