File indexing completed on 2025-08-28 08:27:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #pragma once
0019
0020 #include <cstdint>
0021 #include <limits>
0022 #include <type_traits>
0023
0024 #include "arrow/status.h"
0025 #include "arrow/util/macros.h"
0026 #include "arrow/util/visibility.h"
0027
0028
0029 #include "arrow/util/windows_compatibility.h"
0030 #include "arrow/vendored/portable-snippets/safe-math.h"
0031
0032 #include "arrow/util/windows_fixup.h"
0033
0034
0035 namespace arrow {
0036 namespace internal {
0037
0038
0039
0040
0041
0042
0043 #define OP_WITH_OVERFLOW(_func_name, _psnip_op, _type, _psnip_type) \
0044 [[nodiscard]] static inline bool _func_name(_type u, _type v, _type* out) { \
0045 return !psnip_safe_##_psnip_type##_##_psnip_op(out, u, v); \
0046 }
0047
0048 #define OPS_WITH_OVERFLOW(_func_name, _psnip_op) \
0049 OP_WITH_OVERFLOW(_func_name, _psnip_op, int8_t, int8) \
0050 OP_WITH_OVERFLOW(_func_name, _psnip_op, int16_t, int16) \
0051 OP_WITH_OVERFLOW(_func_name, _psnip_op, int32_t, int32) \
0052 OP_WITH_OVERFLOW(_func_name, _psnip_op, int64_t, int64) \
0053 OP_WITH_OVERFLOW(_func_name, _psnip_op, uint8_t, uint8) \
0054 OP_WITH_OVERFLOW(_func_name, _psnip_op, uint16_t, uint16) \
0055 OP_WITH_OVERFLOW(_func_name, _psnip_op, uint32_t, uint32) \
0056 OP_WITH_OVERFLOW(_func_name, _psnip_op, uint64_t, uint64)
0057
0058 OPS_WITH_OVERFLOW(AddWithOverflow, add)
0059 OPS_WITH_OVERFLOW(SubtractWithOverflow, sub)
0060 OPS_WITH_OVERFLOW(MultiplyWithOverflow, mul)
0061 OPS_WITH_OVERFLOW(DivideWithOverflow, div)
0062
0063 #undef OP_WITH_OVERFLOW
0064 #undef OPS_WITH_OVERFLOW
0065
0066
0067
0068
0069
0070
0071 #define UNARY_OP_WITH_OVERFLOW(_func_name, _psnip_op, _type, _psnip_type) \
0072 [[nodiscard]] static inline bool _func_name(_type u, _type* out) { \
0073 return !psnip_safe_##_psnip_type##_##_psnip_op(out, u); \
0074 }
0075
0076 #define SIGNED_UNARY_OPS_WITH_OVERFLOW(_func_name, _psnip_op) \
0077 UNARY_OP_WITH_OVERFLOW(_func_name, _psnip_op, int8_t, int8) \
0078 UNARY_OP_WITH_OVERFLOW(_func_name, _psnip_op, int16_t, int16) \
0079 UNARY_OP_WITH_OVERFLOW(_func_name, _psnip_op, int32_t, int32) \
0080 UNARY_OP_WITH_OVERFLOW(_func_name, _psnip_op, int64_t, int64)
0081
0082 SIGNED_UNARY_OPS_WITH_OVERFLOW(NegateWithOverflow, neg)
0083
0084 #undef UNARY_OP_WITH_OVERFLOW
0085 #undef SIGNED_UNARY_OPS_WITH_OVERFLOW
0086
0087
0088 template <typename SignedInt>
0089 SignedInt SafeSignedAdd(SignedInt u, SignedInt v) {
0090 using UnsignedInt = typename std::make_unsigned<SignedInt>::type;
0091 return static_cast<SignedInt>(static_cast<UnsignedInt>(u) +
0092 static_cast<UnsignedInt>(v));
0093 }
0094
0095
0096 template <typename SignedInt>
0097 SignedInt SafeSignedSubtract(SignedInt u, SignedInt v) {
0098 using UnsignedInt = typename std::make_unsigned<SignedInt>::type;
0099 return static_cast<SignedInt>(static_cast<UnsignedInt>(u) -
0100 static_cast<UnsignedInt>(v));
0101 }
0102
0103
0104 template <typename SignedInt>
0105 SignedInt SafeSignedNegate(SignedInt u) {
0106 using UnsignedInt = typename std::make_unsigned<SignedInt>::type;
0107 return static_cast<SignedInt>(~static_cast<UnsignedInt>(u) + 1);
0108 }
0109
0110
0111 template <typename SignedInt, typename Shift>
0112 SignedInt SafeLeftShift(SignedInt u, Shift shift) {
0113 using UnsignedInt = typename std::make_unsigned<SignedInt>::type;
0114 return static_cast<SignedInt>(static_cast<UnsignedInt>(u) << shift);
0115 }
0116
0117 }
0118 }