Skip to content

Commit

Permalink
[FEA] Create ListSeries from JS Arrays, add ListSeries.getValue() (
Browse files Browse the repository at this point in the history
…#187)

* move get_scalar_element to its own header, add support for (eventual) libcudf list_scalar

* uncomment getValue list test

* move getValue/setValue into specialized subclasses

* Create List series from JS Arrays

* move set_scalar_value functor to utilities/value_to_scalar.hpp, remove test for ListSeries.setValue until cuDF supports scatter for list_scalar
  • Loading branch information
trxcllnt authored May 11, 2021
1 parent 92b5ebb commit c9360dd
Show file tree
Hide file tree
Showing 11 changed files with 474 additions and 199 deletions.
88 changes: 2 additions & 86 deletions modules/cudf/src/node_cudf/utilities/cpp_to_napi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#pragma once

#include "scalar_to_value.hpp"

#include <nv_node/utilities/cpp_to_napi.hpp>

#include <cudf/scalar/scalar.hpp>
Expand Down Expand Up @@ -82,87 +84,6 @@ inline Napi::Value CPPToNapi::operator()(cudf::timestamp_ns const& val) const {
return (*this)(val.time_since_epoch());
}

namespace detail {

struct get_scalar_value {
Napi::Env env;
template <typename T>
inline std::enable_if_t<cudf::is_index_type<T>(), Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
if (!scalar->is_valid(stream)) { return env.Null(); }
switch (scalar->type().id()) {
case cudf::type_id::INT64:
return Napi::BigInt::New(
env, static_cast<cudf::numeric_scalar<int64_t>*>(scalar.get())->value(stream));
case cudf::type_id::UINT64:
return Napi::BigInt::New(
env, static_cast<cudf::numeric_scalar<uint64_t>*>(scalar.get())->value(stream));
default:
return Napi::Number::New(
env, static_cast<cudf::numeric_scalar<T>*>(scalar.get())->value(stream));
}
}
template <typename T>
inline std::enable_if_t<cudf::is_floating_point<T>(), Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
return scalar->is_valid(stream)
? Napi::Number::New(env,
static_cast<cudf::numeric_scalar<T>*>(scalar.get())->value(stream))
: env.Null();
}
template <typename T>
inline std::enable_if_t<std::is_same<T, bool>::value, Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
return scalar->is_valid(stream)
? Napi::Boolean::New(
env, static_cast<cudf::numeric_scalar<bool>*>(scalar.get())->value(stream))
: env.Null();
}
template <typename T>
inline std::enable_if_t<std::is_same<T, cudf::string_view>::value, Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
return scalar->is_valid(stream)
? CPPToNapi(env)(static_cast<cudf::string_scalar*>(scalar.get())->to_string(stream))
: env.Null();
}
template <typename T>
inline std::enable_if_t<cudf::is_duration<T>(), Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
return scalar->is_valid(stream)
? CPPToNapi(env)(static_cast<cudf::duration_scalar<T>*>(scalar.get())->value(stream))
: env.Null();
}
template <typename T>
inline std::enable_if_t<cudf::is_timestamp<T>(), Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
return scalar->is_valid(stream)
? CPPToNapi(env)(static_cast<cudf::timestamp_scalar<T>*>(scalar.get())->value(stream))
: env.Null();
}
template <typename T>
inline std::enable_if_t<cudf::is_fixed_point<T>(), Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
return scalar->is_valid(stream)
? CPPToNapi(env)(
static_cast<cudf::fixed_point_scalar<T>*>(scalar.get())->value(stream))
: env.Null();
}
template <typename T>
inline std::enable_if_t<!(cudf::is_index_type<T>() || //
cudf::is_floating_point<T>() || //
std::is_same<T, bool>::value || //
std::is_same<T, cudf::string_view>::value || //
cudf::is_duration<T>() || //
cudf::is_timestamp<T>() || //
cudf::is_fixed_point<T>()),
Napi::Value>
operator()(std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
NAPI_THROW(Napi::Error::New(env, "Unsupported dtype"));
}
};

} // namespace detail

template <>
inline Napi::Value CPPToNapi::operator()(std::unique_ptr<cudf::scalar> const& scalar) const {
return cudf::type_dispatcher(scalar->type(), detail::get_scalar_value{Env()}, scalar);
Expand Down Expand Up @@ -227,9 +148,4 @@ inline Value Value::From(napi_env env, cudf::timestamp_ns const& val) {
return Value::From(env, val.time_since_epoch());
}

template <>
inline Value Value::From(napi_env env, std::unique_ptr<cudf::scalar> const& scalar) {
return cudf::type_dispatcher(scalar->type(), nv::detail::get_scalar_value{env}, scalar);
}

} // namespace Napi
132 changes: 132 additions & 0 deletions modules/cudf/src/node_cudf/utilities/scalar_to_value.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Copyright (c) 2021, NVIDIA CORPORATION.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <node_cudf/column.hpp>

#include <cudf/scalar/scalar.hpp>
#include <cudf/types.hpp>
#include <cudf/utilities/traits.hpp>
#include <cudf/utilities/type_dispatcher.hpp>
#include <cudf/wrappers/durations.hpp>
#include <cudf/wrappers/timestamps.hpp>

#include <napi.h>

namespace nv {
namespace detail {

struct get_scalar_value {
Napi::Env env;
template <typename T>
inline std::enable_if_t<cudf::is_index_type<T>(), Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
if (!scalar->is_valid(stream)) { return env.Null(); }
switch (scalar->type().id()) {
case cudf::type_id::INT64:
return Napi::BigInt::New(
env, static_cast<cudf::numeric_scalar<int64_t>*>(scalar.get())->value(stream));
case cudf::type_id::UINT64:
return Napi::BigInt::New(
env, static_cast<cudf::numeric_scalar<uint64_t>*>(scalar.get())->value(stream));
default:
return Napi::Number::New(
env, static_cast<cudf::numeric_scalar<T>*>(scalar.get())->value(stream));
}
}
template <typename T>
inline std::enable_if_t<cudf::is_floating_point<T>(), Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
return scalar->is_valid(stream)
? Napi::Number::New(env,
static_cast<cudf::numeric_scalar<T>*>(scalar.get())->value(stream))
: env.Null();
}
template <typename T>
inline std::enable_if_t<std::is_same<T, bool>::value, Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
return scalar->is_valid(stream)
? Napi::Boolean::New(
env, static_cast<cudf::numeric_scalar<bool>*>(scalar.get())->value(stream))
: env.Null();
}
template <typename T>
inline std::enable_if_t<std::is_same<T, cudf::string_view>::value, Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
return scalar->is_valid(stream)
? CPPToNapi(env)(static_cast<cudf::string_scalar*>(scalar.get())->to_string(stream))
: env.Null();
}
template <typename T>
inline std::enable_if_t<cudf::is_duration<T>(), Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
return scalar->is_valid(stream)
? CPPToNapi(env)(static_cast<cudf::duration_scalar<T>*>(scalar.get())->value(stream))
: env.Null();
}
template <typename T>
inline std::enable_if_t<cudf::is_timestamp<T>(), Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
return scalar->is_valid(stream)
? CPPToNapi(env)(static_cast<cudf::timestamp_scalar<T>*>(scalar.get())->value(stream))
: env.Null();
}
template <typename T>
inline std::enable_if_t<cudf::is_fixed_point<T>(), Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
return scalar->is_valid(stream)
? CPPToNapi(env)(
static_cast<cudf::fixed_point_scalar<T>*>(scalar.get())->value(stream))
: env.Null();
}
template <typename T>
inline std::enable_if_t<std::is_same<T, cudf::list_view>::value, Napi::Value> operator()(
std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
return scalar->is_valid(stream)
? Column::New(env,
std::make_unique<cudf::column>(
// The list_scalar's view is copied here because its underlying column
// cannot be moved.
static_cast<cudf::list_scalar*>(scalar.get())->view(),
stream))
: env.Null();
}
template <typename T>
inline std::enable_if_t<!(cudf::is_index_type<T>() || //
cudf::is_floating_point<T>() || //
std::is_same<T, bool>::value || //
std::is_same<T, cudf::string_view>::value || //
cudf::is_duration<T>() || //
cudf::is_timestamp<T>() || //
cudf::is_fixed_point<T>() || //
std::is_same<T, cudf::list_view>::value),
Napi::Value>
operator()(std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
NAPI_THROW(Napi::Error::New(env, "Unsupported dtype"));
}
};

} // namespace detail

} // namespace nv

namespace Napi {

template <>
inline Value Value::From(napi_env env, std::unique_ptr<cudf::scalar> const& scalar) {
return cudf::type_dispatcher(scalar->type(), nv::detail::get_scalar_value{env}, scalar);
}

} // namespace Napi
74 changes: 74 additions & 0 deletions modules/cudf/src/node_cudf/utilities/value_to_scalar.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) 2021, NVIDIA CORPORATION.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <node_cudf/column.hpp>

#include <cudf/types.hpp>
#include <cudf/utilities/traits.hpp>

#include <napi.h>

namespace nv {
namespace detail {

struct set_scalar_value {
Napi::Value val;

template <typename T>
inline std::enable_if_t<cudf::is_numeric<T>(), void> operator()(
std::unique_ptr<cudf::scalar>& scalar, cudaStream_t stream = 0) {
static_cast<cudf::numeric_scalar<T>*>(scalar.get())->set_value(NapiToCPP(val), stream);
}
template <typename T>
inline std::enable_if_t<std::is_same<T, cudf::string_view>::value, void> operator()(
std::unique_ptr<cudf::scalar>& scalar, cudaStream_t stream = 0) {
scalar.reset(new cudf::string_scalar(val.ToString(), true, stream));
}
template <typename T>
inline std::enable_if_t<cudf::is_duration<T>(), void> operator()(
std::unique_ptr<cudf::scalar>& scalar, cudaStream_t stream = 0) {
static_cast<cudf::duration_scalar<T>*>(scalar.get())->set_value(NapiToCPP(val), stream);
}
template <typename T>
inline std::enable_if_t<cudf::is_timestamp<T>(), void> operator()(
std::unique_ptr<cudf::scalar>& scalar, cudaStream_t stream = 0) {
static_cast<cudf::timestamp_scalar<T>*>(scalar.get())->set_value(NapiToCPP(val), stream);
}
template <typename T>
inline std::enable_if_t<cudf::is_fixed_point<T>(), void> operator()(
std::unique_ptr<cudf::scalar>& scalar, cudaStream_t stream = 0) {
scalar.reset(new cudf::fixed_point_scalar<T>(val.ToNumber(), true, stream));
}
template <typename T>
inline std::enable_if_t<std::is_same<T, cudf::list_view>::value, void> operator()(
std::unique_ptr<cudf::scalar>& scalar, cudaStream_t stream = 0) {
scalar.reset(new cudf::list_scalar(*Column::Unwrap(val.ToObject()), true, stream));
}
template <typename T>
inline std::enable_if_t<!(cudf::is_numeric<T>() || //
std::is_same<T, cudf::string_view>::value || //
cudf::is_duration<T>() || //
cudf::is_timestamp<T>() || //
cudf::is_fixed_point<T>() || //
std::is_same<T, cudf::list_view>::value),
void>
operator()(std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
NAPI_THROW(Napi::Error::New(val.Env(), "Unsupported dtype"));
}
};

} // namespace detail
} // namespace nv
47 changes: 2 additions & 45 deletions modules/cudf/src/scalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <node_cudf/utilities/cpp_to_napi.hpp>
#include <node_cudf/utilities/dtypes.hpp>
#include <node_cudf/utilities/napi_to_cpp.hpp>
#include <node_cudf/utilities/value_to_scalar.hpp>

#include <node_cuda/utilities/error.hpp>
#include <node_cuda/utilities/napi_to_cpp.hpp>
Expand All @@ -34,50 +35,6 @@

namespace nv {

namespace {

struct set_scalar_value {
Napi::Value val;

template <typename T>
inline std::enable_if_t<cudf::is_numeric<T>(), void> operator()(
std::unique_ptr<cudf::scalar>& scalar, cudaStream_t stream = 0) {
static_cast<cudf::numeric_scalar<T>*>(scalar.get())->set_value(NapiToCPP(val), stream);
}
template <typename T>
inline std::enable_if_t<std::is_same<T, cudf::string_view>::value, void> operator()(
std::unique_ptr<cudf::scalar>& scalar, cudaStream_t stream = 0) {
scalar.reset(new cudf::string_scalar(val.ToString(), true, stream));
}
template <typename T>
inline std::enable_if_t<cudf::is_duration<T>(), void> operator()(
std::unique_ptr<cudf::scalar>& scalar, cudaStream_t stream = 0) {
static_cast<cudf::duration_scalar<T>*>(scalar.get())->set_value(NapiToCPP(val), stream);
}
template <typename T>
inline std::enable_if_t<cudf::is_timestamp<T>(), void> operator()(
std::unique_ptr<cudf::scalar>& scalar, cudaStream_t stream = 0) {
static_cast<cudf::timestamp_scalar<T>*>(scalar.get())->set_value(NapiToCPP(val), stream);
}
template <typename T>
inline std::enable_if_t<cudf::is_fixed_point<T>(), void> operator()(
std::unique_ptr<cudf::scalar>& scalar, cudaStream_t stream = 0) {
scalar.reset(new cudf::fixed_point_scalar<T>(val.ToNumber(), true, stream));
}
template <typename T>
inline std::enable_if_t<!(cudf::is_numeric<T>() || //
std::is_same<T, cudf::string_view>::value || //
cudf::is_duration<T>() || //
cudf::is_timestamp<T>() || //
cudf::is_fixed_point<T>()),
void>
operator()(std::unique_ptr<cudf::scalar> const& scalar, cudaStream_t stream = 0) {
NAPI_THROW(Napi::Error::New(val.Env(), "Unsupported dtype"));
}
};

} // namespace

Napi::Function Scalar::Init(Napi::Env const& env, Napi::Object exports) {
return DefineClass(
env,
Expand Down Expand Up @@ -145,7 +102,7 @@ void Scalar::set_value(Napi::CallbackInfo const& info, Napi::Value const& value)
if (value.IsNull() or value.IsUndefined()) {
this->set_valid(false);
} else {
cudf::type_dispatcher(this->type(), set_scalar_value{value}, scalar_);
cudf::type_dispatcher(this->type(), detail::set_scalar_value{value}, scalar_);
}
}

Expand Down
Loading

0 comments on commit c9360dd

Please sign in to comment.