|
15 | 15 | // specific language governing permissions and limitations
|
16 | 16 | // under the License.
|
17 | 17 |
|
| 18 | +use crate::conversion_funcs::schubfach; |
18 | 19 | use crate::timezone;
|
19 | 20 | use crate::utils::array_with_timezone;
|
20 | 21 | use crate::{EvalMode, SparkError, SparkResult};
|
@@ -49,6 +50,7 @@ use num::{
|
49 | 50 | ToPrimitive,
|
50 | 51 | };
|
51 | 52 | use regex::Regex;
|
| 53 | +use std::num::Saturating; |
52 | 54 | use std::str::FromStr;
|
53 | 55 | use std::{
|
54 | 56 | any::Any,
|
@@ -1278,17 +1280,29 @@ where
|
1278 | 1280 | let input = array.as_any().downcast_ref::<PrimitiveArray<T>>().unwrap();
|
1279 | 1281 | let mut cast_array = PrimitiveArray::<Decimal128Type>::builder(input.len());
|
1280 | 1282 |
|
1281 |
| - let mul = 10_f64.powi(scale as i32); |
1282 |
| - |
1283 | 1283 | for i in 0..input.len() {
|
1284 | 1284 | if input.is_null(i) {
|
1285 | 1285 | cast_array.append_null();
|
1286 | 1286 | } else {
|
1287 | 1287 | let input_value = input.value(i).as_();
|
1288 |
| - let value = (input_value * mul).round().to_i128(); |
| 1288 | + let value = schubfach::to_decimal(input_value); |
1289 | 1289 |
|
1290 | 1290 | match value {
|
1291 |
| - Some(v) => { |
| 1291 | + Some((significand, exponent)) => { |
| 1292 | + let mut v = if input_value < 0. { |
| 1293 | + -significand |
| 1294 | + } else { |
| 1295 | + significand |
| 1296 | + } as i128; |
| 1297 | + |
| 1298 | + let k = exponent + scale as i32; |
| 1299 | + if k > 0 { |
| 1300 | + v = v.saturating_mul(Saturating(10_i128).pow(k as u32).0); |
| 1301 | + } else if k < 0 { |
| 1302 | + let dk = Saturating(10_i128).pow((-k) as u32).0; |
| 1303 | + let (div, rem) = if dk < v { v.div_rem(&dk) } else { (0, v) }; |
| 1304 | + v = if rem * 2 >= dk { div + 1 } else { div }; |
| 1305 | + } |
1292 | 1306 | if Decimal128Type::validate_decimal_precision(v, precision).is_err() {
|
1293 | 1307 | if eval_mode == EvalMode::Ansi {
|
1294 | 1308 | return Err(SparkError::NumericValueOutOfRange {
|
|
0 commit comments