| 1 | #include "duckdb/main/capi/capi_internal.hpp" |
| 2 | #include "duckdb/common/types/hugeint.hpp" |
| 3 | #include "duckdb/common/types/decimal.hpp" |
| 4 | #include "duckdb/common/operator/decimal_cast_operators.hpp" |
| 5 | #include "duckdb/main/capi/cast/utils.hpp" |
| 6 | #include "duckdb/main/capi/cast/to_decimal.hpp" |
| 7 | |
| 8 | using duckdb::Hugeint; |
| 9 | using duckdb::hugeint_t; |
| 10 | using duckdb::Value; |
| 11 | |
| 12 | double duckdb_hugeint_to_double(duckdb_hugeint val) { |
| 13 | hugeint_t internal; |
| 14 | internal.lower = val.lower; |
| 15 | internal.upper = val.upper; |
| 16 | return Hugeint::Cast<double>(input: internal); |
| 17 | } |
| 18 | |
| 19 | static duckdb_decimal to_decimal_cast(double val, uint8_t width, uint8_t scale) { |
| 20 | if (width > duckdb::Decimal::MAX_WIDTH_INT64) { |
| 21 | return duckdb::TryCastToDecimalCInternal<double, duckdb::ToCDecimalCastWrapper<hugeint_t>>(source: val, width, scale); |
| 22 | } |
| 23 | if (width > duckdb::Decimal::MAX_WIDTH_INT32) { |
| 24 | return duckdb::TryCastToDecimalCInternal<double, duckdb::ToCDecimalCastWrapper<int64_t>>(source: val, width, scale); |
| 25 | } |
| 26 | if (width > duckdb::Decimal::MAX_WIDTH_INT16) { |
| 27 | return duckdb::TryCastToDecimalCInternal<double, duckdb::ToCDecimalCastWrapper<int32_t>>(source: val, width, scale); |
| 28 | } |
| 29 | return duckdb::TryCastToDecimalCInternal<double, duckdb::ToCDecimalCastWrapper<int16_t>>(source: val, width, scale); |
| 30 | } |
| 31 | |
| 32 | duckdb_decimal duckdb_double_to_decimal(double val, uint8_t width, uint8_t scale) { |
| 33 | if (scale > width || width > duckdb::Decimal::MAX_WIDTH_INT128) { |
| 34 | return duckdb::FetchDefaultValue::Operation<duckdb_decimal>(); |
| 35 | } |
| 36 | return to_decimal_cast(val, width, scale); |
| 37 | } |
| 38 | |
| 39 | duckdb_hugeint duckdb_double_to_hugeint(double val) { |
| 40 | hugeint_t internal_result; |
| 41 | if (!Value::DoubleIsFinite(value: val) || !Hugeint::TryConvert<double>(value: val, result&: internal_result)) { |
| 42 | internal_result.lower = 0; |
| 43 | internal_result.upper = 0; |
| 44 | } |
| 45 | |
| 46 | duckdb_hugeint result; |
| 47 | result.lower = internal_result.lower; |
| 48 | result.upper = internal_result.upper; |
| 49 | return result; |
| 50 | } |
| 51 | |
| 52 | double duckdb_decimal_to_double(duckdb_decimal val) { |
| 53 | double result; |
| 54 | hugeint_t value; |
| 55 | value.lower = val.value.lower; |
| 56 | value.upper = val.value.upper; |
| 57 | duckdb::TryCastFromDecimal::Operation<hugeint_t, double>(input: value, result, error_message: nullptr, width: val.width, scale: val.scale); |
| 58 | return result; |
| 59 | } |
| 60 | |