File indexing completed on 2025-08-28 08:27:08
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 <iosfwd>
0022 #include <limits>
0023 #include <string>
0024 #include <string_view>
0025 #include <utility>
0026
0027 #include "arrow/result.h"
0028 #include "arrow/status.h"
0029 #include "arrow/type_fwd.h"
0030 #include "arrow/util/basic_decimal.h"
0031
0032 namespace arrow {
0033
0034 class Decimal64;
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 class ARROW_EXPORT Decimal32 : public BasicDecimal32 {
0049 public:
0050
0051
0052 using BasicDecimal32::BasicDecimal32;
0053
0054
0055
0056 constexpr Decimal32(const BasicDecimal32& value) noexcept
0057 : BasicDecimal32(value) {}
0058
0059
0060 explicit Decimal32(const std::string& value);
0061
0062
0063
0064 constexpr Decimal32() noexcept : BasicDecimal32() {}
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 Result<std::pair<Decimal32, Decimal32>> Divide(const Decimal32& divisor) const {
0077 std::pair<Decimal32, Decimal32> result;
0078 auto dstatus = BasicDecimal32::Divide(divisor, &result.first, &result.second);
0079 ARROW_RETURN_NOT_OK(ToArrowStatus(dstatus));
0080 return result;
0081 }
0082
0083
0084 std::string ToString(int32_t scale) const;
0085
0086
0087 std::string ToIntegerString() const;
0088
0089
0090 explicit operator int64_t() const;
0091
0092 explicit operator Decimal64() const;
0093
0094
0095
0096 static Status FromString(std::string_view s, Decimal32* out, int32_t* precision,
0097 int32_t* scale = NULLPTR);
0098 static Status FromString(const std::string& s, Decimal32* out, int32_t* precision,
0099 int32_t* scale = NULLPTR);
0100 static Status FromString(const char* s, Decimal32* out, int32_t* precision,
0101 int32_t* scale = NULLPTR);
0102 static Result<Decimal32> FromString(std::string_view s);
0103 static Result<Decimal32> FromString(const std::string& s);
0104 static Result<Decimal32> FromString(const char* s);
0105
0106 static Result<Decimal32> FromReal(double real, int32_t precision, int32_t scale);
0107 static Result<Decimal32> FromReal(float real, int32_t precision, int32_t scale);
0108
0109
0110
0111
0112 static Result<Decimal32> FromBigEndian(const uint8_t* data, int32_t length);
0113
0114
0115 Result<Decimal32> Rescale(int32_t original_scale, int32_t new_scale) const {
0116 Decimal32 out;
0117 auto dstatus = BasicDecimal32::Rescale(original_scale, new_scale, &out);
0118 ARROW_RETURN_NOT_OK(ToArrowStatus(dstatus));
0119 return out;
0120 }
0121
0122
0123 template <typename T, typename = internal::EnableIfIsOneOf<T, int32_t, int64_t>>
0124 Result<T> ToInteger() const {
0125 return static_cast<T>(value_);
0126 }
0127
0128
0129 template <typename T, typename = internal::EnableIfIsOneOf<T, int32_t, int64_t>>
0130 Status ToInteger(T* out) const {
0131 return ToInteger<T>().Value(out);
0132 }
0133
0134
0135 float ToFloat(int32_t scale) const;
0136
0137 double ToDouble(int32_t scale) const;
0138
0139
0140 template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
0141 T ToReal(int32_t scale) const {
0142 static_assert(std::is_same_v<T, float> || std::is_same_v<T, double>,
0143 "Unexpected floating-point type");
0144 if constexpr (std::is_same_v<T, float>) {
0145 return ToFloat(scale);
0146 } else {
0147 return ToDouble(scale);
0148 }
0149 }
0150
0151 ARROW_FRIEND_EXPORT friend std::ostream& operator<<(std::ostream& os,
0152 const Decimal32& decimal);
0153
0154 private:
0155
0156 Status ToArrowStatus(DecimalStatus dstatus) const;
0157 };
0158
0159 class ARROW_EXPORT Decimal64 : public BasicDecimal64 {
0160 public:
0161
0162
0163 using BasicDecimal64::BasicDecimal64;
0164
0165
0166
0167 constexpr Decimal64(const BasicDecimal64& value) noexcept
0168 : BasicDecimal64(value) {}
0169
0170 explicit Decimal64(const BasicDecimal32& value) noexcept
0171 : BasicDecimal64(static_cast<int64_t>(value.value())) {}
0172
0173
0174 explicit Decimal64(const std::string& value);
0175
0176
0177
0178 constexpr Decimal64() noexcept : BasicDecimal64() {}
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190 Result<std::pair<Decimal64, Decimal64>> Divide(const Decimal64& divisor) const {
0191 std::pair<Decimal64, Decimal64> result;
0192 auto dstatus = BasicDecimal64::Divide(divisor, &result.first, &result.second);
0193 ARROW_RETURN_NOT_OK(ToArrowStatus(dstatus));
0194 return result;
0195 }
0196
0197
0198 std::string ToString(int32_t scale) const;
0199
0200
0201 std::string ToIntegerString() const;
0202
0203
0204 explicit operator int64_t() const;
0205
0206
0207
0208 static Status FromString(std::string_view s, Decimal64* out, int32_t* precision,
0209 int32_t* scale = NULLPTR);
0210 static Status FromString(const std::string& s, Decimal64* out, int32_t* precision,
0211 int32_t* scale = NULLPTR);
0212 static Status FromString(const char* s, Decimal64* out, int32_t* precision,
0213 int32_t* scale = NULLPTR);
0214 static Result<Decimal64> FromString(std::string_view s);
0215 static Result<Decimal64> FromString(const std::string& s);
0216 static Result<Decimal64> FromString(const char* s);
0217
0218 static Result<Decimal64> FromReal(double real, int32_t precision, int32_t scale);
0219 static Result<Decimal64> FromReal(float real, int32_t precision, int32_t scale);
0220
0221
0222
0223
0224 static Result<Decimal64> FromBigEndian(const uint8_t* data, int32_t length);
0225
0226
0227 Result<Decimal64> Rescale(int32_t original_scale, int32_t new_scale) const {
0228 Decimal64 out;
0229 auto dstatus = BasicDecimal64::Rescale(original_scale, new_scale, &out);
0230 ARROW_RETURN_NOT_OK(ToArrowStatus(dstatus));
0231 return out;
0232 }
0233
0234
0235 template <typename T, typename = internal::EnableIfIsOneOf<T, int32_t, int64_t>>
0236 Result<T> ToInteger() const {
0237 return static_cast<T>(value_);
0238 }
0239
0240
0241 template <typename T, typename = internal::EnableIfIsOneOf<T, int32_t, int64_t>>
0242 Status ToInteger(T* out) const {
0243 return ToInteger<T>().Value(out);
0244 }
0245
0246
0247 float ToFloat(int32_t scale) const;
0248
0249 double ToDouble(int32_t scale) const;
0250
0251
0252 template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
0253 T ToReal(int32_t scale) const {
0254 static_assert(std::is_same_v<T, float> || std::is_same_v<T, double>,
0255 "Unexpected floating-point type");
0256 if constexpr (std::is_same_v<T, float>) {
0257 return ToFloat(scale);
0258 } else {
0259 return ToDouble(scale);
0260 }
0261 }
0262
0263 ARROW_FRIEND_EXPORT friend std::ostream& operator<<(std::ostream& os,
0264 const Decimal64& decimal);
0265
0266 private:
0267
0268 Status ToArrowStatus(DecimalStatus dstatus) const;
0269 };
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288 class ARROW_EXPORT Decimal128 : public BasicDecimal128 {
0289 public:
0290
0291
0292 using BasicDecimal128::BasicDecimal128;
0293
0294
0295
0296 constexpr Decimal128(const BasicDecimal128& value) noexcept
0297 : BasicDecimal128(value) {}
0298
0299
0300 explicit Decimal128(const std::string& value);
0301
0302
0303
0304 constexpr Decimal128() noexcept : BasicDecimal128() {}
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316 Result<std::pair<Decimal128, Decimal128>> Divide(const Decimal128& divisor) const {
0317 std::pair<Decimal128, Decimal128> result;
0318 auto dstatus = BasicDecimal128::Divide(divisor, &result.first, &result.second);
0319 ARROW_RETURN_NOT_OK(ToArrowStatus(dstatus));
0320 return result;
0321 }
0322
0323
0324
0325 std::string ToString(int32_t scale) const;
0326
0327
0328 std::string ToIntegerString() const;
0329
0330
0331 explicit operator int64_t() const;
0332
0333
0334
0335 static Status FromString(std::string_view s, Decimal128* out, int32_t* precision,
0336 int32_t* scale = NULLPTR);
0337 static Status FromString(const std::string& s, Decimal128* out, int32_t* precision,
0338 int32_t* scale = NULLPTR);
0339 static Status FromString(const char* s, Decimal128* out, int32_t* precision,
0340 int32_t* scale = NULLPTR);
0341 static Result<Decimal128> FromString(std::string_view s);
0342 static Result<Decimal128> FromString(const std::string& s);
0343 static Result<Decimal128> FromString(const char* s);
0344
0345 static Result<Decimal128> FromReal(double real, int32_t precision, int32_t scale);
0346 static Result<Decimal128> FromReal(float real, int32_t precision, int32_t scale);
0347
0348
0349
0350
0351 static Result<Decimal128> FromBigEndian(const uint8_t* data, int32_t length);
0352
0353
0354 Result<Decimal128> Rescale(int32_t original_scale, int32_t new_scale) const {
0355 Decimal128 out;
0356 auto dstatus = BasicDecimal128::Rescale(original_scale, new_scale, &out);
0357 ARROW_RETURN_NOT_OK(ToArrowStatus(dstatus));
0358 return out;
0359 }
0360
0361
0362 template <typename T, typename = internal::EnableIfIsOneOf<T, int32_t, int64_t>>
0363 Result<T> ToInteger() const {
0364 constexpr auto min_value = std::numeric_limits<T>::min();
0365 constexpr auto max_value = std::numeric_limits<T>::max();
0366 const auto& self = *this;
0367 if (self < min_value || self > max_value) {
0368 return Status::Invalid("Invalid cast from Decimal128 to ", sizeof(T),
0369 " byte integer");
0370 }
0371 return static_cast<T>(low_bits());
0372 }
0373
0374
0375 template <typename T, typename = internal::EnableIfIsOneOf<T, int32_t, int64_t>>
0376 Status ToInteger(T* out) const {
0377 return ToInteger<T>().Value(out);
0378 }
0379
0380
0381 float ToFloat(int32_t scale) const;
0382
0383 double ToDouble(int32_t scale) const;
0384
0385
0386 template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
0387 T ToReal(int32_t scale) const {
0388 static_assert(std::is_same_v<T, float> || std::is_same_v<T, double>,
0389 "Unexpected floating-point type");
0390 if constexpr (std::is_same_v<T, float>) {
0391 return ToFloat(scale);
0392 } else {
0393 return ToDouble(scale);
0394 }
0395 }
0396
0397 ARROW_FRIEND_EXPORT friend std::ostream& operator<<(std::ostream& os,
0398 const Decimal128& decimal);
0399
0400 private:
0401
0402 Status ToArrowStatus(DecimalStatus dstatus) const;
0403 };
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416 class ARROW_EXPORT Decimal256 : public BasicDecimal256 {
0417 public:
0418
0419
0420 using BasicDecimal256::BasicDecimal256;
0421
0422
0423
0424 constexpr Decimal256(const BasicDecimal256& value) noexcept
0425 : BasicDecimal256(value) {}
0426
0427
0428 explicit Decimal256(const std::string& value);
0429
0430
0431
0432 constexpr Decimal256() noexcept : BasicDecimal256() {}
0433
0434
0435
0436 std::string ToString(int32_t scale) const;
0437
0438
0439 std::string ToIntegerString() const;
0440
0441
0442
0443 static Status FromString(std::string_view s, Decimal256* out, int32_t* precision,
0444 int32_t* scale = NULLPTR);
0445 static Status FromString(const std::string& s, Decimal256* out, int32_t* precision,
0446 int32_t* scale = NULLPTR);
0447 static Status FromString(const char* s, Decimal256* out, int32_t* precision,
0448 int32_t* scale = NULLPTR);
0449 static Result<Decimal256> FromString(std::string_view s);
0450 static Result<Decimal256> FromString(const std::string& s);
0451 static Result<Decimal256> FromString(const char* s);
0452
0453
0454 Result<Decimal256> Rescale(int32_t original_scale, int32_t new_scale) const {
0455 Decimal256 out;
0456 auto dstatus = BasicDecimal256::Rescale(original_scale, new_scale, &out);
0457 ARROW_RETURN_NOT_OK(ToArrowStatus(dstatus));
0458 return out;
0459 }
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471 Result<std::pair<Decimal256, Decimal256>> Divide(const Decimal256& divisor) const {
0472 std::pair<Decimal256, Decimal256> result;
0473 auto dstatus = BasicDecimal256::Divide(divisor, &result.first, &result.second);
0474 ARROW_RETURN_NOT_OK(ToArrowStatus(dstatus));
0475 return result;
0476 }
0477
0478
0479
0480
0481 static Result<Decimal256> FromBigEndian(const uint8_t* data, int32_t length);
0482
0483 static Result<Decimal256> FromReal(double real, int32_t precision, int32_t scale);
0484 static Result<Decimal256> FromReal(float real, int32_t precision, int32_t scale);
0485
0486
0487
0488 float ToFloat(int32_t scale) const;
0489
0490 double ToDouble(int32_t scale) const;
0491
0492
0493 template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
0494 T ToReal(int32_t scale) const {
0495 static_assert(std::is_same_v<T, float> || std::is_same_v<T, double>,
0496 "Unexpected floating-point type");
0497 if constexpr (std::is_same_v<T, float>) {
0498 return ToFloat(scale);
0499 } else {
0500 return ToDouble(scale);
0501 }
0502 }
0503
0504 ARROW_FRIEND_EXPORT friend std::ostream& operator<<(std::ostream& os,
0505 const Decimal256& decimal);
0506
0507 private:
0508
0509 Status ToArrowStatus(DecimalStatus dstatus) const;
0510 };
0511
0512
0513
0514 inline Result<int32_t> MaxDecimalDigitsForInteger(Type::type type_id) {
0515 switch (type_id) {
0516 case Type::INT8:
0517 case Type::UINT8:
0518 return 3;
0519 case Type::INT16:
0520 case Type::UINT16:
0521 return 5;
0522 case Type::INT32:
0523 case Type::UINT32:
0524 return 10;
0525 case Type::INT64:
0526 return 19;
0527 case Type::UINT64:
0528 return 20;
0529 default:
0530 break;
0531 }
0532 return Status::Invalid("Not an integer type: ", type_id);
0533 }
0534
0535 }