This is an automated email from the ASF dual-hosted git repository.
pitrou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 95237d96b26 GH-55312: [C++][Compute] More flexible kernel exec
generation (#55291)
95237d96b26 is described below
commit 95237d96b26283e7e45e8cd887fcc40adbe94ab9
Author: Antoine Pitrou <[email protected]>
AuthorDate: Mon Nov 2 14:22:29 2026 +0100
GH-55312: [C++][Compute] More flexible kernel exec generation (#55291)
### Rationale for this change
Our kernel generation utilities in
`arrow/compute/kernels/codegen_internal.h` are a hodge-podge of hand-written
switch statements with inconsistent template parameter signatures and semantics.
This PR makes those more flexible, more consistent and more reusable.
### What changes are included in this PR?
* Rewrite kernel generation utilities to make them more generic, allowing
to pass compile-time arrays of type ids
* Add compile-time constant arrays of type ids (`kAllTypeIds`,
`kIntegerTypeIds`...)
* Add missing `TypeIdTraits` specializations
* Add missing `type_id` static member definitions on `RunEndEncodedType`
and `ExtensionType`
* Reduce code duplication in numeric cast kernel generation
### Are these changes tested?
Yes, by existing tests and new unit tests around type id traits.
### Are there any user-facing changes?
No.
### Was AI used for this PR?
In accordance to the [AI generation
guidelines](https://arrow.apache.org/docs/dev/developers/overview.html#ai-generated-code),
please disclose below whether and how AI was used in this PR.
**PR code and description written by:**
- [x] Human
- [ ] AI
**Reviewed before submission by:**
- [x] Human
- [ ] AI
- [ ] Not reviewed
* GitHub Issue: #55312
Authored-by: Antoine Pitrou <[email protected]>
Signed-off-by: Antoine Pitrou <[email protected]>
---
cpp/src/arrow/compute/kernels/aggregate_mode.cc | 27 +-
.../arrow/compute/kernels/aggregate_quantile.cc | 13 +-
cpp/src/arrow/compute/kernels/codegen_internal.h | 525 ++++++++++-----------
cpp/src/arrow/compute/kernels/scalar_arithmetic.cc | 38 +-
.../arrow/compute/kernels/scalar_cast_boolean.cc | 9 +-
.../arrow/compute/kernels/scalar_cast_numeric.cc | 200 ++------
.../arrow/compute/kernels/scalar_cast_string.cc | 24 +-
cpp/src/arrow/compute/kernels/scalar_compare.cc | 22 +-
cpp/src/arrow/compute/kernels/scalar_if_else.cc | 2 +-
cpp/src/arrow/compute/kernels/scalar_nested.cc | 3 +-
.../arrow/compute/kernels/scalar_string_ascii.cc | 10 +-
cpp/src/arrow/compute/kernels/vector_array_sort.cc | 12 +-
cpp/src/arrow/compute/kernels/vector_replace.cc | 9 +-
cpp/src/arrow/compute/kernels/vector_statistics.cc | 15 +-
cpp/src/arrow/compute/kernels/vector_swizzle.cc | 14 +-
cpp/src/arrow/type.cc | 83 +---
cpp/src/arrow/type_test.cc | 18 +
cpp/src/arrow/type_traits.h | 326 ++++++-------
18 files changed, 578 insertions(+), 772 deletions(-)
diff --git a/cpp/src/arrow/compute/kernels/aggregate_mode.cc
b/cpp/src/arrow/compute/kernels/aggregate_mode.cc
index 75786d12b6e..5011e4a0724 100644
--- a/cpp/src/arrow/compute/kernels/aggregate_mode.cc
+++ b/cpp/src/arrow/compute/kernels/aggregate_mode.cc
@@ -428,7 +428,7 @@ Status CheckOptions(KernelContext* ctx) {
return Status::OK();
}
-template <typename OutTypeUnused, typename InType>
+template <typename InType>
struct ModeExecutor {
static Status Exec(KernelContext* ctx, const ExecSpan& batch, ExecResult*
out) {
RETURN_NOT_OK(CheckOptions(ctx));
@@ -436,7 +436,7 @@ struct ModeExecutor {
}
};
-template <typename OutTypeUnused, typename InType>
+template <typename InType>
struct ModeExecutorChunked {
static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
RETURN_NOT_OK(CheckOptions(ctx));
@@ -491,21 +491,20 @@ void RegisterScalarAggregateMode(FunctionRegistry*
registry) {
static auto default_options = ModeOptions::Defaults();
auto func = std::make_shared<VectorFunction>("mode", Arity::Unary(),
mode_doc,
&default_options);
- DCHECK_OK(func->AddKernel(
- NewModeKernel(boolean(), ModeExecutor<StructType, BooleanType>::Exec,
- ModeExecutorChunked<StructType, BooleanType>::Exec)));
+ DCHECK_OK(func->AddKernel(NewModeKernel(boolean(),
ModeExecutor<BooleanType>::Exec,
+
ModeExecutorChunked<BooleanType>::Exec)));
for (const auto& type : NumericTypes()) {
- DCHECK_OK(func->AddKernel(
- NewModeKernel(type, GenerateNumeric<ModeExecutor, StructType>(*type),
- GenerateNumeric<ModeExecutorChunked,
StructType>(*type))));
+ DCHECK_OK(
+ func->AddKernel(NewModeKernel(type,
GenerateNumeric<ModeExecutor>(*type),
+
GenerateNumeric<ModeExecutorChunked>(*type))));
}
// Type parameters are ignored
- DCHECK_OK(func->AddKernel(
- NewModeKernel(decimal128(1, 0), ModeExecutor<StructType,
Decimal128Type>::Exec,
- ModeExecutorChunked<StructType, Decimal128Type>::Exec)));
- DCHECK_OK(func->AddKernel(
- NewModeKernel(decimal256(1, 0), ModeExecutor<StructType,
Decimal256Type>::Exec,
- ModeExecutorChunked<StructType, Decimal256Type>::Exec)));
+ DCHECK_OK(
+ func->AddKernel(NewModeKernel(decimal128(1, 0),
ModeExecutor<Decimal128Type>::Exec,
+
ModeExecutorChunked<Decimal128Type>::Exec)));
+ DCHECK_OK(
+ func->AddKernel(NewModeKernel(decimal256(1, 0),
ModeExecutor<Decimal256Type>::Exec,
+
ModeExecutorChunked<Decimal256Type>::Exec)));
DCHECK_OK(registry->AddFunction(std::move(func)));
}
diff --git a/cpp/src/arrow/compute/kernels/aggregate_quantile.cc
b/cpp/src/arrow/compute/kernels/aggregate_quantile.cc
index 4e3894d2f20..79b9b415df4 100644
--- a/cpp/src/arrow/compute/kernels/aggregate_quantile.cc
+++ b/cpp/src/arrow/compute/kernels/aggregate_quantile.cc
@@ -496,7 +496,7 @@ Status CheckQuantileOptions(KernelContext* ctx) {
return Status::OK();
}
-template <typename OutputTypeUnused, typename InType>
+template <typename InType>
struct QuantileExecutor {
static Status Exec(KernelContext* ctx, const ExecSpan& batch, ExecResult*
out) {
RETURN_NOT_OK(CheckQuantileOptions(ctx));
@@ -504,7 +504,7 @@ struct QuantileExecutor {
}
};
-template <typename OutputTypeUnused, typename InType>
+template <typename InType>
struct QuantileExecutorChunked {
static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
RETURN_NOT_OK(CheckQuantileOptions(ctx));
@@ -530,15 +530,14 @@ void AddQuantileKernels(VectorFunction* func) {
for (const auto& ty : NumericTypes()) {
base.signature = KernelSignature::Make({InputType(ty)},
OutputType(ResolveOutput));
- // output type is determined at runtime, set template argument to nulltype
- base.exec = GenerateNumeric<QuantileExecutor, NullType>(*ty);
- base.exec_chunked = GenerateNumeric<QuantileExecutorChunked,
NullType>(*ty);
+ base.exec = GenerateNumeric<QuantileExecutor>(*ty);
+ base.exec_chunked = GenerateNumeric<QuantileExecutorChunked>(*ty);
DCHECK_OK(func->AddKernel(base));
}
for (auto type_id : DecimalTypeIds()) {
base.signature = KernelSignature::Make({type_id},
OutputType(ResolveOutput));
- base.exec = GenerateDecimal<QuantileExecutor, NullType>(type_id);
- base.exec_chunked = GenerateDecimal<QuantileExecutorChunked,
NullType>(type_id);
+ base.exec = GenerateDecimal<QuantileExecutor>(type_id);
+ base.exec_chunked = GenerateDecimal<QuantileExecutorChunked>(type_id);
DCHECK_OK(func->AddKernel(base));
}
}
diff --git a/cpp/src/arrow/compute/kernels/codegen_internal.h
b/cpp/src/arrow/compute/kernels/codegen_internal.h
index 9da440cc65a..405f35a9234 100644
--- a/cpp/src/arrow/compute/kernels/codegen_internal.h
+++ b/cpp/src/arrow/compute/kernels/codegen_internal.h
@@ -17,6 +17,7 @@
#pragma once
+#include <concepts>
#include <cstdint>
#include <cstring>
#include <memory>
@@ -49,6 +50,7 @@
#include "arrow/util/float16.h"
#include "arrow/util/logging.h"
#include "arrow/util/macros.h"
+#include "arrow/util/unreachable.h"
#include "arrow/util/visibility.h"
#include "arrow/visit_data_inline.h"
@@ -1000,26 +1002,43 @@ using ScalarBinaryNotNullStatefulEqualTypes =
// looping over vectors of data types rather than using macros or other
// approaches.
//
-// The kernel functor must be of the form:
+// A typical kernel functor is of the form:
//
-// template <typename Type0, typename Type1, Args...>
+// template <typename Type1, Args...>
// struct FUNCTOR {
// static void Exec(KernelContext* ctx, const ExecSpan& batch, ExecResult*
out) {
// // IMPLEMENTATION
// }
// };
//
-// When you pass FUNCTOR to a GD function, you must pass at least one static
-// type along with the functor -- this is often the fixed return type of the
-// functor. This Type0 argument is passed as the first argument to the functor
-// during instantiation. The 2nd type passed to the functor is the DataType
-// subclass corresponding to the type passed as argument (not template type) to
-// the function.
-//
-// For example, GenerateNumeric<FUNCTOR, Type0>(int32()) will select a kernel
-// instantiated like FUNCTOR<Type0, Int32Type>. Any additional variadic
+// For example, GenerateNumeric<FUNCTOR>(int32()) will select a kernel
+// instantiated like FUNCTOR<Int32Type>. Any additional variadic
// template arguments will be passed as additional template arguments to the
// kernel template.
+//
+// In some instances, the functor needs to be parametered using several types,
+// for example both by input type and return type:
+//
+// template <typename Type0, typename Type1, Args...>
+// struct FUNCTOR {
+// static void Exec(KernelContext* ctx, const ExecSpan& batch, ExecResult*
out) {
+// // IMPLEMENTATION
+// }
+// };
+//
+// If you want the GD function to instantiate the Type1 parameter of FUNCTOR
+// while passing Type0 explicitly *before* Type1 in the template parameter
list,
+// you can use the WithType0<> template parameter.
+// For example, GenerateNumeric<FUNCTOR, WithType0<StringType>>(int32()) will
+// select a kernel instantiated like FUNCTOR<StringType, Int32Type>.
+//
+// (note that calling GenerateNumeric<FUNCTOR, StringType>(int32()) would
instead
+// select a kernel instantiated like FUNCTOR<Int32Type, StringType>).
+//
+// Similarly, the WithFirstTypeTwice template parameter instructs the GD to
pass
+// its generated template parameter twice.
+// In the example above, calling GenerateNumeric<FUNCTOR,
WithFirstTypeTwice>(int32())
+// will select a kernel instantiated like FUNCTOR<Int32Type, Int32Type>.
namespace detail {
@@ -1028,9 +1047,9 @@ struct GetTypeId {
Type::type id;
GetTypeId(const std::shared_ptr<DataType>& type) // NOLINT implicit
construction
: id(type->id()) {}
- GetTypeId(const DataType& type) // NOLINT implicit construction
+ constexpr GetTypeId(const DataType& type) // NOLINT implicit construction
: id(type.id()) {}
- GetTypeId(Type::type id) // NOLINT implicit construction
+ constexpr GetTypeId(Type::type id) // NOLINT implicit construction
: id(id) {}
};
@@ -1053,221 +1072,252 @@ struct FailFunctor<VectorKernel::ChunkedExec> {
}
};
-// GD for numeric types (integer and floating point)
-template <template <typename...> class Generator, typename Type0, typename...
Args>
-auto GenerateNumeric(detail::GetTypeId get_id) {
- using KernelType = decltype(&Generator<Type0, Int8Type, Args...>::Exec);
- switch (get_id.id) {
+constexpr Type::type TypeIdIdentity(Type::type id) { return id; }
+
+constexpr std::optional<Type::type> TypeIdToUnsigned(Type::type id) {
+ switch (id) {
case Type::INT8:
- return Generator<Type0, Int8Type, Args...>::Exec;
case Type::UINT8:
- return Generator<Type0, UInt8Type, Args...>::Exec;
+ return Type::UINT8;
case Type::INT16:
- return Generator<Type0, Int16Type, Args...>::Exec;
case Type::UINT16:
- return Generator<Type0, UInt16Type, Args...>::Exec;
+ return Type::UINT16;
case Type::INT32:
- return Generator<Type0, Int32Type, Args...>::Exec;
case Type::UINT32:
- return Generator<Type0, UInt32Type, Args...>::Exec;
- case Type::INT64:
- return Generator<Type0, Int64Type, Args...>::Exec;
- case Type::UINT64:
- return Generator<Type0, UInt64Type, Args...>::Exec;
- case Type::FLOAT:
- return Generator<Type0, FloatType, Args...>::Exec;
- case Type::DOUBLE:
- return Generator<Type0, DoubleType, Args...>::Exec;
- default:
- ARROW_DCHECK(false);
- return FailFunctor<KernelType>::Exec;
- }
-}
-
-// Generate a kernel given a templated functor for floating point types
-//
-// See "Numeric" above for description of the generator functor
-template <template <typename...> class Generator, typename Type0, typename...
Args>
-ArrayKernelExec GenerateFloatingPoint(detail::GetTypeId get_id) {
- switch (get_id.id) {
- case Type::FLOAT:
- return Generator<Type0, FloatType, Args...>::Exec;
- case Type::DOUBLE:
- return Generator<Type0, DoubleType, Args...>::Exec;
- default:
- ARROW_DCHECK(false);
- return nullptr;
- }
-}
-
-// Generate a kernel given a templated functor for integer types
-//
-// See "Numeric" above for description of the generator functor
-template <template <typename...> class Generator, typename Type0,
- typename KernelType = ArrayKernelExec, typename... Args>
-KernelType GenerateInteger(detail::GetTypeId get_id) {
- switch (get_id.id) {
- case Type::INT8:
- return Generator<Type0, Int8Type, Args...>::Exec;
- case Type::INT16:
- return Generator<Type0, Int16Type, Args...>::Exec;
- case Type::INT32:
- return Generator<Type0, Int32Type, Args...>::Exec;
+ return Type::UINT32;
case Type::INT64:
- return Generator<Type0, Int64Type, Args...>::Exec;
- case Type::UINT8:
- return Generator<Type0, UInt8Type, Args...>::Exec;
- case Type::UINT16:
- return Generator<Type0, UInt16Type, Args...>::Exec;
- case Type::UINT32:
- return Generator<Type0, UInt32Type, Args...>::Exec;
case Type::UINT64:
- return Generator<Type0, UInt64Type, Args...>::Exec;
+ return Type::UINT64;
default:
- ARROW_DCHECK(false);
- return nullptr;
+ return std::nullopt;
}
}
-template <template <typename...> class Generator, typename Type0, typename...
Args>
-ArrayKernelExec GeneratePhysicalInteger(detail::GetTypeId get_id) {
- switch (get_id.id) {
+constexpr std::optional<Type::type> TypeIdToPhysicalNumeric(Type::type id) {
+ switch (id) {
case Type::INT8:
- return Generator<Type0, Int8Type, Args...>::Exec;
+ return Type::INT8;
case Type::INT16:
- return Generator<Type0, Int16Type, Args...>::Exec;
+ return Type::INT16;
case Type::INT32:
case Type::DATE32:
case Type::TIME32:
- return Generator<Type0, Int32Type, Args...>::Exec;
+ return Type::INT32;
case Type::INT64:
case Type::DATE64:
case Type::TIMESTAMP:
case Type::TIME64:
case Type::DURATION:
- return Generator<Type0, Int64Type, Args...>::Exec;
+ return Type::INT64;
case Type::UINT8:
- return Generator<Type0, UInt8Type, Args...>::Exec;
+ return Type::UINT8;
case Type::UINT16:
- return Generator<Type0, UInt16Type, Args...>::Exec;
+ return Type::UINT16;
case Type::UINT32:
- return Generator<Type0, UInt32Type, Args...>::Exec;
+ return Type::UINT32;
case Type::UINT64:
- return Generator<Type0, UInt64Type, Args...>::Exec;
+ return Type::UINT64;
+ case Type::HALF_FLOAT:
+ return Type::HALF_FLOAT;
+ case Type::FLOAT:
+ return Type::FLOAT;
+ case Type::DOUBLE:
+ return Type::DOUBLE;
default:
- ARROW_DCHECK(false);
- return nullptr;
+ return std::nullopt;
}
}
-template <template <typename...> class KernelGenerator, typename Op,
- typename KernelType = ArrayKernelExec, typename... Args>
-KernelType ArithmeticExecFromOp(detail::GetTypeId get_id) {
- switch (get_id.id) {
- case Type::INT8:
- return KernelGenerator<Int8Type, Int8Type, Op, Args...>::Exec;
- case Type::UINT8:
- return KernelGenerator<UInt8Type, UInt8Type, Op, Args...>::Exec;
- case Type::INT16:
- return KernelGenerator<Int16Type, Int16Type, Op, Args...>::Exec;
- case Type::UINT16:
- return KernelGenerator<UInt16Type, UInt16Type, Op, Args...>::Exec;
- case Type::INT32:
- return KernelGenerator<Int32Type, Int32Type, Op, Args...>::Exec;
- case Type::UINT32:
- return KernelGenerator<UInt32Type, UInt32Type, Op, Args...>::Exec;
- case Type::DURATION:
- case Type::INT64:
- case Type::TIMESTAMP:
- return KernelGenerator<Int64Type, Int64Type, Op, Args...>::Exec;
- case Type::UINT64:
- return KernelGenerator<UInt64Type, UInt64Type, Op, Args...>::Exec;
- case Type::FLOAT:
- return KernelGenerator<FloatType, FloatType, Op, Args...>::Exec;
- case Type::DOUBLE:
- return KernelGenerator<DoubleType, DoubleType, Op, Args...>::Exec;
+constexpr std::optional<Type::type> TypeIdToPhysicalBinary(Type::type id) {
+ switch (id) {
+ case Type::BINARY:
+ case Type::STRING:
+ return Type::BINARY;
+ case Type::LARGE_BINARY:
+ case Type::LARGE_STRING:
+ return Type::LARGE_BINARY;
+ case Type::BINARY_VIEW:
+ case Type::STRING_VIEW:
+ return Type::BINARY_VIEW;
default:
- ARROW_DCHECK(false);
- return FailFunctor<KernelType>::Exec;
+ return std::nullopt;
}
}
-template <typename ReturnType, template <typename... Args> class Generator,
- typename... Args>
-ReturnType GeneratePhysicalNumericGeneric(detail::GetTypeId get_id) {
- switch (get_id.id) {
+constexpr std::optional<Type::type> TypeIdToPrimitiveAgnostic(Type::type id) {
+ switch (id) {
+ case Type::NA:
+ return Type::NA;
+ case Type::BOOL:
+ return Type::BOOL;
+ case Type::UINT8:
case Type::INT8:
- return Generator<Int8Type, Args...>::Exec;
+ return Type::UINT8;
+ case Type::UINT16:
case Type::INT16:
- return Generator<Int16Type, Args...>::Exec;
+ case Type::HALF_FLOAT:
+ return Type::UINT16;
+ case Type::UINT32:
case Type::INT32:
+ case Type::FLOAT:
case Type::DATE32:
case Type::TIME32:
- return Generator<Int32Type, Args...>::Exec;
+ case Type::INTERVAL_MONTHS:
+ return Type::UINT32;
+ case Type::UINT64:
case Type::INT64:
+ case Type::DOUBLE:
case Type::DATE64:
case Type::TIMESTAMP:
case Type::TIME64:
case Type::DURATION:
- return Generator<Int64Type, Args...>::Exec;
- case Type::UINT8:
- return Generator<UInt8Type, Args...>::Exec;
- case Type::UINT16:
- return Generator<UInt16Type, Args...>::Exec;
- case Type::UINT32:
- return Generator<UInt32Type, Args...>::Exec;
- case Type::UINT64:
- return Generator<UInt64Type, Args...>::Exec;
- case Type::FLOAT:
- return Generator<FloatType, Args...>::Exec;
- case Type::DOUBLE:
- return Generator<DoubleType, Args...>::Exec;
+ case Type::INTERVAL_DAY_TIME:
+ return Type::UINT64;
+ case Type::INTERVAL_MONTH_DAY_NANO:
+ return Type::INTERVAL_MONTH_DAY_NANO;
default:
- ARROW_DCHECK(false);
- return nullptr;
+ return std::nullopt;
}
}
-template <template <typename... Args> class Generator, typename... Args>
-ArrayKernelExec GeneratePhysicalNumeric(detail::GetTypeId get_id) {
- return GeneratePhysicalNumericGeneric<ArrayKernelExec, Generator,
Args...>(get_id);
+
+// A special marker for GenerateKernelExec that indicates its type parameter
+// should be passed *before* the generated type parameter.
+template <typename T>
+struct WithType0 {
+ using Type = T;
+};
+
+// A special marker for GenerateKernelExec that indicates the generated type
+// parameter should be passed twice.
+struct WithFirstTypeTwice {};
+
+namespace detail {
+
+template <typename Array, std::size_t... I>
+constexpr auto array_to_tuple_impl(const Array& a, std::index_sequence<I...>) {
+ return std::make_tuple(a[I]...);
}
-// Generate a kernel given a templated functor for decimal types
-template <template <typename... Args> class Generator, typename... Args>
-ArrayKernelExec GenerateDecimalToDecimal(detail::GetTypeId get_id) {
- switch (get_id.id) {
- case Type::DECIMAL32:
- return Generator<Decimal32Type, Args...>::Exec;
- case Type::DECIMAL64:
- return Generator<Decimal64Type, Args...>::Exec;
- case Type::DECIMAL128:
- return Generator<Decimal128Type, Args...>::Exec;
- case Type::DECIMAL256:
- return Generator<Decimal256Type, Args...>::Exec;
- default:
- ARROW_DCHECK(false);
- return nullptr;
+template <typename T, std::size_t N>
+constexpr auto array_to_tuple(const std::array<T, N>& a) {
+ return array_to_tuple_impl(a, std::make_index_sequence<N>{});
+}
+
+template <typename Tup>
+constexpr auto tuple_to_array(const Tup& tup) {
+ return std::apply([](auto&&... elements) { return std::array{elements...};
}, tup);
+}
+
+} // namespace detail
+
+// Concatenate a number of std::array's
+template <typename... Args>
+constexpr auto array_cat(Args&&... args) {
+ return
detail::tuple_to_array(std::tuple_cat(detail::array_to_tuple(args)...));
+}
+
+namespace detail {
+
+template <template <typename...> class Generator, typename... Args>
+struct GeneratorApplicator {
+ using Type = Generator<Args...>;
+};
+
+template <template <typename...> class Generator, typename Arg1, typename
Type0,
+ typename... Args>
+struct GeneratorApplicator<Generator, Arg1, WithType0<Type0>, Args...> {
+ using Type = GeneratorApplicator<Generator, Type0, Arg1, Args...>::Type;
+};
+
+template <template <typename...> class Generator, typename Arg1, typename...
Args>
+struct GeneratorApplicator<Generator, Arg1, WithFirstTypeTwice, Args...> {
+ using Type = GeneratorApplicator<Generator, Arg1, Arg1, Args...>::Type;
+};
+
+template <auto Transform, auto TypeIdArray, size_t ArrayIndex,
+ template <typename...> class Generator, typename... Args>
+ requires std::invocable<decltype(Transform), Type::type>
+auto GenerateKernelExecImpl(Type::type id) {
+ constexpr auto kNumTypeIds = std::tuple_size_v<decltype(TypeIdArray)>;
+ static_assert(ArrayIndex < kNumTypeIds);
+
+ constexpr Type::type match_id = std::get<ArrayIndex>(TypeIdArray);
+ // The transformer may return Type::type or std::optional<Type::type>
+ constexpr std::optional<Type::type> transformed_id =
std::optional{Transform(match_id)};
+ static_assert(transformed_id.has_value(), "Transform function didn't accept
match_id");
+
+ using TransformedType = typename TypeIdTraits<transformed_id.value()>::Type;
+ constexpr auto match_val =
+ GeneratorApplicator<Generator, TransformedType, Args...>::Type::Exec;
+
+ if constexpr (ArrayIndex == kNumTypeIds - 1) {
+ ARROW_CHECK(id == match_id) << "Unmatched type id in kernel generation";
+ return match_val;
+ } else {
+ auto fallback = [&]() {
+ return GenerateKernelExecImpl<Transform, TypeIdArray, ArrayIndex + 1,
Generator,
+ Args...>(id);
+ };
+ // Help the compiler infer the proper return type for this function
+ using RetType = std::common_type_t<decltype(match_val),
decltype(fallback())>;
+ if (id == match_id) {
+ return RetType{match_val};
+ } else {
+ return RetType{fallback()};
+ }
}
}
+} // namespace detail
+
+template <auto Transform, auto TypeIdArray, template <typename...> class
Generator,
+ typename... Args>
+ requires std::invocable<decltype(Transform), Type::type>
+auto GenerateKernelExec(detail::GetTypeId get_id) {
+ return detail::GenerateKernelExecImpl<Transform, TypeIdArray,
/*ArrayIndex=*/0,
+ Generator, Args...>(get_id.id);
+}
+
+template <auto TypeIdArray, template <typename...> class Generator,
typename... Args>
+auto GenerateKernelExec(detail::GetTypeId get_id) {
+ return detail::GenerateKernelExecImpl<TypeIdIdentity, TypeIdArray,
+ /*ArrayIndex=*/0, Generator,
Args...>(get_id.id);
+}
+
+// GD for numeric types (integer and floating point)
+template <template <typename...> class Generator, typename... Args>
+auto GenerateNumeric(detail::GetTypeId get_id) {
+ return GenerateKernelExec<array_cat(kIntegerTypeIds,
kPhysicalFloatingTypeIds),
+ Generator, Args...>(get_id);
+}
+
// Generate a kernel given a templated functor for integer types
//
-// See "Numeric" above for description of the generator functor
-template <template <typename...> class Generator, typename Type0, typename...
Args>
-ArrayKernelExec GenerateSignedInteger(detail::GetTypeId get_id) {
- switch (get_id.id) {
- case Type::INT8:
- return Generator<Type0, Int8Type, Args...>::Exec;
- case Type::INT16:
- return Generator<Type0, Int16Type, Args...>::Exec;
- case Type::INT32:
- return Generator<Type0, Int32Type, Args...>::Exec;
- case Type::INT64:
- return Generator<Type0, Int64Type, Args...>::Exec;
- default:
- ARROW_DCHECK(false);
- return nullptr;
- }
+template <template <typename...> class Generator, typename... Args>
+auto GenerateInteger(detail::GetTypeId get_id) {
+ return GenerateKernelExec<kIntegerTypeIds, Generator, Args...>(get_id);
+}
+
+template <template <typename...> class Generator, typename... Args>
+auto ArithmeticExec(detail::GetTypeId get_id) {
+ return GenerateKernelExec<TypeIdToPhysicalNumeric,
+ array_cat(kIntegerTypeIds,
kPhysicalFloatingTypeIds,
+ std::array{Type::TIMESTAMP,
Type::DURATION}),
+ Generator, WithFirstTypeTwice, Args...>(get_id);
+}
+
+template <template <typename... Args> class Generator, typename... Args>
+auto GeneratePhysicalNumeric(detail::GetTypeId get_id) {
+ return GenerateKernelExec<TypeIdToPhysicalNumeric,
+ array_cat(kIntegerTypeIds,
kPhysicalFloatingTypeIds,
+ kTemporalTypeIds,
std::array{Type::DURATION}),
+ Generator, Args...>(get_id);
+}
+
+// Generate a kernel given a templated functor for decimal types
+template <template <typename... Args> class Generator, typename... Args>
+auto GenerateDecimalToDecimal(detail::GetTypeId get_id) {
+ return GenerateKernelExec<kDecimalTypeIds, Generator, Args...>(get_id);
}
// Generate a kernel given a templated functor. Only a single template is
@@ -1277,43 +1327,11 @@ ArrayKernelExec GenerateSignedInteger(detail::GetTypeId
get_id) {
// bits).
//
// See "Numeric" above for description of the generator functor
-template <template <typename...> class Generator, typename KernelType =
ArrayKernelExec,
- typename... Args>
-KernelType GenerateTypeAgnosticPrimitive(detail::GetTypeId get_id) {
- switch (get_id.id) {
- case Type::NA:
- return Generator<NullType, Args...>::Exec;
- case Type::BOOL:
- return Generator<BooleanType, Args...>::Exec;
- case Type::UINT8:
- case Type::INT8:
- return Generator<UInt8Type, Args...>::Exec;
- case Type::UINT16:
- case Type::INT16:
- case Type::HALF_FLOAT:
- return Generator<UInt16Type, Args...>::Exec;
- case Type::UINT32:
- case Type::INT32:
- case Type::FLOAT:
- case Type::DATE32:
- case Type::TIME32:
- case Type::INTERVAL_MONTHS:
- return Generator<UInt32Type, Args...>::Exec;
- case Type::UINT64:
- case Type::INT64:
- case Type::DOUBLE:
- case Type::DATE64:
- case Type::TIMESTAMP:
- case Type::TIME64:
- case Type::DURATION:
- case Type::INTERVAL_DAY_TIME:
- return Generator<UInt64Type, Args...>::Exec;
- case Type::INTERVAL_MONTH_DAY_NANO:
- return Generator<MonthDayNanoIntervalType, Args...>::Exec;
- default:
- ARROW_DCHECK(false);
- return FailFunctor<KernelType>::Exec;
- }
+template <template <typename...> class Generator, typename... Args>
+auto GenerateTypeAgnosticPrimitive(detail::GetTypeId get_id) {
+ return GenerateKernelExec<TypeIdToPrimitiveAgnostic,
+ array_cat(kPrimitiveTypeIds,
std::array{Type::NA}), Generator,
+ Args...>(get_id);
}
// Similar to GenerateTypeAgnosticPrimitive, but for base variable binary types
@@ -1323,18 +1341,8 @@ KernelType
GenerateTypeAgnosticPrimitive(detail::GetTypeId get_id) {
// This helps cut down on code generation (see GH-50615).
template <template <typename...> class Generator, typename... Args>
auto GenerateTypeAgnosticVarBinaryBase(detail::GetTypeId get_id) {
- using KernelType = decltype(&Generator<BinaryType, Args...>::Exec);
- switch (get_id.id) {
- case Type::BINARY:
- case Type::STRING:
- return Generator<BinaryType, Args...>::Exec;
- case Type::LARGE_BINARY:
- case Type::LARGE_STRING:
- return Generator<LargeBinaryType, Args...>::Exec;
- default:
- ARROW_DCHECK(false);
- return FailFunctor<KernelType>::Exec;
- }
+ return GenerateKernelExec<TypeIdToPhysicalBinary, kBaseBinaryLikeTypeIds,
Generator,
+ Args...>(get_id);
}
// Generate a kernel given a templated functor for base binary types. Generates
@@ -1343,80 +1351,37 @@ auto
GenerateTypeAgnosticVarBinaryBase(detail::GetTypeId get_id) {
// BaseBinarySpecific.
//
// See "Numeric" above for description of the generator functor
-template <template <typename...> class Generator, typename Type0, typename...
Args>
-ArrayKernelExec GenerateVarBinaryBase(detail::GetTypeId get_id) {
- switch (get_id.id) {
- case Type::BINARY:
- case Type::STRING:
- return Generator<Type0, BinaryType, Args...>::Exec;
- case Type::LARGE_BINARY:
- case Type::LARGE_STRING:
- return Generator<Type0, LargeBinaryType, Args...>::Exec;
- default:
- ARROW_DCHECK(false);
- return nullptr;
- }
+template <template <typename...> class Generator, typename... Args>
+auto GenerateVarBinaryBase(detail::GetTypeId get_id) {
+ return GenerateKernelExec<TypeIdToPhysicalBinary, kBaseBinaryLikeTypeIds,
Generator,
+ Args...>(get_id);
}
// Generate a kernel given a templated functor for binary-view types.
Generates a
// single kernel for binary/string-view.
//
// See "Numeric" above for description of the generator functor
-template <template <typename...> class Generator, typename Type0, typename...
Args>
-ArrayKernelExec GenerateVarBinaryViewBase(detail::GetTypeId get_id) {
- switch (get_id.id) {
- case Type::BINARY_VIEW:
- case Type::STRING_VIEW:
- return Generator<Type0, BinaryViewType, Args...>::Exec;
- default:
- ARROW_DCHECK(false);
- return nullptr;
- }
+template <template <typename...> class Generator, typename... Args>
+auto GenerateVarBinaryViewBase(detail::GetTypeId get_id) {
+ return GenerateKernelExec<TypeIdToPhysicalBinary, kBinaryViewLikeTypeIds,
Generator,
+ Args...>(get_id);
}
// Generate a kernel given a templated functor for temporal types
//
// See "Numeric" above for description of the generator functor
-template <template <typename...> class Generator, typename Type0, typename...
Args>
-ArrayKernelExec GenerateTemporal(detail::GetTypeId get_id) {
- switch (get_id.id) {
- case Type::DATE32:
- return Generator<Type0, Date32Type, Args...>::Exec;
- case Type::DATE64:
- return Generator<Type0, Date64Type, Args...>::Exec;
- case Type::DURATION:
- return Generator<Type0, DurationType, Args...>::Exec;
- case Type::TIME32:
- return Generator<Type0, Time32Type, Args...>::Exec;
- case Type::TIME64:
- return Generator<Type0, Time64Type, Args...>::Exec;
- case Type::TIMESTAMP:
- return Generator<Type0, TimestampType, Args...>::Exec;
- default:
- ARROW_DCHECK(false);
- return nullptr;
- }
+template <template <typename...> class Generator, typename... Args>
+auto GenerateTemporal(detail::GetTypeId get_id) {
+ return GenerateKernelExec<array_cat(kTemporalTypeIds,
std::array{Type::DURATION}),
+ Generator, Args...>(get_id);
}
// Generate a kernel given a templated functor for decimal types
//
// See "Numeric" above for description of the generator functor
-template <template <typename...> class Generator, typename Type0, typename...
Args>
+template <template <typename...> class Generator, typename... Args>
auto GenerateDecimal(detail::GetTypeId get_id) {
- using KernelType = decltype(&Generator<Type0, Decimal256Type,
Args...>::Exec);
- switch (get_id.id) {
- case Type::DECIMAL32:
- return Generator<Type0, Decimal32Type, Args...>::Exec;
- case Type::DECIMAL64:
- return Generator<Type0, Decimal64Type, Args...>::Exec;
- case Type::DECIMAL128:
- return Generator<Type0, Decimal128Type, Args...>::Exec;
- case Type::DECIMAL256:
- return Generator<Type0, Decimal256Type, Args...>::Exec;
- default:
- ARROW_DCHECK(false);
- return KernelType(nullptr);
- }
+ return GenerateKernelExec<kDecimalTypeIds, Generator, Args...>(get_id);
}
// END of kernel generator-dispatchers
diff --git a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
index 14dbd5b7e8b..53d4751b8c4 100644
--- a/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_arithmetic.cc
@@ -913,7 +913,7 @@ std::shared_ptr<ScalarFunction>
MakeArithmeticFunction(std::string name,
FunctionDoc doc) {
auto func = std::make_shared<FunctionImpl>(name, Arity::Binary(),
std::move(doc));
for (const auto& ty : NumericTypes()) {
- auto exec = ArithmeticExecFromOp<ScalarBinaryEqualTypes, Op>(ty);
+ auto exec = ArithmeticExec<ScalarBinaryEqualTypes, Op>(ty);
DCHECK_OK(func->AddKernel({ty, ty}, ty, exec));
}
AddNullExec(func.get());
@@ -927,7 +927,7 @@ std::shared_ptr<ScalarFunction>
MakeArithmeticFunctionNotNull(std::string name,
FunctionDoc doc)
{
auto func = std::make_shared<FunctionImpl>(name, Arity::Binary(),
std::move(doc));
for (const auto& ty : NumericTypes()) {
- auto exec = ArithmeticExecFromOp<ScalarBinaryNotNullEqualTypes, Op>(ty);
+ auto exec = ArithmeticExec<ScalarBinaryNotNullEqualTypes, Op>(ty);
DCHECK_OK(func->AddKernel({ty, ty}, ty, exec));
}
AddNullExec(func.get());
@@ -939,7 +939,7 @@ std::shared_ptr<ScalarFunction>
MakeUnaryArithmeticFunction(std::string name,
FunctionDoc doc) {
auto func = std::make_shared<ArithmeticFunction>(name, Arity::Unary(),
std::move(doc));
for (const auto& ty : NumericTypes()) {
- auto exec = ArithmeticExecFromOp<ScalarUnary, Op>(ty);
+ auto exec = ArithmeticExec<ScalarUnary, Op>(ty);
DCHECK_OK(func->AddKernel({ty}, ty, exec));
}
AddNullExec(func.get());
@@ -975,7 +975,7 @@ std::shared_ptr<ScalarFunction>
MakeUnaryArithmeticFunctionNotNull(std::string n
FunctionDoc
doc) {
auto func = std::make_shared<ArithmeticFunction>(name, Arity::Unary(),
std::move(doc));
for (const auto& ty : NumericTypes()) {
- auto exec = ArithmeticExecFromOp<ScalarUnaryNotNull, Op>(ty);
+ auto exec = ArithmeticExec<ScalarUnaryNotNull, Op>(ty);
DCHECK_OK(func->AddKernel({ty}, ty, exec));
}
AddNullExec(func.get());
@@ -990,7 +990,7 @@ std::shared_ptr<ScalarFunction>
MakeUnarySignedArithmeticFunctionNotNull(
auto func = std::make_shared<ArithmeticFunction>(name, Arity::Unary(),
std::move(doc));
for (const auto& ty : NumericTypes()) {
if (!arrow::is_unsigned_integer(ty->id())) {
- auto exec = ArithmeticExecFromOp<ScalarUnaryNotNull, Op>(ty);
+ auto exec = ArithmeticExec<ScalarUnaryNotNull, Op>(ty);
DCHECK_OK(func->AddKernel({ty}, ty, exec));
}
}
@@ -1508,7 +1508,7 @@ void RegisterScalarArithmetic(FunctionRegistry* registry)
{
// abs(duration)
for (auto unit : TimeUnit::values()) {
- auto exec = ArithmeticExecFromOp<ScalarUnary,
AbsoluteValue>(duration(unit));
+ auto exec = ArithmeticExec<ScalarUnary, AbsoluteValue>(duration(unit));
DCHECK_OK(
absolute_value->AddKernel({duration(unit)},
OutputType(duration(unit)), exec));
}
@@ -1521,8 +1521,7 @@ void RegisterScalarArithmetic(FunctionRegistry* registry)
{
AddDecimalUnaryKernels<AbsoluteValueChecked>(absolute_value_checked.get());
// abs_checked(duraton)
for (auto unit : TimeUnit::values()) {
- auto exec =
- ArithmeticExecFromOp<ScalarUnaryNotNull,
AbsoluteValueChecked>(duration(unit));
+ auto exec = ArithmeticExec<ScalarUnaryNotNull,
AbsoluteValueChecked>(duration(unit));
DCHECK_OK(absolute_value_checked->AddKernel({duration(unit)},
OutputType(duration(unit)),
exec));
}
@@ -1543,7 +1542,7 @@ void RegisterScalarArithmetic(FunctionRegistry* registry)
{
// Add add(duration, duration) -> duration
for (auto unit : TimeUnit::values()) {
InputType in_type(match::DurationTypeUnit(unit));
- auto exec = ArithmeticExecFromOp<ScalarBinaryEqualTypes,
Add>(Type::DURATION);
+ auto exec = ArithmeticExec<ScalarBinaryEqualTypes, Add>(Type::DURATION);
DCHECK_OK(add->AddKernel({in_type, in_type}, duration(unit),
std::move(exec)));
}
@@ -1570,7 +1569,7 @@ void RegisterScalarArithmetic(FunctionRegistry* registry)
{
// Add add(duration, duration) -> duration
for (auto unit : TimeUnit::values()) {
InputType in_type(match::DurationTypeUnit(unit));
- auto exec = ArithmeticExecFromOp<ScalarBinaryEqualTypes,
AddChecked>(Type::DURATION);
+ auto exec = ArithmeticExec<ScalarBinaryEqualTypes,
AddChecked>(Type::DURATION);
DCHECK_OK(
add_checked->AddKernel({in_type, in_type}, duration(unit),
std::move(exec)));
}
@@ -1587,7 +1586,7 @@ void RegisterScalarArithmetic(FunctionRegistry* registry)
{
// Add subtract(timestamp, timestamp) -> duration
for (auto unit : TimeUnit::values()) {
InputType in_type(match::TimestampTypeUnit(unit));
- auto exec = ArithmeticExecFromOp<ScalarBinaryEqualTypes,
Subtract>(Type::TIMESTAMP);
+ auto exec = ArithmeticExec<ScalarBinaryEqualTypes,
Subtract>(Type::TIMESTAMP);
DCHECK_OK(subtract->AddKernel({in_type, in_type},
OutputType::Resolver(ResolveTemporalOutput),
std::move(exec)));
@@ -1604,7 +1603,7 @@ void RegisterScalarArithmetic(FunctionRegistry* registry)
{
// Add subtract(duration, duration) -> duration
for (auto unit : TimeUnit::values()) {
InputType in_type(match::DurationTypeUnit(unit));
- auto exec = ArithmeticExecFromOp<ScalarBinaryEqualTypes,
Subtract>(Type::DURATION);
+ auto exec = ArithmeticExec<ScalarBinaryEqualTypes,
Subtract>(Type::DURATION);
DCHECK_OK(subtract->AddKernel({in_type, in_type}, duration(unit),
std::move(exec)));
}
@@ -1646,8 +1645,7 @@ void RegisterScalarArithmetic(FunctionRegistry* registry)
{
// Add subtract_checked(timestamp, timestamp) -> duration
for (auto unit : TimeUnit::values()) {
InputType in_type(match::TimestampTypeUnit(unit));
- auto exec =
- ArithmeticExecFromOp<ScalarBinaryEqualTypes,
SubtractChecked>(Type::TIMESTAMP);
+ auto exec = ArithmeticExec<ScalarBinaryEqualTypes,
SubtractChecked>(Type::TIMESTAMP);
DCHECK_OK(subtract_checked->AddKernel({in_type, in_type},
OutputType::Resolver(ResolveTemporalOutput),
std::move(exec)));
@@ -1664,8 +1662,7 @@ void RegisterScalarArithmetic(FunctionRegistry* registry)
{
// Add subtract_checked(duration, duration) -> duration
for (auto unit : TimeUnit::values()) {
InputType in_type(match::DurationTypeUnit(unit));
- auto exec =
- ArithmeticExecFromOp<ScalarBinaryEqualTypes,
SubtractChecked>(Type::DURATION);
+ auto exec = ArithmeticExec<ScalarBinaryEqualTypes,
SubtractChecked>(Type::DURATION);
DCHECK_OK(
subtract_checked->AddKernel({in_type, in_type}, duration(unit),
std::move(exec)));
}
@@ -1710,7 +1707,7 @@ void RegisterScalarArithmetic(FunctionRegistry* registry)
{
// Add multiply(duration, int64) -> duration
for (auto unit : TimeUnit::values()) {
- auto exec = ArithmeticExecFromOp<ScalarBinaryEqualTypes,
Multiply>(Type::DURATION);
+ auto exec = ArithmeticExec<ScalarBinaryEqualTypes,
Multiply>(Type::DURATION);
DCHECK_OK(multiply->AddKernel({duration(unit), int64()}, duration(unit),
exec));
DCHECK_OK(multiply->AddKernel({int64(), duration(unit)}, duration(unit),
exec));
}
@@ -1724,8 +1721,7 @@ void RegisterScalarArithmetic(FunctionRegistry* registry)
{
// Add multiply_checked(duration, int64) -> duration
for (auto unit : TimeUnit::values()) {
- auto exec =
- ArithmeticExecFromOp<ScalarBinaryEqualTypes,
MultiplyChecked>(Type::DURATION);
+ auto exec = ArithmeticExec<ScalarBinaryEqualTypes,
MultiplyChecked>(Type::DURATION);
DCHECK_OK(
multiply_checked->AddKernel({duration(unit), int64()}, duration(unit),
exec));
DCHECK_OK(
@@ -1805,7 +1801,7 @@ void RegisterScalarArithmetic(FunctionRegistry* registry)
{
// Add neg(duration) -> duration
for (auto unit : TimeUnit::values()) {
- auto exec = ArithmeticExecFromOp<ScalarUnary, Negate>(duration(unit));
+ auto exec = ArithmeticExec<ScalarUnary, Negate>(duration(unit));
DCHECK_OK(negate->AddKernel({duration(unit)}, OutputType(duration(unit)),
exec));
}
@@ -1819,7 +1815,7 @@ void RegisterScalarArithmetic(FunctionRegistry* registry)
{
// Add neg_checked(duration) -> duration
for (auto unit : TimeUnit::values()) {
- auto exec = ArithmeticExecFromOp<ScalarUnaryNotNull,
Negate>(duration(unit));
+ auto exec = ArithmeticExec<ScalarUnaryNotNull, Negate>(duration(unit));
DCHECK_OK(
negate_checked->AddKernel({duration(unit)},
OutputType(duration(unit)), exec));
}
diff --git a/cpp/src/arrow/compute/kernels/scalar_cast_boolean.cc
b/cpp/src/arrow/compute/kernels/scalar_cast_boolean.cc
index 61669e0af0e..c9c3aa3f3f5 100644
--- a/cpp/src/arrow/compute/kernels/scalar_cast_boolean.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_cast_boolean.cc
@@ -55,17 +55,18 @@ std::vector<std::shared_ptr<CastFunction>>
GetBooleanCasts() {
for (const auto& ty : NumericTypes()) {
ArrayKernelExec exec =
- GenerateNumeric<applicator::ScalarUnary, BooleanType, IsNonZero>(*ty);
+ GenerateNumeric<applicator::ScalarUnary, WithType0<BooleanType>,
IsNonZero>(*ty);
DCHECK_OK(func->AddKernel(ty->id(), {ty}, boolean(), exec));
}
for (const auto& ty : BaseBinaryTypes()) {
- ArrayKernelExec exec =
GenerateVarBinaryBase<applicator::ScalarUnaryNotNull,
- BooleanType,
ParseBooleanString>(*ty);
+ ArrayKernelExec exec =
+ GenerateVarBinaryBase<applicator::ScalarUnaryNotNull,
WithType0<BooleanType>,
+ ParseBooleanString>(*ty);
DCHECK_OK(func->AddKernel(ty->id(), {ty}, boolean(), exec));
}
for (const auto& ty : BinaryViewTypes()) {
ArrayKernelExec exec =
- GenerateVarBinaryViewBase<applicator::ScalarUnaryNotNull, BooleanType,
+ GenerateVarBinaryViewBase<applicator::ScalarUnaryNotNull,
WithType0<BooleanType>,
ParseBooleanString>(*ty);
DCHECK_OK(func->AddKernel(ty->id(), {ty}, boolean(), exec));
}
diff --git a/cpp/src/arrow/compute/kernels/scalar_cast_numeric.cc
b/cpp/src/arrow/compute/kernels/scalar_cast_numeric.cc
index ba2a8c4b563..388bf7b9ee6 100644
--- a/cpp/src/arrow/compute/kernels/scalar_cast_numeric.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_cast_numeric.cc
@@ -779,11 +779,11 @@ void AddCommonNumberCasts(const
std::shared_ptr<DataType>& out_ty, CastFunction*
// Cast from other strings
for (const std::shared_ptr<DataType>& in_ty : BaseBinaryTypes()) {
- auto exec = GenerateVarBinaryBase<CastFunctor, OutType>(*in_ty);
+ auto exec = GenerateVarBinaryBase<CastFunctor, WithType0<OutType>>(*in_ty);
DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, out_ty, exec));
}
for (const std::shared_ptr<DataType>& in_ty : BinaryViewTypes()) {
- auto exec = GenerateVarBinaryViewBase<CastFunctor, OutType>(*in_ty);
+ auto exec = GenerateVarBinaryViewBase<CastFunctor,
WithType0<OutType>>(*in_ty);
DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, out_ty, exec));
}
}
@@ -856,136 +856,97 @@ std::shared_ptr<CastFunction>
GetCastToFloating(std::string name) {
return func;
}
-std::shared_ptr<CastFunction> GetCastToDecimal32() {
- OutputType sig_out_ty(ResolveOutputFromOptions);
-
- auto func = std::make_shared<CastFunction>("cast_decimal32",
Type::DECIMAL32);
- AddCommonCasts(Type::DECIMAL32, sig_out_ty, func.get());
-
- // Cast from floating point
- DCHECK_OK(func->AddKernel(Type::FLOAT, {float32()}, sig_out_ty,
- CastFunctor<Decimal32Type, FloatType>::Exec));
- DCHECK_OK(func->AddKernel(Type::DOUBLE, {float64()}, sig_out_ty,
- CastFunctor<Decimal32Type, DoubleType>::Exec));
+std::shared_ptr<CastFunction> GetCastToHalfFloat() {
+ // HalfFloat is a bit brain-damaged for now
+ auto func = std::make_shared<CastFunction>("func", Type::HALF_FLOAT);
+ AddCommonCasts(Type::HALF_FLOAT, float16(), func.get());
- // Cast from integer
+ // Casts from integer to floating point
for (const std::shared_ptr<DataType>& in_ty : IntTypes()) {
- auto exec = GenerateInteger<CastFunctor, Decimal32Type>(in_ty->id());
- DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, sig_out_ty,
std::move(exec)));
+ DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty},
+ TypeTraits<HalfFloatType>::type_singleton(),
+ CastIntegerToFloating));
}
- // Cast from other strings
+ // Cast from other strings to half float.
for (const std::shared_ptr<DataType>& in_ty : BaseBinaryTypes()) {
- auto exec = GenerateVarBinaryBase<CastFunctor, Decimal32Type>(in_ty->id());
- DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, sig_out_ty,
std::move(exec)));
- }
- for (const std::shared_ptr<DataType>& in_ty : BinaryViewTypes()) {
- auto exec = GenerateVarBinaryViewBase<CastFunctor,
Decimal32Type>(in_ty->id());
- DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, sig_out_ty,
std::move(exec)));
+ auto exec = GenerateVarBinaryBase<CastFunctor,
WithType0<HalfFloatType>>(*in_ty);
+ DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty},
+ TypeTraits<HalfFloatType>::type_singleton(),
exec));
}
- // Cast from other decimal
- auto exec = CastFunctor<Decimal32Type, Decimal32Type>::Exec;
- DCHECK_OK(
- func->AddKernel(Type::DECIMAL32, {InputType(Type::DECIMAL32)},
sig_out_ty, exec));
- exec = CastFunctor<Decimal32Type, Decimal64Type>::Exec;
- DCHECK_OK(
- func->AddKernel(Type::DECIMAL64, {InputType(Type::DECIMAL64)},
sig_out_ty, exec));
- exec = CastFunctor<Decimal32Type, Decimal128Type>::Exec;
- DCHECK_OK(
- func->AddKernel(Type::DECIMAL128, {InputType(Type::DECIMAL128)},
sig_out_ty, exec));
- exec = CastFunctor<Decimal32Type, Decimal256Type>::Exec;
- DCHECK_OK(
- func->AddKernel(Type::DECIMAL256, {InputType(Type::DECIMAL256)},
sig_out_ty, exec));
+ DCHECK_OK(func.get()->AddKernel(Type::FLOAT, {InputType(Type::FLOAT)},
float16(),
+ CastFloatingToFloating));
+ DCHECK_OK(func.get()->AddKernel(Type::DOUBLE, {InputType(Type::DOUBLE)},
float16(),
+ CastFloatingToFloating));
return func;
}
-std::shared_ptr<CastFunction> GetCastToDecimal64() {
- OutputType sig_out_ty(ResolveOutputFromOptions);
-
- auto func = std::make_shared<CastFunction>("cast_decimal64",
Type::DECIMAL64);
- AddCommonCasts(Type::DECIMAL64, sig_out_ty, func.get());
-
+template <typename DecimalOutType>
+void AddCommonCastsToDecimal(const OutputType& sig_out_ty, CastFunction* func)
{
// Cast from floating point
DCHECK_OK(func->AddKernel(Type::FLOAT, {float32()}, sig_out_ty,
- CastFunctor<Decimal64Type, FloatType>::Exec));
+ CastFunctor<DecimalOutType, FloatType>::Exec));
DCHECK_OK(func->AddKernel(Type::DOUBLE, {float64()}, sig_out_ty,
- CastFunctor<Decimal64Type, DoubleType>::Exec));
+ CastFunctor<DecimalOutType, DoubleType>::Exec));
// Cast from integer
for (const std::shared_ptr<DataType>& in_ty : IntTypes()) {
- auto exec = GenerateInteger<CastFunctor, Decimal64Type>(in_ty->id());
+ auto exec = GenerateInteger<CastFunctor,
WithType0<DecimalOutType>>(in_ty->id());
DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, sig_out_ty,
std::move(exec)));
}
// Cast from other strings
for (const std::shared_ptr<DataType>& in_ty : BaseBinaryTypes()) {
- auto exec = GenerateVarBinaryBase<CastFunctor, Decimal64Type>(in_ty->id());
+ auto exec =
+ GenerateVarBinaryBase<CastFunctor,
WithType0<DecimalOutType>>(in_ty->id());
DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, sig_out_ty,
std::move(exec)));
}
for (const std::shared_ptr<DataType>& in_ty : BinaryViewTypes()) {
- auto exec = GenerateVarBinaryViewBase<CastFunctor,
Decimal64Type>(in_ty->id());
+ auto exec =
+ GenerateVarBinaryViewBase<CastFunctor,
WithType0<DecimalOutType>>(in_ty->id());
DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, sig_out_ty,
std::move(exec)));
}
// Cast from other decimal
- auto exec = CastFunctor<Decimal64Type, Decimal32Type>::Exec;
+ auto exec = CastFunctor<DecimalOutType, Decimal32Type>::Exec;
DCHECK_OK(
func->AddKernel(Type::DECIMAL32, {InputType(Type::DECIMAL32)},
sig_out_ty, exec));
- exec = CastFunctor<Decimal64Type, Decimal64Type>::Exec;
+ exec = CastFunctor<DecimalOutType, Decimal64Type>::Exec;
DCHECK_OK(
func->AddKernel(Type::DECIMAL64, {InputType(Type::DECIMAL64)},
sig_out_ty, exec));
- exec = CastFunctor<Decimal64Type, Decimal128Type>::Exec;
+ exec = CastFunctor<DecimalOutType, Decimal128Type>::Exec;
DCHECK_OK(
func->AddKernel(Type::DECIMAL128, {InputType(Type::DECIMAL128)},
sig_out_ty, exec));
- exec = CastFunctor<Decimal64Type, Decimal256Type>::Exec;
+ exec = CastFunctor<DecimalOutType, Decimal256Type>::Exec;
DCHECK_OK(
func->AddKernel(Type::DECIMAL256, {InputType(Type::DECIMAL256)},
sig_out_ty, exec));
- return func;
}
-std::shared_ptr<CastFunction> GetCastToDecimal128() {
+std::shared_ptr<CastFunction> GetCastToDecimal32() {
OutputType sig_out_ty(ResolveOutputFromOptions);
- auto func = std::make_shared<CastFunction>("cast_decimal", Type::DECIMAL128);
- AddCommonCasts(Type::DECIMAL128, sig_out_ty, func.get());
+ auto func = std::make_shared<CastFunction>("cast_decimal32",
Type::DECIMAL32);
+ AddCommonCasts(Type::DECIMAL32, sig_out_ty, func.get());
+ AddCommonCastsToDecimal<Decimal32Type>(sig_out_ty, func.get());
+ return func;
+}
- // Cast from floating point
- DCHECK_OK(func->AddKernel(Type::FLOAT, {float32()}, sig_out_ty,
- CastFunctor<Decimal128Type, FloatType>::Exec));
- DCHECK_OK(func->AddKernel(Type::DOUBLE, {float64()}, sig_out_ty,
- CastFunctor<Decimal128Type, DoubleType>::Exec));
+std::shared_ptr<CastFunction> GetCastToDecimal64() {
+ OutputType sig_out_ty(ResolveOutputFromOptions);
- // Cast from integer
- for (const std::shared_ptr<DataType>& in_ty : IntTypes()) {
- auto exec = GenerateInteger<CastFunctor, Decimal128Type>(in_ty->id());
- DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, sig_out_ty,
std::move(exec)));
- }
+ auto func = std::make_shared<CastFunction>("cast_decimal64",
Type::DECIMAL64);
+ AddCommonCasts(Type::DECIMAL64, sig_out_ty, func.get());
+ AddCommonCastsToDecimal<Decimal64Type>(sig_out_ty, func.get());
+ return func;
+}
- // Cast from other strings
- for (const std::shared_ptr<DataType>& in_ty : BaseBinaryTypes()) {
- auto exec = GenerateVarBinaryBase<CastFunctor,
Decimal128Type>(in_ty->id());
- DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, sig_out_ty,
std::move(exec)));
- }
- for (const std::shared_ptr<DataType>& in_ty : BinaryViewTypes()) {
- auto exec = GenerateVarBinaryViewBase<CastFunctor,
Decimal128Type>(in_ty->id());
- DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, sig_out_ty,
std::move(exec)));
- }
+std::shared_ptr<CastFunction> GetCastToDecimal128() {
+ OutputType sig_out_ty(ResolveOutputFromOptions);
- // Cast from other decimal
- auto exec = CastFunctor<Decimal128Type, Decimal32Type>::Exec;
- // We resolve the output type of this kernel from the CastOptions
- DCHECK_OK(
- func->AddKernel(Type::DECIMAL32, {InputType(Type::DECIMAL32)},
sig_out_ty, exec));
- exec = CastFunctor<Decimal128Type, Decimal64Type>::Exec;
- DCHECK_OK(
- func->AddKernel(Type::DECIMAL64, {InputType(Type::DECIMAL64)},
sig_out_ty, exec));
- exec = CastFunctor<Decimal128Type, Decimal128Type>::Exec;
- DCHECK_OK(
- func->AddKernel(Type::DECIMAL128, {InputType(Type::DECIMAL128)},
sig_out_ty, exec));
- exec = CastFunctor<Decimal128Type, Decimal256Type>::Exec;
- DCHECK_OK(
- func->AddKernel(Type::DECIMAL256, {InputType(Type::DECIMAL256)},
sig_out_ty, exec));
+ auto func = std::make_shared<CastFunction>("cast_decimal", Type::DECIMAL128);
+ AddCommonCasts(Type::DECIMAL128, sig_out_ty, func.get());
+ AddCommonCastsToDecimal<Decimal128Type>(sig_out_ty, func.get());
return func;
}
@@ -994,68 +955,7 @@ std::shared_ptr<CastFunction> GetCastToDecimal256() {
auto func = std::make_shared<CastFunction>("cast_decimal256",
Type::DECIMAL256);
AddCommonCasts(Type::DECIMAL256, sig_out_ty, func.get());
-
- // Cast from floating point
- DCHECK_OK(func->AddKernel(Type::FLOAT, {float32()}, sig_out_ty,
- CastFunctor<Decimal256Type, FloatType>::Exec));
- DCHECK_OK(func->AddKernel(Type::DOUBLE, {float64()}, sig_out_ty,
- CastFunctor<Decimal256Type, DoubleType>::Exec));
-
- // Cast from integer
- for (const std::shared_ptr<DataType>& in_ty : IntTypes()) {
- auto exec = GenerateInteger<CastFunctor, Decimal256Type>(in_ty->id());
- DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, sig_out_ty,
std::move(exec)));
- }
-
- // Cast from other strings
- for (const std::shared_ptr<DataType>& in_ty : BaseBinaryTypes()) {
- auto exec = GenerateVarBinaryBase<CastFunctor,
Decimal256Type>(in_ty->id());
- DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, sig_out_ty,
std::move(exec)));
- }
- for (const std::shared_ptr<DataType>& in_ty : BinaryViewTypes()) {
- auto exec = GenerateVarBinaryViewBase<CastFunctor,
Decimal256Type>(in_ty->id());
- DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty}, sig_out_ty,
std::move(exec)));
- }
-
- // Cast from other decimal
- auto exec = CastFunctor<Decimal256Type, Decimal32Type>::Exec;
- DCHECK_OK(
- func->AddKernel(Type::DECIMAL32, {InputType(Type::DECIMAL32)},
sig_out_ty, exec));
- exec = CastFunctor<Decimal256Type, Decimal64Type>::Exec;
- DCHECK_OK(
- func->AddKernel(Type::DECIMAL64, {InputType(Type::DECIMAL64)},
sig_out_ty, exec));
- exec = CastFunctor<Decimal256Type, Decimal128Type>::Exec;
- DCHECK_OK(
- func->AddKernel(Type::DECIMAL128, {InputType(Type::DECIMAL128)},
sig_out_ty, exec));
- exec = CastFunctor<Decimal256Type, Decimal256Type>::Exec;
- DCHECK_OK(
- func->AddKernel(Type::DECIMAL256, {InputType(Type::DECIMAL256)},
sig_out_ty, exec));
- return func;
-}
-
-std::shared_ptr<CastFunction> GetCastToHalfFloat() {
- // HalfFloat is a bit brain-damaged for now
- auto func = std::make_shared<CastFunction>("func", Type::HALF_FLOAT);
- AddCommonCasts(Type::HALF_FLOAT, float16(), func.get());
-
- // Casts from integer to floating point
- for (const std::shared_ptr<DataType>& in_ty : IntTypes()) {
- DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty},
- TypeTraits<HalfFloatType>::type_singleton(),
- CastIntegerToFloating));
- }
-
- // Cast from other strings to half float.
- for (const std::shared_ptr<DataType>& in_ty : BaseBinaryTypes()) {
- auto exec = GenerateVarBinaryBase<CastFunctor, HalfFloatType>(*in_ty);
- DCHECK_OK(func->AddKernel(in_ty->id(), {in_ty},
- TypeTraits<HalfFloatType>::type_singleton(),
exec));
- }
-
- DCHECK_OK(func.get()->AddKernel(Type::FLOAT, {InputType(Type::FLOAT)},
float16(),
- CastFloatingToFloating));
- DCHECK_OK(func.get()->AddKernel(Type::DOUBLE, {InputType(Type::DOUBLE)},
float16(),
- CastFloatingToFloating));
+ AddCommonCastsToDecimal<Decimal256Type>(sig_out_ty, func.get());
return func;
}
diff --git a/cpp/src/arrow/compute/kernels/scalar_cast_string.cc
b/cpp/src/arrow/compute/kernels/scalar_cast_string.cc
index 52b79c8d452..43fe3910f57 100644
--- a/cpp/src/arrow/compute/kernels/scalar_cast_string.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_cast_string.cc
@@ -706,10 +706,10 @@ void AddNumberToStringCasts(CastFunction* func) {
NullHandling::COMPUTED_NO_PREALLOCATE));
for (const std::shared_ptr<DataType>& in_ty : NumericTypes()) {
- DCHECK_OK(
- func->AddKernel(in_ty->id(), {in_ty}, out_ty,
- GenerateNumeric<NumericToStringCastFunctor,
OutType>(*in_ty),
- NullHandling::COMPUTED_NO_PREALLOCATE));
+ DCHECK_OK(func->AddKernel(
+ in_ty->id(), {in_ty}, out_ty,
+ GenerateNumeric<NumericToStringCastFunctor,
WithType0<OutType>>(*in_ty),
+ NullHandling::COMPUTED_NO_PREALLOCATE));
}
DCHECK_OK(func->AddKernel(Type::HALF_FLOAT, {float16()}, out_ty,
@@ -721,10 +721,10 @@ template <typename OutType>
void AddDecimalToStringCasts(CastFunction* func) {
auto out_ty = TypeTraits<OutType>::type_singleton();
for (const auto& in_tid : DecimalTypeIds()) {
- DCHECK_OK(
- func->AddKernel(in_tid, {in_tid}, out_ty,
- GenerateDecimal<DecimalToStringCastFunctor,
OutType>(in_tid),
- NullHandling::COMPUTED_NO_PREALLOCATE));
+ DCHECK_OK(func->AddKernel(
+ in_tid, {in_tid}, out_ty,
+ GenerateDecimal<DecimalToStringCastFunctor,
WithType0<OutType>>(in_tid),
+ NullHandling::COMPUTED_NO_PREALLOCATE));
}
}
@@ -733,10 +733,10 @@ void AddTemporalToStringCasts(CastFunction* func) {
auto out_ty = TypeTraits<OutType>::type_singleton();
for (const auto& types : {TemporalTypes(), DurationTypes()}) {
for (const std::shared_ptr<DataType>& in_ty : types) {
- DCHECK_OK(
- func->AddKernel(in_ty->id(), {InputType(in_ty->id())}, out_ty,
- GenerateTemporal<TemporalToStringCastFunctor,
OutType>(*in_ty),
- NullHandling::COMPUTED_NO_PREALLOCATE));
+ DCHECK_OK(func->AddKernel(
+ in_ty->id(), {InputType(in_ty->id())}, out_ty,
+ GenerateTemporal<TemporalToStringCastFunctor,
WithType0<OutType>>(*in_ty),
+ NullHandling::COMPUTED_NO_PREALLOCATE));
}
}
}
diff --git a/cpp/src/arrow/compute/kernels/scalar_compare.cc
b/cpp/src/arrow/compute/kernels/scalar_compare.cc
index e7f12838c91..d844597e5c7 100644
--- a/cpp/src/arrow/compute/kernels/scalar_compare.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_compare.cc
@@ -311,14 +311,11 @@ ScalarKernel GetCompareKernel(InputType ty, Type::type
compare_type,
ScalarKernel kernel;
kernel.signature = KernelSignature::Make({ty, ty}, boolean());
BinaryKernel func_aa =
- GeneratePhysicalNumericGeneric<BinaryKernel, ComparePrimitiveArrayArray,
Op>(
- compare_type);
+ GeneratePhysicalNumeric<ComparePrimitiveArrayArray, Op>(compare_type);
BinaryKernel func_sa =
- GeneratePhysicalNumericGeneric<BinaryKernel,
ComparePrimitiveScalarArray, Op>(
- compare_type);
+ GeneratePhysicalNumeric<ComparePrimitiveScalarArray, Op>(compare_type);
BinaryKernel func_as =
- GeneratePhysicalNumericGeneric<BinaryKernel,
ComparePrimitiveArrayScalar, Op>(
- compare_type);
+ GeneratePhysicalNumeric<ComparePrimitiveArrayScalar, Op>(compare_type);
kernel.data = std::make_shared<CompareData>(func_aa, func_sa, func_as);
kernel.exec = exec;
return kernel;
@@ -423,19 +420,20 @@ std::shared_ptr<ScalarFunction>
MakeCompareFunction(std::string name, FunctionDo
}
for (const std::shared_ptr<DataType>& ty : BaseBinaryTypes()) {
- auto exec =
- GenerateVarBinaryBase<applicator::ScalarBinaryEqualTypes, BooleanType,
Op>(*ty);
+ auto exec = GenerateVarBinaryBase<applicator::ScalarBinaryEqualTypes,
+ WithType0<BooleanType>, Op>(*ty);
DCHECK_OK(func->AddKernel({ty, ty}, boolean(), std::move(exec)));
}
for (const auto& ty : BinaryViewTypes()) {
- auto exec =
- GenerateVarBinaryViewBase<applicator::ScalarBinaryEqualTypes,
BooleanType, Op>(
- *ty);
+ auto exec = GenerateVarBinaryViewBase<applicator::ScalarBinaryEqualTypes,
+ WithType0<BooleanType>, Op>(*ty);
DCHECK_OK(func->AddKernel({ty, ty}, boolean(), std::move(exec)));
}
for (const auto id : {Type::DECIMAL128, Type::DECIMAL256}) {
- auto exec = GenerateDecimal<applicator::ScalarBinaryEqualTypes,
BooleanType, Op>(id);
+ auto exec =
+ GenerateDecimal<applicator::ScalarBinaryEqualTypes,
WithType0<BooleanType>, Op>(
+ id);
DCHECK_OK(func->AddKernel({InputType(id), InputType(id)}, boolean(),
std::move(exec),
/*init=*/nullptr, DecimalsHaveSameScale()));
}
diff --git a/cpp/src/arrow/compute/kernels/scalar_if_else.cc
b/cpp/src/arrow/compute/kernels/scalar_if_else.cc
index 1d8e6c1f62e..666c0ae93ab 100644
--- a/cpp/src/arrow/compute/kernels/scalar_if_else.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_if_else.cc
@@ -1303,7 +1303,7 @@ void AddPrimitiveIfElseKernels(const
std::shared_ptr<ScalarFunction>& scalar_fun
const std::vector<std::shared_ptr<DataType>>&
types) {
for (auto&& type : types) {
auto exec =
- internal::GenerateTypeAgnosticPrimitive<ResolveIfElseExec,
ArrayKernelExec,
+ internal::GenerateTypeAgnosticPrimitive<ResolveIfElseExec,
/*AllocateMem=*/std::false_type>(*type);
// cond array needs to be boolean always
std::shared_ptr<KernelSignature> sig;
diff --git a/cpp/src/arrow/compute/kernels/scalar_nested.cc
b/cpp/src/arrow/compute/kernels/scalar_nested.cc
index 0df3dc738b0..c5d9624bada 100644
--- a/cpp/src/arrow/compute/kernels/scalar_nested.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_nested.cc
@@ -517,7 +517,8 @@ void AddListElementKernels(ScalarFunction* func) {
auto output = OutputType{ListValuesType};
auto sig = KernelSignature::Make(std::move(inputs), std::move(output),
/*is_varargs=*/false);
- auto scalar_exec = GenerateInteger<Functor,
InListType>({index_type->id()});
+ auto scalar_exec =
+ GenerateInteger<Functor, WithType0<InListType>>({index_type->id()});
ScalarKernel kernel{std::move(sig), std::move(scalar_exec)};
kernel.null_handling = NullHandling::COMPUTED_NO_PREALLOCATE;
kernel.mem_allocation = MemAllocation::NO_PREALLOCATE;
diff --git a/cpp/src/arrow/compute/kernels/scalar_string_ascii.cc
b/cpp/src/arrow/compute/kernels/scalar_string_ascii.cc
index 8e7b626837f..dd3c507ef53 100644
--- a/cpp/src/arrow/compute/kernels/scalar_string_ascii.cc
+++ b/cpp/src/arrow/compute/kernels/scalar_string_ascii.cc
@@ -874,15 +874,13 @@ void AddAsciiStringLength(FunctionRegistry* registry) {
auto func = std::make_shared<ScalarFunction>("binary_length", Arity::Unary(),
binary_length_doc);
for (const auto& ty : {binary(), utf8()}) {
- auto exec =
- GenerateVarBinaryBase<applicator::ScalarUnaryNotNull, Int32Type,
BinaryLength>(
- ty);
+ auto exec = GenerateVarBinaryBase<applicator::ScalarUnaryNotNull,
+ WithType0<Int32Type>, BinaryLength>(ty);
DCHECK_OK(func->AddKernel({ty}, int32(), std::move(exec)));
}
for (const auto& ty : {large_binary(), large_utf8()}) {
- auto exec =
- GenerateVarBinaryBase<applicator::ScalarUnaryNotNull, Int64Type,
BinaryLength>(
- ty);
+ auto exec = GenerateVarBinaryBase<applicator::ScalarUnaryNotNull,
+ WithType0<Int64Type>, BinaryLength>(ty);
DCHECK_OK(func->AddKernel({ty}, int64(), std::move(exec)));
}
DCHECK_OK(func->AddKernel({InputType(Type::FIXED_SIZE_BINARY)}, int32(),
diff --git a/cpp/src/arrow/compute/kernels/vector_array_sort.cc
b/cpp/src/arrow/compute/kernels/vector_array_sort.cc
index 1cfb11286e4..497ecd1ca96 100644
--- a/cpp/src/arrow/compute/kernels/vector_array_sort.cc
+++ b/cpp/src/arrow/compute/kernels/vector_array_sort.cc
@@ -523,6 +523,8 @@ using ArraySortIndicesState =
internal::OptionsWrapper<ArraySortOptions>;
template <typename OutType, typename InType>
struct ArraySortIndices {
+ static_assert(std::is_same_v<UInt64Type, OutType>,
+ "Invalid output type for ArraySortIndices");
using ArrayType = typename TypeTraits<InType>::ArrayType;
static Status Exec(KernelContext* ctx, const ExecSpan& batch, ExecResult*
out) {
@@ -565,29 +567,29 @@ void AddArraySortingKernels(VectorKernel base,
VectorFunction* func) {
// duration type
base.signature = KernelSignature::Make({Type::DURATION}, uint64());
- base.exec = GenerateNumeric<ExecTemplate, UInt64Type>(*int64());
+ base.exec = GenerateNumeric<ExecTemplate, WithType0<UInt64Type>>(*int64());
DCHECK_OK(func->AddKernel(base));
for (const auto& ty : NumericTypes()) {
auto physical_type = GetPhysicalType(ty);
base.signature = KernelSignature::Make({ty}, uint64());
- base.exec = GenerateNumeric<ExecTemplate, UInt64Type>(*physical_type);
+ base.exec = GenerateNumeric<ExecTemplate,
WithType0<UInt64Type>>(*physical_type);
DCHECK_OK(func->AddKernel(base));
}
for (const auto& ty : TemporalTypes()) {
auto physical_type = GetPhysicalType(ty);
base.signature = KernelSignature::Make({ty->id()}, uint64());
- base.exec = GenerateNumeric<ExecTemplate, UInt64Type>(*physical_type);
+ base.exec = GenerateNumeric<ExecTemplate,
WithType0<UInt64Type>>(*physical_type);
DCHECK_OK(func->AddKernel(base));
}
for (const auto id : {Type::DECIMAL128, Type::DECIMAL256}) {
base.signature = KernelSignature::Make({id}, uint64());
- base.exec = GenerateDecimal<ExecTemplate, UInt64Type>(id);
+ base.exec = GenerateDecimal<ExecTemplate, WithType0<UInt64Type>>(id);
DCHECK_OK(func->AddKernel(base));
}
for (const auto& ty : BaseBinaryTypes()) {
base.signature = KernelSignature::Make({ty}, uint64());
- base.exec = GenerateVarBinaryBase<ExecTemplate, UInt64Type>(ty);
+ base.exec = GenerateVarBinaryBase<ExecTemplate, WithType0<UInt64Type>>(ty);
DCHECK_OK(func->AddKernel(base));
}
base.signature = KernelSignature::Make({Type::FIXED_SIZE_BINARY}, uint64());
diff --git a/cpp/src/arrow/compute/kernels/vector_replace.cc
b/cpp/src/arrow/compute/kernels/vector_replace.cc
index 313fbd53c8b..9b42e5d6cbb 100644
--- a/cpp/src/arrow/compute/kernels/vector_replace.cc
+++ b/cpp/src/arrow/compute/kernels/vector_replace.cc
@@ -824,11 +824,10 @@ template <template <class> class Functor, template
<class> class ChunkedFunctor>
void RegisterVectorFunction(FunctionRegistry* registry,
std::shared_ptr<VectorFunction> func) {
auto add_primitive_kernel = [&](detail::GetTypeId get_id) {
- AddKernel(
- get_id.id, Functor<FixedSizeBinaryType>::GetSignature(get_id),
- GenerateTypeAgnosticPrimitive<Functor, ArrayKernelExec>(get_id),
- GenerateTypeAgnosticPrimitive<ChunkedFunctor,
VectorKernel::ChunkedExec>(get_id),
- registry, func.get());
+ AddKernel(get_id.id, Functor<FixedSizeBinaryType>::GetSignature(get_id),
+ GenerateTypeAgnosticPrimitive<Functor>(get_id),
+ GenerateTypeAgnosticPrimitive<ChunkedFunctor>(get_id), registry,
+ func.get());
};
for (const auto& ty : NumericTypes()) {
add_primitive_kernel(ty);
diff --git a/cpp/src/arrow/compute/kernels/vector_statistics.cc
b/cpp/src/arrow/compute/kernels/vector_statistics.cc
index cc2fbc40164..b4aa66e4f8f 100644
--- a/cpp/src/arrow/compute/kernels/vector_statistics.cc
+++ b/cpp/src/arrow/compute/kernels/vector_statistics.cc
@@ -56,8 +56,7 @@ Status ValidateOptions(const WinsorizeOptions& options) {
using WinsorizeState = internal::OptionsWrapper<WinsorizeOptions>;
-// We have a first unused template parameter for compatibility with
GenerateNumeric.
-template <typename Unused, typename Type>
+template <typename Type>
struct Winsorize {
using ArrayType = typename TypeTraits<Type>::ArrayType;
using CType = typename TypeTraits<Type>::CType;
@@ -157,10 +156,10 @@ struct Winsorize {
}
};
-template <typename Unused, typename Type>
+template <typename Type>
struct WinsorizeChunked {
static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) {
- return Winsorize<Unused, Type>::ExecChunked(ctx, batch, out);
+ return Winsorize<Type>::ExecChunked(ctx, batch, out);
}
};
@@ -198,14 +197,14 @@ void RegisterVectorStatistics(FunctionRegistry* registry)
{
for (const auto& ty : NumericTypes()) {
base.signature = KernelSignature::Make({ty->id()},
&ResolveWinsorizeOutput);
- base.exec = GenerateNumeric<Winsorize, /*Unused*/ void>(ty->id());
- base.exec_chunked = GenerateNumeric<WinsorizeChunked, /*Unused*/
void>(ty->id());
+ base.exec = GenerateNumeric<Winsorize>(ty->id());
+ base.exec_chunked = GenerateNumeric<WinsorizeChunked>(ty->id());
DCHECK_OK(winsorize->AddKernel(base));
}
for (auto type_id : DecimalTypeIds()) {
base.signature = KernelSignature::Make({type_id}, &ResolveWinsorizeOutput);
- base.exec = GenerateDecimal<Winsorize, /*Unused*/ void>(type_id);
- base.exec_chunked = GenerateDecimal<WinsorizeChunked, /*Unused*/
void>(type_id);
+ base.exec = GenerateDecimal<Winsorize>(type_id);
+ base.exec_chunked = GenerateDecimal<WinsorizeChunked>(type_id);
DCHECK_OK(winsorize->AddKernel(base));
}
DCHECK_OK(registry->AddFunction(std::move(winsorize)));
diff --git a/cpp/src/arrow/compute/kernels/vector_swizzle.cc
b/cpp/src/arrow/compute/kernels/vector_swizzle.cc
index cf9f5379a69..4fae37c0fc5 100644
--- a/cpp/src/arrow/compute/kernels/vector_swizzle.cc
+++ b/cpp/src/arrow/compute/kernels/vector_swizzle.cc
@@ -242,9 +242,9 @@ struct InversePermutationImpl {
}
};
-template <typename Ignored, typename Type>
+template <typename Type>
struct InversePermutation {
- using ThisType = InversePermutation<Ignored, Type>;
+ using ThisType = InversePermutation<Type>;
using IndexType = Type;
using ShapeType = ArraySpan;
@@ -266,9 +266,9 @@ struct InversePermutation {
}
};
-template <typename Ignored, typename Type>
+template <typename Type>
struct InversePermutationChunked {
- using ThisType = InversePermutationChunked<Ignored, Type>;
+ using ThisType = InversePermutationChunked<Type>;
using IndexType = Type;
using ShapeType = std::shared_ptr<ChunkedArray>;
@@ -307,10 +307,8 @@ void RegisterVectorInversePermutation(FunctionRegistry*
registry) {
KernelSignature::Make({InputType(match::SameTypeId(type_id))},
OutputType(ResolveInversePermutationOutputType));
kernel.init = InversePermutationState::Init;
- kernel.exec = GenerateInteger<InversePermutation, void,
ArrayKernelExec>(type_id);
- kernel.exec_chunked =
- GenerateInteger<InversePermutationChunked, void,
VectorKernel::ChunkedExec>(
- type_id);
+ kernel.exec = GenerateInteger<InversePermutation>(type_id);
+ kernel.exec_chunked = GenerateInteger<InversePermutationChunked>(type_id);
kernel.can_execute_chunkwise = false;
kernel.output_chunked = false;
DCHECK_OK(function->AddKernel(std::move(kernel)));
diff --git a/cpp/src/arrow/type.cc b/cpp/src/arrow/type.cc
index e841f091809..019c52aee99 100644
--- a/cpp/src/arrow/type.cc
+++ b/cpp/src/arrow/type.cc
@@ -55,110 +55,45 @@ namespace arrow {
using internal::checked_cast;
+// XXX Ideally we'd declare those fields `inline` instead, but that doesn't
work
+// with MinGW's gcc.
+// (see
https://github.com/apache/arrow/actions/runs/40679598086/job/122809014205)
constexpr Type::type NullType::type_id;
constexpr Type::type ListType::type_id;
constexpr Type::type LargeListType::type_id;
constexpr Type::type ListViewType::type_id;
constexpr Type::type LargeListViewType::type_id;
-
constexpr Type::type MapType::type_id;
-
constexpr Type::type FixedSizeListType::type_id;
-
constexpr Type::type BinaryType::type_id;
-
constexpr Type::type BinaryViewType::type_id;
-
constexpr Type::type LargeBinaryType::type_id;
-
constexpr Type::type StringType::type_id;
-
constexpr Type::type StringViewType::type_id;
-
constexpr Type::type LargeStringType::type_id;
-
constexpr Type::type FixedSizeBinaryType::type_id;
-
constexpr Type::type StructType::type_id;
-
constexpr Type::type Decimal32Type::type_id;
-
constexpr Type::type Decimal64Type::type_id;
-
constexpr Type::type Decimal128Type::type_id;
-
constexpr Type::type Decimal256Type::type_id;
-
constexpr Type::type SparseUnionType::type_id;
-
constexpr Type::type DenseUnionType::type_id;
-
constexpr Type::type Date32Type::type_id;
-
constexpr Type::type Date64Type::type_id;
-
constexpr Type::type Time32Type::type_id;
-
constexpr Type::type Time64Type::type_id;
-
constexpr Type::type TimestampType::type_id;
-
constexpr Type::type MonthIntervalType::type_id;
-
constexpr Type::type DayTimeIntervalType::type_id;
-
constexpr Type::type MonthDayNanoIntervalType::type_id;
-
constexpr Type::type DurationType::type_id;
-
constexpr Type::type DictionaryType::type_id;
+constexpr Type::type ExtensionType::type_id;
+constexpr Type::type RunEndEncodedType::type_id;
std::vector<Type::type> AllTypeIds() {
- return {Type::NA,
- Type::BOOL,
- Type::INT8,
- Type::INT16,
- Type::INT32,
- Type::INT64,
- Type::UINT8,
- Type::UINT16,
- Type::UINT32,
- Type::UINT64,
- Type::HALF_FLOAT,
- Type::FLOAT,
- Type::DOUBLE,
- Type::DECIMAL32,
- Type::DECIMAL64,
- Type::DECIMAL128,
- Type::DECIMAL256,
- Type::DATE32,
- Type::DATE64,
- Type::TIME32,
- Type::TIME64,
- Type::TIMESTAMP,
- Type::INTERVAL_DAY_TIME,
- Type::INTERVAL_MONTHS,
- Type::DURATION,
- Type::STRING,
- Type::BINARY,
- Type::LARGE_STRING,
- Type::LARGE_BINARY,
- Type::STRING_VIEW,
- Type::BINARY_VIEW,
- Type::FIXED_SIZE_BINARY,
- Type::STRUCT,
- Type::LIST,
- Type::LARGE_LIST,
- Type::LIST_VIEW,
- Type::LARGE_LIST_VIEW,
- Type::FIXED_SIZE_LIST,
- Type::MAP,
- Type::DENSE_UNION,
- Type::SPARSE_UNION,
- Type::DICTIONARY,
- Type::EXTENSION,
- Type::INTERVAL_MONTH_DAY_NANO,
- Type::RUN_END_ENCODED};
+ return std::vector<Type::type>(kAllTypeIds.begin(), kAllTypeIds.end());
}
namespace internal {
@@ -3028,8 +2963,7 @@ std::string FixedSizeListType::ComputeFingerprint() const
{
} else {
ss << 'N';
}
- ss << "[" << list_size_ << "]"
- << "{" << child_fingerprint << "}";
+ ss << "[" << list_size_ << "]" << "{" << child_fingerprint << "}";
return ss.str();
}
return "";
@@ -3548,8 +3482,7 @@ const std::vector<TimeUnit::type>& TimeUnit::values() {
}
const std::vector<Type::type>& DecimalTypeIds() {
- static std::vector<Type::type> type_ids = {Type::DECIMAL32, Type::DECIMAL64,
- Type::DECIMAL128,
Type::DECIMAL256};
+ static std::vector<Type::type> type_ids{kDecimalTypeIds.begin(),
kDecimalTypeIds.end()};
return type_ids;
}
diff --git a/cpp/src/arrow/type_test.cc b/cpp/src/arrow/type_test.cc
index 133afbfa0c5..b46807a74cf 100644
--- a/cpp/src/arrow/type_test.cc
+++ b/cpp/src/arrow/type_test.cc
@@ -49,6 +49,24 @@ using internal::checked_pointer_cast;
TEST(TestTypeId, AllTypeIds) {
const auto all_ids = AllTypeIds();
ASSERT_EQ(static_cast<int>(all_ids.size()), Type::MAX_ID);
+ std::unordered_set<Type::type> distinct_ids(all_ids.begin(), all_ids.end());
+ ASSERT_EQ(distinct_ids.size(), all_ids.size());
+
+ for (const auto id : all_ids) {
+ // Check that all known type ids:
+ // - are supported by VisitTypeId
+ // - have a corresponding `TypeIdTraits` specialization
+ ASSERT_OK(VisitTypeId(id, [id]<typename T>(const T*) {
+ if constexpr (!std::is_same_v<T, DataType>) {
+ EXPECT_EQ(T::type_id, id);
+ using TypeInferredFromId = typename TypeIdTraits<T::type_id>::Type;
+ EXPECT_TRUE((std::is_same_v<T, TypeInferredFromId>));
+ return Status::OK();
+ } else {
+ return Status::Invalid("Unexpectedly got DataType* for id ", id);
+ }
+ }));
+ }
}
TEST(TestTypeSingleton, ParameterFreeTypes) {
diff --git a/cpp/src/arrow/type_traits.h b/cpp/src/arrow/type_traits.h
index fda3e3be12b..d99befd7de6 100644
--- a/cpp/src/arrow/type_traits.h
+++ b/cpp/src/arrow/type_traits.h
@@ -17,9 +17,11 @@
#pragma once
+#include <array>
#include <memory>
#include <string>
#include <type_traits>
+#include <utility>
#include <vector>
#include "arrow/type.h"
@@ -57,6 +59,8 @@ TYPE_ID_TRAIT(STRING, StringType)
TYPE_ID_TRAIT(BINARY, BinaryType)
TYPE_ID_TRAIT(LARGE_STRING, LargeStringType)
TYPE_ID_TRAIT(LARGE_BINARY, LargeBinaryType)
+TYPE_ID_TRAIT(STRING_VIEW, StringViewType)
+TYPE_ID_TRAIT(BINARY_VIEW, BinaryViewType)
TYPE_ID_TRAIT(FIXED_SIZE_BINARY, FixedSizeBinaryType)
TYPE_ID_TRAIT(DATE32, Date32Type)
TYPE_ID_TRAIT(DATE64, Date64Type)
@@ -74,10 +78,13 @@ TYPE_ID_TRAIT(DECIMAL256, Decimal256Type)
TYPE_ID_TRAIT(STRUCT, StructType)
TYPE_ID_TRAIT(LIST, ListType)
TYPE_ID_TRAIT(LARGE_LIST, LargeListType)
+TYPE_ID_TRAIT(LIST_VIEW, ListViewType)
+TYPE_ID_TRAIT(LARGE_LIST_VIEW, LargeListViewType)
TYPE_ID_TRAIT(FIXED_SIZE_LIST, FixedSizeListType)
TYPE_ID_TRAIT(MAP, MapType)
TYPE_ID_TRAIT(DENSE_UNION, DenseUnionType)
TYPE_ID_TRAIT(SPARSE_UNION, SparseUnionType)
+TYPE_ID_TRAIT(RUN_END_ENCODED, RunEndEncodedType)
TYPE_ID_TRAIT(DICTIONARY, DictionaryType)
TYPE_ID_TRAIT(EXTENSION, ExtensionType)
@@ -1018,6 +1025,146 @@ template <typename T, typename R = void>
using enable_if_physical_floating_point =
enable_if_t<is_physical_floating_type<T>::value, R>;
+///
+/// Compile-time collections of type ids, for metaprogramming and other
purposes.
+///
+
+/// \addtogroup type-id-collections
+/// @{
+
+/// A std::array<> of all valid Type::type ids.
+constexpr auto kAllTypeIds = std::array{Type::NA,
+ Type::BOOL,
+ Type::INT8,
+ Type::INT16,
+ Type::INT32,
+ Type::INT64,
+ Type::UINT8,
+ Type::UINT16,
+ Type::UINT32,
+ Type::UINT64,
+ Type::HALF_FLOAT,
+ Type::FLOAT,
+ Type::DOUBLE,
+ Type::DECIMAL32,
+ Type::DECIMAL64,
+ Type::DECIMAL128,
+ Type::DECIMAL256,
+ Type::DATE32,
+ Type::DATE64,
+ Type::TIME32,
+ Type::TIME64,
+ Type::TIMESTAMP,
+ Type::INTERVAL_DAY_TIME,
+ Type::INTERVAL_MONTHS,
+ Type::DURATION,
+ Type::STRING,
+ Type::BINARY,
+ Type::LARGE_STRING,
+ Type::LARGE_BINARY,
+ Type::STRING_VIEW,
+ Type::BINARY_VIEW,
+ Type::FIXED_SIZE_BINARY,
+ Type::STRUCT,
+ Type::LIST,
+ Type::LARGE_LIST,
+ Type::LIST_VIEW,
+ Type::LARGE_LIST_VIEW,
+ Type::FIXED_SIZE_LIST,
+ Type::MAP,
+ Type::DENSE_UNION,
+ Type::SPARSE_UNION,
+ Type::DICTIONARY,
+ Type::EXTENSION,
+ Type::INTERVAL_MONTH_DAY_NANO,
+ Type::RUN_END_ENCODED};
+
+/// A std::array of all integer type ids
+constexpr auto kIntegerTypeIds =
+ std::array{Type::INT8, Type::UINT8, Type::INT16, Type::UINT16,
+ Type::INT32, Type::UINT32, Type::INT64, Type::UINT64};
+
+/// A std::array of all signed integer type ids
+constexpr auto kSignedIntegerTypeIds =
+ std::array{Type::INT8, Type::INT16, Type::INT32, Type::INT64};
+
+/// A std::array of all unsigned integer type ids
+constexpr auto kUnsignedIntegerTypeIds =
+ std::array{Type::UINT8, Type::UINT16, Type::UINT32, Type::UINT64};
+
+/// A std::array of all floating-point type ids
+constexpr auto kFloatingTypeIds = std::array{Type::HALF_FLOAT, Type::FLOAT,
Type::DOUBLE};
+
+/// A std::array of all floating-point type ids, except HALF_FLOAT
+constexpr auto kPhysicalFloatingTypeIds = std::array{Type::FLOAT,
Type::DOUBLE};
+
+/// A std::array of all numeric type ids (except decimals)
+constexpr auto kNumericTypeIds = std::array{
+ Type::INT8, Type::UINT8, Type::INT16, Type::UINT16, Type::INT32,
Type::UINT32,
+ Type::INT64, Type::UINT64, Type::HALF_FLOAT, Type::FLOAT, Type::DOUBLE};
+
+/// A std::array of all decimal type ids
+constexpr auto kDecimalTypeIds =
+ std::array{Type::DECIMAL32, Type::DECIMAL64, Type::DECIMAL128,
Type::DECIMAL256};
+
+/// A std::array of all temporal type ids (dates, times, timestamps)
+constexpr auto kTemporalTypeIds =
+ std::array{Type::DATE32, Type::DATE64, Type::TIME32, Type::TIME64,
Type::TIMESTAMP};
+
+/// A std::array of all date type ids
+constexpr auto kDateTypeIds = std::array{Type::DATE32, Type::DATE64};
+
+/// A std::array of all time type ids
+constexpr auto kTimeTypeIds = std::array{Type::TIME32, Type::TIME64};
+
+/// A std::array of all interval type ids
+constexpr auto kIntervalTypeIds = std::array{
+ Type::INTERVAL_DAY_TIME, Type::INTERVAL_MONTHS,
Type::INTERVAL_MONTH_DAY_NANO};
+
+/// A std::array of all primitive type ids (excluding null, decimals,
binary-like)
+constexpr auto kPrimitiveTypeIds = std::array{Type::BOOL,
+ Type::INT8,
+ Type::UINT8,
+ Type::INT16,
+ Type::UINT16,
+ Type::INT32,
+ Type::UINT32,
+ Type::INT64,
+ Type::UINT64,
+ Type::HALF_FLOAT,
+ Type::FLOAT,
+ Type::DOUBLE,
+ Type::DATE32,
+ Type::DATE64,
+ Type::TIME32,
+ Type::TIME64,
+ Type::TIMESTAMP,
+ Type::DURATION,
+ Type::INTERVAL_DAY_TIME,
+ Type::INTERVAL_MONTHS,
+ Type::INTERVAL_MONTH_DAY_NANO};
+
+/// A std::array of all base-binary-like type ids
+constexpr auto kBaseBinaryLikeTypeIds =
+ std::array{Type::BINARY, Type::LARGE_BINARY, Type::STRING,
Type::LARGE_STRING};
+
+/// A std::array of all binary-view-like type ids
+constexpr auto kBinaryViewLikeTypeIds = std::array{Type::BINARY_VIEW,
Type::STRING_VIEW};
+
+/// @}
+
+namespace detail {
+
+template <typename T, size_t N>
+constexpr bool array_contains(const std::array<T, N>& array, T value) {
+ auto impl = [&]<std::size_t... I>(std::index_sequence<I...>) {
+ return ((std::get<I>(array) == value) || ...);
+ }; // NOLINT(readability/braces)
+ return impl(std::make_index_sequence<N>{});
+}
+
+} // namespace detail
+
/// @}
/// \addtogroup runtime-type-predicates
@@ -1028,20 +1175,7 @@ using enable_if_physical_floating_point =
/// \param[in] type_id the type-id to check
/// \return whether type-id is an integer type one
constexpr bool is_integer(Type::type type_id) {
- switch (type_id) {
- case Type::UINT8:
- case Type::INT8:
- case Type::UINT16:
- case Type::INT16:
- case Type::UINT32:
- case Type::INT32:
- case Type::UINT64:
- case Type::INT64:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kIntegerTypeIds, type_id);
}
/// \brief Check for a signed integer type
@@ -1049,16 +1183,7 @@ constexpr bool is_integer(Type::type type_id) {
/// \param[in] type_id the type-id to check
/// \return whether type-id is a signed integer type one
constexpr bool is_signed_integer(Type::type type_id) {
- switch (type_id) {
- case Type::INT8:
- case Type::INT16:
- case Type::INT32:
- case Type::INT64:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kSignedIntegerTypeIds, type_id);
}
/// \brief Check for an unsigned integer type
@@ -1066,16 +1191,7 @@ constexpr bool is_signed_integer(Type::type type_id) {
/// \param[in] type_id the type-id to check
/// \return whether type-id is an unsigned integer type one
constexpr bool is_unsigned_integer(Type::type type_id) {
- switch (type_id) {
- case Type::UINT8:
- case Type::UINT16:
- case Type::UINT32:
- case Type::UINT64:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kUnsignedIntegerTypeIds, type_id);
}
/// \brief Check for a floating point type
@@ -1083,22 +1199,14 @@ constexpr bool is_unsigned_integer(Type::type type_id) {
/// \param[in] type_id the type-id to check
/// \return whether type-id is a floating point type one
constexpr bool is_floating(Type::type type_id) {
- switch (type_id) {
- case Type::HALF_FLOAT:
- case Type::FLOAT:
- case Type::DOUBLE:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kFloatingTypeIds, type_id);
}
/// \brief Check for a physical floating point type
///
/// This predicate matches floating-point types, except half-float.
constexpr bool is_physical_floating(Type::type type_id) {
- return is_floating(type_id) && type_id != Type::HALF_FLOAT;
+ return detail::array_contains(kPhysicalFloatingTypeIds, type_id);
}
/// \brief Check for a numeric type
@@ -1108,23 +1216,7 @@ constexpr bool is_physical_floating(Type::type type_id) {
/// \param[in] type_id the type-id to check
/// \return whether type-id is a numeric type one
constexpr bool is_numeric(Type::type type_id) {
- switch (type_id) {
- case Type::UINT8:
- case Type::INT8:
- case Type::UINT16:
- case Type::INT16:
- case Type::UINT32:
- case Type::INT32:
- case Type::UINT64:
- case Type::INT64:
- case Type::HALF_FLOAT:
- case Type::FLOAT:
- case Type::DOUBLE:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kNumericTypeIds, type_id);
}
/// \brief Check for a decimal type
@@ -1132,16 +1224,7 @@ constexpr bool is_numeric(Type::type type_id) {
/// \param[in] type_id the type-id to check
/// \return whether type-id is a decimal type one
constexpr bool is_decimal(Type::type type_id) {
- switch (type_id) {
- case Type::DECIMAL32:
- case Type::DECIMAL64:
- case Type::DECIMAL128:
- case Type::DECIMAL256:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kDecimalTypeIds, type_id);
}
/// \brief Check for a type that can be used as a run-end in Run-End Encoded
@@ -1168,33 +1251,7 @@ constexpr bool is_run_end_type(Type::type type_id) {
/// \param[in] type_id the type-id to check
/// \return whether type-id is a primitive type one
constexpr bool is_primitive(Type::type type_id) {
- switch (type_id) {
- case Type::BOOL:
- case Type::UINT8:
- case Type::INT8:
- case Type::UINT16:
- case Type::INT16:
- case Type::UINT32:
- case Type::INT32:
- case Type::UINT64:
- case Type::INT64:
- case Type::HALF_FLOAT:
- case Type::FLOAT:
- case Type::DOUBLE:
- case Type::DATE32:
- case Type::DATE64:
- case Type::TIME32:
- case Type::TIME64:
- case Type::TIMESTAMP:
- case Type::DURATION:
- case Type::INTERVAL_MONTHS:
- case Type::INTERVAL_MONTH_DAY_NANO:
- case Type::INTERVAL_DAY_TIME:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kPrimitiveTypeIds, type_id);
}
/// \brief Check for a base-binary-like type
@@ -1205,16 +1262,7 @@ constexpr bool is_primitive(Type::type type_id) {
/// \param[in] type_id the type-id to check
/// \return whether type-id is a base-binary-like type one
constexpr bool is_base_binary_like(Type::type type_id) {
- switch (type_id) {
- case Type::BINARY:
- case Type::LARGE_BINARY:
- case Type::STRING:
- case Type::LARGE_STRING:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kBaseBinaryLikeTypeIds, type_id);
}
/// \brief Check for a binary-like type (i.e. with 32-bit offsets)
@@ -1314,14 +1362,7 @@ constexpr bool is_string_or_string_view(Type::type
type_id) {
/// \param[in] type_id the type-id to check
/// \return whether type-id is a binary-view-like type one
constexpr bool is_binary_view_like(Type::type type_id) {
- switch (type_id) {
- case Type::STRING_VIEW:
- case Type::BINARY_VIEW:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kBinaryViewLikeTypeIds, type_id);
}
/// \brief Check for a temporal type
@@ -1329,17 +1370,7 @@ constexpr bool is_binary_view_like(Type::type type_id) {
/// \param[in] type_id the type-id to check
/// \return whether type-id is a temporal type one
constexpr bool is_temporal(Type::type type_id) {
- switch (type_id) {
- case Type::DATE32:
- case Type::DATE64:
- case Type::TIME32:
- case Type::TIME64:
- case Type::TIMESTAMP:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kTemporalTypeIds, type_id);
}
/// \brief Check for a time type
@@ -1347,14 +1378,7 @@ constexpr bool is_temporal(Type::type type_id) {
/// \param[in] type_id the type-id to check
/// \return whether type-id is a primitive type one
constexpr bool is_time(Type::type type_id) {
- switch (type_id) {
- case Type::TIME32:
- case Type::TIME64:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kTimeTypeIds, type_id);
}
/// \brief Check for a date type
@@ -1362,14 +1386,7 @@ constexpr bool is_time(Type::type type_id) {
/// \param[in] type_id the type-id to check
/// \return whether type-id is a primitive type one
constexpr bool is_date(Type::type type_id) {
- switch (type_id) {
- case Type::DATE32:
- case Type::DATE64:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kDateTypeIds, type_id);
}
/// \brief Check for an interval type
@@ -1377,15 +1394,7 @@ constexpr bool is_date(Type::type type_id) {
/// \param[in] type_id the type-id to check
/// \return whether type-id is an interval type one
constexpr bool is_interval(Type::type type_id) {
- switch (type_id) {
- case Type::INTERVAL_MONTHS:
- case Type::INTERVAL_DAY_TIME:
- case Type::INTERVAL_MONTH_DAY_NANO:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kIntervalTypeIds, type_id);
}
/// \brief Check for a dictionary type
@@ -1400,17 +1409,8 @@ constexpr bool is_dictionary(Type::type type_id) {
return type_id == Type::DICTI
/// \param[in] type_id the type-id to check
/// \return whether type-id is a fixed-size-binary type one
constexpr bool is_fixed_size_binary(Type::type type_id) {
- switch (type_id) {
- case Type::DECIMAL32:
- case Type::DECIMAL64:
- case Type::DECIMAL128:
- case Type::DECIMAL256:
- case Type::FIXED_SIZE_BINARY:
- return true;
- default:
- break;
- }
- return false;
+ return detail::array_contains(kDecimalTypeIds, type_id) ||
+ type_id == Type::FIXED_SIZE_BINARY;
}
/// \brief Check for a fixed-width type