Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-compute/src/cast/decimal_to.rs
8446 views
1
use arrow::array::*;
2
use arrow::datatypes::ArrowDataType;
3
use arrow::types::NativeType;
4
use num_traits::{AsPrimitive, Float, NumCast};
5
use polars_error::PolarsResult;
6
7
use crate::decimal::{dec128_fits, dec128_rescale, dec128_to_f64, dec128_to_i128};
8
9
/// Returns a [`PrimitiveArray<i128>`] with the cast values. Values become null on overflow.
10
pub fn decimal_to_decimal(
11
from: &PrimitiveArray<i128>,
12
to_precision: usize,
13
to_scale: usize,
14
) -> PrimitiveArray<i128> {
15
let (from_precision, from_scale) =
16
if let ArrowDataType::Decimal(p, s) = from.dtype().to_storage() {
17
(*p, *s)
18
} else {
19
panic!("internal error: i128 is always a decimal")
20
};
21
22
if to_scale == from_scale {
23
if to_precision >= from_precision {
24
// Increasing precision is always allowed.
25
return from
26
.clone()
27
.to(ArrowDataType::Decimal(to_precision, to_scale));
28
} else {
29
let it = from
30
.iter()
31
.map(|opt_x| opt_x.copied().filter(|x| dec128_fits(*x, to_precision)));
32
return PrimitiveArray::<i128>::from_trusted_len_iter(it)
33
.to(ArrowDataType::Decimal(to_precision, to_scale));
34
}
35
}
36
37
let it = from
38
.iter()
39
.map(|opt_x| dec128_rescale(*(opt_x?), from_scale, to_precision, to_scale));
40
PrimitiveArray::<i128>::from_trusted_len_iter(it)
41
.to(ArrowDataType::Decimal(to_precision, to_scale))
42
}
43
44
pub(super) fn decimal_to_decimal_dyn(
45
from: &dyn Array,
46
to_precision: usize,
47
to_scale: usize,
48
) -> PolarsResult<Box<dyn Array>> {
49
let from = from.as_any().downcast_ref().unwrap();
50
Ok(Box::new(decimal_to_decimal(from, to_precision, to_scale)))
51
}
52
53
/// Returns a [`PrimitiveArray<i128>`] with the cast values. Values are `None` on overflow
54
pub fn decimal_to_float<T>(from: &PrimitiveArray<i128>) -> PrimitiveArray<T>
55
where
56
T: NativeType + Float,
57
f64: AsPrimitive<T>,
58
{
59
let (_, from_scale) = if let ArrowDataType::Decimal(p, s) = from.dtype().to_storage() {
60
(*p, *s)
61
} else {
62
unreachable!()
63
};
64
65
let it = from
66
.iter()
67
.map(|opt_x| Some(dec128_to_f64(*(opt_x?), from_scale).as_()));
68
PrimitiveArray::<T>::from_trusted_len_iter(it)
69
}
70
71
pub(super) fn decimal_to_float_dyn<T>(from: &dyn Array) -> PolarsResult<Box<dyn Array>>
72
where
73
T: NativeType + Float,
74
f64: AsPrimitive<T>,
75
{
76
let from = from.as_any().downcast_ref().unwrap();
77
Ok(Box::new(decimal_to_float::<T>(from)))
78
}
79
80
/// Returns a [`PrimitiveArray<i128>`] with the cast values. Values are `None` on overflow
81
pub fn decimal_to_integer<T>(from: &PrimitiveArray<i128>) -> PrimitiveArray<T>
82
where
83
T: NativeType + NumCast,
84
{
85
let (_, from_scale) = if let ArrowDataType::Decimal(p, s) = from.dtype().to_storage() {
86
(*p, *s)
87
} else {
88
unreachable!()
89
};
90
91
let it = from
92
.iter()
93
.map(|opt_x| T::from(dec128_to_i128(*(opt_x?), from_scale)));
94
PrimitiveArray::<T>::from_trusted_len_iter(it)
95
}
96
97
pub(super) fn decimal_to_integer_dyn<T>(from: &dyn Array) -> PolarsResult<Box<dyn Array>>
98
where
99
T: NativeType + NumCast,
100
{
101
let from = from.as_any().downcast_ref().unwrap();
102
Ok(Box::new(decimal_to_integer::<T>(from)))
103
}
104
105
/// Returns a [`Utf8Array`] where every element is the utf8 representation of the decimal.
106
#[cfg(feature = "dtype-decimal")]
107
pub(super) fn decimal_to_utf8view(from: &PrimitiveArray<i128>) -> Utf8ViewArray {
108
use crate::decimal::DecimalFmtBuffer;
109
110
let (_, from_scale) = if let ArrowDataType::Decimal(p, s) = from.dtype().to_storage() {
111
(*p, *s)
112
} else {
113
unreachable!()
114
};
115
116
let mut mutable = MutableBinaryViewArray::with_capacity(from.len());
117
let mut fmt_buf = DecimalFmtBuffer::new();
118
for &x in from.values().iter() {
119
mutable.push_value_ignore_validity(fmt_buf.format_dec128(x, from_scale, false, false))
120
}
121
122
mutable.freeze().with_validity(from.validity().cloned())
123
}
124
125
#[cfg(feature = "dtype-decimal")]
126
pub(super) fn decimal_to_utf8view_dyn(from: &dyn Array) -> Utf8ViewArray {
127
let from = from.as_any().downcast_ref().unwrap();
128
decimal_to_utf8view(from)
129
}
130
131