2020#include " arrow/array/builder_primitive.h"
2121#include " arrow/compute/kernels/common.h"
2222#include " arrow/compute/kernels/scalar_cast_internal.h"
23+ #include " arrow/compute/kernels/util_internal.h"
2324#include " arrow/util/bit_block_counter.h"
2425#include " arrow/util/int_util.h"
2526#include " arrow/util/value_parsing.h"
@@ -361,8 +362,7 @@ struct CastFunctor<O, Decimal128Type, enable_if_t<is_integer_type<O>::value>> {
361362 static void Exec (KernelContext* ctx, const ExecBatch& batch, Datum* out) {
362363 const auto & options = checked_cast<const CastState*>(ctx->state ())->options ;
363364
364- const ArrayData& input = *batch[0 ].array ();
365- const auto & in_type_inst = checked_cast<const Decimal128Type&>(*input.type );
365+ const auto & in_type_inst = checked_cast<const Decimal128Type&>(*batch[0 ].type ());
366366 const auto in_scale = in_type_inst.scale ();
367367
368368 if (options.allow_decimal_truncate ) {
@@ -395,34 +395,34 @@ struct CastFunctor<O, Decimal128Type, enable_if_t<is_integer_type<O>::value>> {
395395struct UnsafeUpscaleDecimal {
396396 template <typename ... Unused>
397397 Decimal128 Call (KernelContext* ctx, Decimal128 val) const {
398- return val.IncreaseScaleBy (out_scale_ - in_scale_ );
398+ return val.IncreaseScaleBy (by_ );
399399 }
400-
401- int32_t out_scale_, in_scale_;
400+ int32_t by_;
402401};
403402
404403struct UnsafeDownscaleDecimal {
405404 template <typename ... Unused>
406405 Decimal128 Call (KernelContext* ctx, Decimal128 val) const {
407- return val.ReduceScaleBy (in_scale_ - out_scale_ , false );
406+ return val.ReduceScaleBy (by_ , false );
408407 }
409-
410- int32_t out_scale_, in_scale_;
408+ int32_t by_;
411409};
412410
413411struct SafeRescaleDecimal {
414412 template <typename ... Unused>
415413 Decimal128 Call (KernelContext* ctx, Decimal128 val) const {
416- auto result = val.Rescale (in_scale_, out_scale_);
417- if (ARROW_PREDICT_FALSE (!result.ok ())) {
418- ctx->SetStatus (result.status ());
419- return Decimal128 (); // Zero
420- } else if (ARROW_PREDICT_FALSE (!(*result).FitsInPrecision (out_precision_))) {
421- ctx->SetStatus (Status::Invalid (" Decimal value does not fit in precision" ));
422- return Decimal128 (); // Zero
423- } else {
424- return *std::move (result);
414+ auto maybe_rescaled = val.Rescale (in_scale_, out_scale_);
415+ if (ARROW_PREDICT_FALSE (!maybe_rescaled.ok ())) {
416+ ctx->SetStatus (maybe_rescaled.status ());
417+ return {}; // Zero
425418 }
419+
420+ if (ARROW_PREDICT_TRUE (maybe_rescaled->FitsInPrecision (out_precision_))) {
421+ return maybe_rescaled.MoveValueUnsafe ();
422+ }
423+
424+ ctx->SetStatus (Status::Invalid (" Decimal value does not fit in precision" ));
425+ return {}; // Zero
426426 }
427427
428428 int32_t out_scale_, out_precision_, in_scale_;
@@ -432,36 +432,33 @@ template <>
432432struct CastFunctor <Decimal128Type, Decimal128Type> {
433433 static void Exec (KernelContext* ctx, const ExecBatch& batch, Datum* out) {
434434 const auto & options = checked_cast<const CastState*>(ctx->state ())->options ;
435- const ArrayData& input = *batch[0 ].array ();
436- ArrayData* output = out->mutable_array ();
437435
438- const auto & in_type_inst = checked_cast<const Decimal128Type&>(*input.type );
439- const auto & out_type_inst = checked_cast<const Decimal128Type&>(*output->type );
440- const auto in_scale = in_type_inst.scale ();
441- const auto out_scale = out_type_inst.scale ();
442- const auto out_precision = out_type_inst.precision ();
436+ const auto & in_type = checked_cast<const Decimal128Type&>(*batch[0 ].type ());
437+ const auto & out_type = checked_cast<const Decimal128Type&>(*out->type ());
438+ const auto in_scale = in_type.scale ();
439+ const auto out_scale = out_type.scale ();
443440
444441 if (options.allow_decimal_truncate ) {
445442 if (in_scale < out_scale) {
446443 // Unsafe upscale
447444 applicator::ScalarUnaryNotNullStateful<Decimal128Type, Decimal128Type,
448445 UnsafeUpscaleDecimal>
449- kernel (UnsafeUpscaleDecimal{out_scale, in_scale});
446+ kernel (UnsafeUpscaleDecimal{out_scale - in_scale});
450447 return kernel.Exec (ctx, batch, out);
451448 } else {
452449 // Unsafe downscale
453450 applicator::ScalarUnaryNotNullStateful<Decimal128Type, Decimal128Type,
454451 UnsafeDownscaleDecimal>
455- kernel (UnsafeDownscaleDecimal{out_scale, in_scale});
452+ kernel (UnsafeDownscaleDecimal{in_scale - out_scale });
456453 return kernel.Exec (ctx, batch, out);
457454 }
458- } else {
459- // Safe rescale
460- applicator::ScalarUnaryNotNullStateful<Decimal128Type, Decimal128Type,
461- SafeRescaleDecimal>
462- kernel (SafeRescaleDecimal{out_scale, out_precision, in_scale});
463- return kernel.Exec (ctx, batch, out);
464455 }
456+
457+ // Safe rescale
458+ applicator::ScalarUnaryNotNullStateful<Decimal128Type, Decimal128Type,
459+ SafeRescaleDecimal>
460+ kernel (SafeRescaleDecimal{out_scale, out_type.precision (), in_scale});
461+ return kernel.Exec (ctx, batch, out);
465462 }
466463};
467464
@@ -471,15 +468,16 @@ struct CastFunctor<Decimal128Type, Decimal128Type> {
471468struct RealToDecimal {
472469 template <typename OutValue, typename RealType>
473470 Decimal128 Call (KernelContext* ctx, RealType val) const {
474- auto result = Decimal128::FromReal (val, out_precision_, out_scale_);
475- if (ARROW_PREDICT_FALSE (!result.ok ())) {
476- if (!allow_truncate_) {
477- ctx->SetStatus (result.status ());
478- }
479- return Decimal128 (); // Zero
480- } else {
481- return *std::move (result);
471+ auto maybe_decimal = Decimal128::FromReal (val, out_precision_, out_scale_);
472+
473+ if (ARROW_PREDICT_TRUE (maybe_decimal.ok ())) {
474+ return maybe_decimal.MoveValueUnsafe ();
482475 }
476+
477+ if (!allow_truncate_) {
478+ ctx->SetStatus (maybe_decimal.status ());
479+ }
480+ return {}; // Zero
483481 }
484482
485483 int32_t out_scale_, out_precision_;
@@ -490,10 +488,9 @@ template <typename I>
490488struct CastFunctor <Decimal128Type, I, enable_if_t <is_floating_type<I>::value>> {
491489 static void Exec (KernelContext* ctx, const ExecBatch& batch, Datum* out) {
492490 const auto & options = checked_cast<const CastState*>(ctx->state ())->options ;
493- ArrayData* output = out->mutable_array ();
494- const auto & out_type_inst = checked_cast<const Decimal128Type&>(*output->type );
495- const auto out_scale = out_type_inst.scale ();
496- const auto out_precision = out_type_inst.precision ();
491+ const auto & out_type = checked_cast<const Decimal128Type&>(*out->type ());
492+ const auto out_scale = out_type.scale ();
493+ const auto out_precision = out_type.precision ();
497494
498495 applicator::ScalarUnaryNotNullStateful<Decimal128Type, I, RealToDecimal> kernel (
499496 RealToDecimal{out_scale, out_precision, options.allow_decimal_truncate });
@@ -516,9 +513,8 @@ struct DecimalToReal {
516513template <typename O>
517514struct CastFunctor <O, Decimal128Type, enable_if_t <is_floating_type<O>::value>> {
518515 static void Exec (KernelContext* ctx, const ExecBatch& batch, Datum* out) {
519- const auto & in_type_inst =
520- checked_cast<const Decimal128Type&>(*batch[0 ].array ()->type );
521- const auto in_scale = in_type_inst.scale ();
516+ const auto & in_type = checked_cast<const Decimal128Type&>(*batch[0 ].type ());
517+ const auto in_scale = in_type.scale ();
522518
523519 applicator::ScalarUnaryNotNullStateful<O, Decimal128Type, DecimalToReal> kernel (
524520 DecimalToReal{in_scale});
@@ -564,7 +560,7 @@ std::shared_ptr<CastFunction> GetCastToInteger(std::string name) {
564560 AddCommonNumberCasts<OutType>(out_ty, func.get ());
565561
566562 // From decimal to integer
567- DCHECK_OK (func->AddKernel (Type::DECIMAL , {InputType::Array (Type::DECIMAL )}, out_ty,
563+ DCHECK_OK (func->AddKernel (Type::DECIMAL , {InputType (Type::DECIMAL )}, out_ty,
568564 CastFunctor<OutType, Decimal128Type>::Exec));
569565 return func;
570566}
@@ -588,7 +584,7 @@ std::shared_ptr<CastFunction> GetCastToFloating(std::string name) {
588584 AddCommonNumberCasts<OutType>(out_ty, func.get ());
589585
590586 // From decimal to floating point
591- DCHECK_OK (func->AddKernel (Type::DECIMAL , {InputType::Array (Type::DECIMAL )}, out_ty,
587+ DCHECK_OK (func->AddKernel (Type::DECIMAL , {InputType (Type::DECIMAL )}, out_ty,
592588 CastFunctor<OutType, Decimal128Type>::Exec));
593589 return func;
594590}
@@ -608,8 +604,8 @@ std::shared_ptr<CastFunction> GetCastToDecimal128() {
608604 // Cast from other decimal
609605 auto exec = CastFunctor<Decimal128Type, Decimal128Type>::Exec;
610606 // We resolve the output type of this kernel from the CastOptions
611- DCHECK_OK (func-> AddKernel (Type:: DECIMAL128 , { InputType::Array (Type:: DECIMAL128 )},
612- sig_out_ty, exec));
607+ DCHECK_OK (
608+ func-> AddKernel (Type:: DECIMAL128 , { InputType (Type:: DECIMAL128 )}, sig_out_ty, exec));
613609 return func;
614610}
615611
0 commit comments