diff --git a/NAMESPACE b/NAMESPACE index 75f6600..9983327 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -96,6 +96,7 @@ export(unlisted_length) export(unused_levels) export(used_levels) export(val_count) +export(vector_length) export(which_) export(which_na) export(which_not_na) diff --git a/NEWS.md b/NEWS.md index 4e4efd7..c469183 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,9 @@ # cheapr (Development version) +* New function `na_insert` to randomly insert `NA` values into a vector. + +* New function `vector_length` as a hybrid between `length` and `nrow`. + * Limited support added for 'integer64' objects. This applies to the `NA` related functions as well as the GCD and LCM functions. diff --git a/R/cpp11.R b/R/cpp11.R index 10430e5..885b791 100644 --- a/R/cpp11.R +++ b/R/cpp11.R @@ -244,8 +244,8 @@ cpp_numeric_to_int64 <- function(x) { .Call(`_cheapr_cpp_numeric_to_int64`, x) } -cpp_format_double_as_int64 <- function(x) { - .Call(`_cheapr_cpp_format_double_as_int64`, x) +cpp_format_numeric_as_int64 <- function(x) { + .Call(`_cheapr_cpp_format_numeric_as_int64`, x) } cpp_which_ <- function(x, invert) { diff --git a/R/extras.R b/R/extras.R index c19777e..099a549 100644 --- a/R/extras.R +++ b/R/extras.R @@ -37,6 +37,10 @@ #' `sample_()` is an alternative to `sample()` that natively samples #' data frame rows through `sset()`. It also does not have a special case when #' `length(x)` is 1. \cr +#' `na_insert` inserts `NA` values randomly into your vector. +#' Useful for generating missing data. \cr +#' `vector_length` behaves mostly like `NROW()` except +#' for matrices in which it matches `length()`. #' #' @details #' `intersect_()` and `setdiff_()` are faster and more efficient @@ -207,6 +211,10 @@ na_insert <- function(x, n = NULL, prop = NULL){ } x } +#' @export +#' @rdname extras +vector_length <- cpp_vec_length + # head_ <- function(x, n = 1L){ # check_length(n, 1L) # N <- cpp_vec_length(x) diff --git a/R/factors.R b/R/factors.R index 2dd2dbf..c958880 100644 --- a/R/factors.R +++ b/R/factors.R @@ -77,7 +77,7 @@ factor_ <- function( } else if (is_int64){ # fct_lvls <- formatC(lvls, format = "f", drop0trailing = TRUE) # fct_lvls <- format(lvls, scientific = FALSE, trim = TRUE) - fct_lvls <- cpp_format_double_as_int64(lvls) + fct_lvls <- cpp_format_numeric_as_int64(lvls) } else { fct_lvls <- as.character(lvls) } @@ -222,3 +222,9 @@ levels_reorder <- function(x, order_by, decreasing = FALSE){ factor_(x, levels = ordered_levels) } } +# Generic factor conversion to data representation +factor_as_type <- function(x, type){ + check_length(type, 1) + + do.call(paste0("as.", type), list(levels(x)))[unclass(x)] +} diff --git a/man/extras.Rd b/man/extras.Rd index bca835d..0feeb1a 100644 --- a/man/extras.Rd +++ b/man/extras.Rd @@ -12,6 +12,7 @@ \alias{na_rm} \alias{sample_} \alias{na_insert} +\alias{vector_length} \title{Extra utilities} \usage{ setdiff_(x, y, dups = TRUE) @@ -53,6 +54,8 @@ na_rm(x) sample_(x, size = cpp_vec_length(x), replace = FALSE, prob = NULL) na_insert(x, n = NULL, prop = NULL) + +vector_length(x) } \arguments{ \item{x}{A vector or data frame.} @@ -109,6 +112,10 @@ For more advanced \code{NA} handling, see \code{?is_na}. \cr \code{sample_()} is an alternative to \code{sample()} that natively samples data frame rows through \code{sset()}. It also does not have a special case when \code{length(x)} is 1. \cr +\code{na_insert} inserts \code{NA} values randomly into your vector. +Useful for generating missing data. \cr +\code{vector_length} behaves mostly like \code{NROW()} except +for matrices in which it matches \code{length()}. } \description{ Extra utilities diff --git a/src/cheapr_cpp.h b/src/cheapr_cpp.h index d02e831..c706df4 100644 --- a/src/cheapr_cpp.h +++ b/src/cheapr_cpp.h @@ -63,6 +63,19 @@ #define cheapr_is_na_int64(x) ((bool) (x == NA_INTEGER64)) #endif +#ifndef CHEAPR_INT_TO_INT64 +#define CHEAPR_INT_TO_INT64(x) ((long long int) (x == NA_INTEGER ? NA_INTEGER64 : x)) +#endif +#ifndef CHEAPR_DBL_TO_INT64 +#define CHEAPR_DBL_TO_INT64(x) ((long long int) (x != x ? NA_INTEGER64 : x)) +#endif +#ifndef CHEAPR_INT64_TO_INT +#define CHEAPR_INT64_TO_INT(x) ((int) (x == NA_INTEGER64 ? NA_INTEGER : x)) +#endif +#ifndef CHEAPR_INT64_TO_DBL +#define CHEAPR_INT64_TO_DBL(x) ((double) (x == NA_INTEGER64 ? NA_REAL : x)) +#endif + #ifndef CHEAPR_OMP_THRESHOLD #define CHEAPR_OMP_THRESHOLD 100000 #endif diff --git a/src/cpp11.cpp b/src/cpp11.cpp index 42358a9..d069092 100644 --- a/src/cpp11.cpp +++ b/src/cpp11.cpp @@ -433,10 +433,10 @@ extern "C" SEXP _cheapr_cpp_numeric_to_int64(SEXP x) { END_CPP11 } // utils.cpp -SEXP cpp_format_double_as_int64(SEXP x); -extern "C" SEXP _cheapr_cpp_format_double_as_int64(SEXP x) { +SEXP cpp_format_numeric_as_int64(SEXP x); +extern "C" SEXP _cheapr_cpp_format_numeric_as_int64(SEXP x) { BEGIN_CPP11 - return cpp11::as_sexp(cpp_format_double_as_int64(cpp11::as_cpp>(x))); + return cpp11::as_sexp(cpp_format_numeric_as_int64(cpp11::as_cpp>(x))); END_CPP11 } // which.cpp @@ -470,72 +470,72 @@ extern "C" SEXP _cheapr_cpp_which_not_na(SEXP x) { extern "C" { static const R_CallMethodDef CallEntries[] = { - {"_cheapr_compact_seq_data", (DL_FUNC) &_cheapr_compact_seq_data, 1}, - {"_cheapr_cpp_all_na", (DL_FUNC) &_cheapr_cpp_all_na, 3}, - {"_cheapr_cpp_any_na", (DL_FUNC) &_cheapr_cpp_any_na, 2}, - {"_cheapr_cpp_character_compare", (DL_FUNC) &_cheapr_cpp_character_compare, 3}, - {"_cheapr_cpp_col_all_na", (DL_FUNC) &_cheapr_cpp_col_all_na, 2}, - {"_cheapr_cpp_col_any_na", (DL_FUNC) &_cheapr_cpp_col_any_na, 2}, - {"_cheapr_cpp_col_na_counts", (DL_FUNC) &_cheapr_cpp_col_na_counts, 2}, - {"_cheapr_cpp_count_val", (DL_FUNC) &_cheapr_cpp_count_val, 3}, - {"_cheapr_cpp_dbl_sequence", (DL_FUNC) &_cheapr_cpp_dbl_sequence, 3}, - {"_cheapr_cpp_df_col_na_counts", (DL_FUNC) &_cheapr_cpp_df_col_na_counts, 1}, - {"_cheapr_cpp_df_row_na_counts", (DL_FUNC) &_cheapr_cpp_df_row_na_counts, 1}, - {"_cheapr_cpp_drop_null", (DL_FUNC) &_cheapr_cpp_drop_null, 2}, - {"_cheapr_cpp_format_double_as_int64", (DL_FUNC) &_cheapr_cpp_format_double_as_int64, 1}, - {"_cheapr_cpp_gcd", (DL_FUNC) &_cheapr_cpp_gcd, 5}, - {"_cheapr_cpp_gcd2", (DL_FUNC) &_cheapr_cpp_gcd2, 4}, - {"_cheapr_cpp_gcd2_vectorised", (DL_FUNC) &_cheapr_cpp_gcd2_vectorised, 4}, - {"_cheapr_cpp_int64_to_double", (DL_FUNC) &_cheapr_cpp_int64_to_double, 1}, - {"_cheapr_cpp_int_sequence", (DL_FUNC) &_cheapr_cpp_int_sequence, 3}, - {"_cheapr_cpp_is_na", (DL_FUNC) &_cheapr_cpp_is_na, 1}, - {"_cheapr_cpp_lag", (DL_FUNC) &_cheapr_cpp_lag, 5}, - {"_cheapr_cpp_lag2", (DL_FUNC) &_cheapr_cpp_lag2, 6}, - {"_cheapr_cpp_lag_sequence", (DL_FUNC) &_cheapr_cpp_lag_sequence, 3}, - {"_cheapr_cpp_lcm", (DL_FUNC) &_cheapr_cpp_lcm, 3}, - {"_cheapr_cpp_lcm2", (DL_FUNC) &_cheapr_cpp_lcm2, 4}, - {"_cheapr_cpp_lcm2_vectorised", (DL_FUNC) &_cheapr_cpp_lcm2_vectorised, 4}, - {"_cheapr_cpp_lead_sequence", (DL_FUNC) &_cheapr_cpp_lead_sequence, 3}, - {"_cheapr_cpp_lengths", (DL_FUNC) &_cheapr_cpp_lengths, 2}, - {"_cheapr_cpp_list_as_df", (DL_FUNC) &_cheapr_cpp_list_as_df, 1}, - {"_cheapr_cpp_matrix_col_na_counts", (DL_FUNC) &_cheapr_cpp_matrix_col_na_counts, 1}, - {"_cheapr_cpp_matrix_row_na_counts", (DL_FUNC) &_cheapr_cpp_matrix_row_na_counts, 1}, - {"_cheapr_cpp_new_list", (DL_FUNC) &_cheapr_cpp_new_list, 2}, - {"_cheapr_cpp_num_na", (DL_FUNC) &_cheapr_cpp_num_na, 2}, - {"_cheapr_cpp_numeric_to_int64", (DL_FUNC) &_cheapr_cpp_numeric_to_int64, 1}, - {"_cheapr_cpp_r_unnested_length", (DL_FUNC) &_cheapr_cpp_r_unnested_length, 1}, - {"_cheapr_cpp_row_na_counts", (DL_FUNC) &_cheapr_cpp_row_na_counts, 2}, - {"_cheapr_cpp_sequence", (DL_FUNC) &_cheapr_cpp_sequence, 3}, - {"_cheapr_cpp_sequence_id", (DL_FUNC) &_cheapr_cpp_sequence_id, 1}, - {"_cheapr_cpp_set_abs", (DL_FUNC) &_cheapr_cpp_set_abs, 1}, - {"_cheapr_cpp_set_add", (DL_FUNC) &_cheapr_cpp_set_add, 2}, - {"_cheapr_cpp_set_add_attr", (DL_FUNC) &_cheapr_cpp_set_add_attr, 3}, - {"_cheapr_cpp_set_add_attributes", (DL_FUNC) &_cheapr_cpp_set_add_attributes, 3}, - {"_cheapr_cpp_set_ceiling", (DL_FUNC) &_cheapr_cpp_set_ceiling, 1}, - {"_cheapr_cpp_set_change_sign", (DL_FUNC) &_cheapr_cpp_set_change_sign, 1}, - {"_cheapr_cpp_set_divide", (DL_FUNC) &_cheapr_cpp_set_divide, 2}, - {"_cheapr_cpp_set_exp", (DL_FUNC) &_cheapr_cpp_set_exp, 1}, - {"_cheapr_cpp_set_floor", (DL_FUNC) &_cheapr_cpp_set_floor, 1}, - {"_cheapr_cpp_set_log", (DL_FUNC) &_cheapr_cpp_set_log, 2}, - {"_cheapr_cpp_set_multiply", (DL_FUNC) &_cheapr_cpp_set_multiply, 2}, - {"_cheapr_cpp_set_pow", (DL_FUNC) &_cheapr_cpp_set_pow, 2}, - {"_cheapr_cpp_set_rm_attr", (DL_FUNC) &_cheapr_cpp_set_rm_attr, 2}, - {"_cheapr_cpp_set_rm_attributes", (DL_FUNC) &_cheapr_cpp_set_rm_attributes, 1}, - {"_cheapr_cpp_set_round", (DL_FUNC) &_cheapr_cpp_set_round, 2}, - {"_cheapr_cpp_set_sqrt", (DL_FUNC) &_cheapr_cpp_set_sqrt, 1}, - {"_cheapr_cpp_set_subtract", (DL_FUNC) &_cheapr_cpp_set_subtract, 2}, - {"_cheapr_cpp_set_trunc", (DL_FUNC) &_cheapr_cpp_set_trunc, 1}, - {"_cheapr_cpp_sset_df", (DL_FUNC) &_cheapr_cpp_sset_df, 2}, - {"_cheapr_cpp_sset_range", (DL_FUNC) &_cheapr_cpp_sset_range, 4}, - {"_cheapr_cpp_val_replace", (DL_FUNC) &_cheapr_cpp_val_replace, 4}, - {"_cheapr_cpp_vec_length", (DL_FUNC) &_cheapr_cpp_vec_length, 1}, - {"_cheapr_cpp_which_", (DL_FUNC) &_cheapr_cpp_which_, 2}, - {"_cheapr_cpp_which_na", (DL_FUNC) &_cheapr_cpp_which_na, 1}, - {"_cheapr_cpp_which_not_na", (DL_FUNC) &_cheapr_cpp_which_not_na, 1}, - {"_cheapr_cpp_which_val", (DL_FUNC) &_cheapr_cpp_which_val, 3}, - {"_cheapr_cpp_window_sequence", (DL_FUNC) &_cheapr_cpp_window_sequence, 4}, - {"_cheapr_is_compact_seq", (DL_FUNC) &_cheapr_is_compact_seq, 1}, - {"_cheapr_r_copy", (DL_FUNC) &_cheapr_r_copy, 1}, + {"_cheapr_compact_seq_data", (DL_FUNC) &_cheapr_compact_seq_data, 1}, + {"_cheapr_cpp_all_na", (DL_FUNC) &_cheapr_cpp_all_na, 3}, + {"_cheapr_cpp_any_na", (DL_FUNC) &_cheapr_cpp_any_na, 2}, + {"_cheapr_cpp_character_compare", (DL_FUNC) &_cheapr_cpp_character_compare, 3}, + {"_cheapr_cpp_col_all_na", (DL_FUNC) &_cheapr_cpp_col_all_na, 2}, + {"_cheapr_cpp_col_any_na", (DL_FUNC) &_cheapr_cpp_col_any_na, 2}, + {"_cheapr_cpp_col_na_counts", (DL_FUNC) &_cheapr_cpp_col_na_counts, 2}, + {"_cheapr_cpp_count_val", (DL_FUNC) &_cheapr_cpp_count_val, 3}, + {"_cheapr_cpp_dbl_sequence", (DL_FUNC) &_cheapr_cpp_dbl_sequence, 3}, + {"_cheapr_cpp_df_col_na_counts", (DL_FUNC) &_cheapr_cpp_df_col_na_counts, 1}, + {"_cheapr_cpp_df_row_na_counts", (DL_FUNC) &_cheapr_cpp_df_row_na_counts, 1}, + {"_cheapr_cpp_drop_null", (DL_FUNC) &_cheapr_cpp_drop_null, 2}, + {"_cheapr_cpp_format_numeric_as_int64", (DL_FUNC) &_cheapr_cpp_format_numeric_as_int64, 1}, + {"_cheapr_cpp_gcd", (DL_FUNC) &_cheapr_cpp_gcd, 5}, + {"_cheapr_cpp_gcd2", (DL_FUNC) &_cheapr_cpp_gcd2, 4}, + {"_cheapr_cpp_gcd2_vectorised", (DL_FUNC) &_cheapr_cpp_gcd2_vectorised, 4}, + {"_cheapr_cpp_int64_to_double", (DL_FUNC) &_cheapr_cpp_int64_to_double, 1}, + {"_cheapr_cpp_int_sequence", (DL_FUNC) &_cheapr_cpp_int_sequence, 3}, + {"_cheapr_cpp_is_na", (DL_FUNC) &_cheapr_cpp_is_na, 1}, + {"_cheapr_cpp_lag", (DL_FUNC) &_cheapr_cpp_lag, 5}, + {"_cheapr_cpp_lag2", (DL_FUNC) &_cheapr_cpp_lag2, 6}, + {"_cheapr_cpp_lag_sequence", (DL_FUNC) &_cheapr_cpp_lag_sequence, 3}, + {"_cheapr_cpp_lcm", (DL_FUNC) &_cheapr_cpp_lcm, 3}, + {"_cheapr_cpp_lcm2", (DL_FUNC) &_cheapr_cpp_lcm2, 4}, + {"_cheapr_cpp_lcm2_vectorised", (DL_FUNC) &_cheapr_cpp_lcm2_vectorised, 4}, + {"_cheapr_cpp_lead_sequence", (DL_FUNC) &_cheapr_cpp_lead_sequence, 3}, + {"_cheapr_cpp_lengths", (DL_FUNC) &_cheapr_cpp_lengths, 2}, + {"_cheapr_cpp_list_as_df", (DL_FUNC) &_cheapr_cpp_list_as_df, 1}, + {"_cheapr_cpp_matrix_col_na_counts", (DL_FUNC) &_cheapr_cpp_matrix_col_na_counts, 1}, + {"_cheapr_cpp_matrix_row_na_counts", (DL_FUNC) &_cheapr_cpp_matrix_row_na_counts, 1}, + {"_cheapr_cpp_new_list", (DL_FUNC) &_cheapr_cpp_new_list, 2}, + {"_cheapr_cpp_num_na", (DL_FUNC) &_cheapr_cpp_num_na, 2}, + {"_cheapr_cpp_numeric_to_int64", (DL_FUNC) &_cheapr_cpp_numeric_to_int64, 1}, + {"_cheapr_cpp_r_unnested_length", (DL_FUNC) &_cheapr_cpp_r_unnested_length, 1}, + {"_cheapr_cpp_row_na_counts", (DL_FUNC) &_cheapr_cpp_row_na_counts, 2}, + {"_cheapr_cpp_sequence", (DL_FUNC) &_cheapr_cpp_sequence, 3}, + {"_cheapr_cpp_sequence_id", (DL_FUNC) &_cheapr_cpp_sequence_id, 1}, + {"_cheapr_cpp_set_abs", (DL_FUNC) &_cheapr_cpp_set_abs, 1}, + {"_cheapr_cpp_set_add", (DL_FUNC) &_cheapr_cpp_set_add, 2}, + {"_cheapr_cpp_set_add_attr", (DL_FUNC) &_cheapr_cpp_set_add_attr, 3}, + {"_cheapr_cpp_set_add_attributes", (DL_FUNC) &_cheapr_cpp_set_add_attributes, 3}, + {"_cheapr_cpp_set_ceiling", (DL_FUNC) &_cheapr_cpp_set_ceiling, 1}, + {"_cheapr_cpp_set_change_sign", (DL_FUNC) &_cheapr_cpp_set_change_sign, 1}, + {"_cheapr_cpp_set_divide", (DL_FUNC) &_cheapr_cpp_set_divide, 2}, + {"_cheapr_cpp_set_exp", (DL_FUNC) &_cheapr_cpp_set_exp, 1}, + {"_cheapr_cpp_set_floor", (DL_FUNC) &_cheapr_cpp_set_floor, 1}, + {"_cheapr_cpp_set_log", (DL_FUNC) &_cheapr_cpp_set_log, 2}, + {"_cheapr_cpp_set_multiply", (DL_FUNC) &_cheapr_cpp_set_multiply, 2}, + {"_cheapr_cpp_set_pow", (DL_FUNC) &_cheapr_cpp_set_pow, 2}, + {"_cheapr_cpp_set_rm_attr", (DL_FUNC) &_cheapr_cpp_set_rm_attr, 2}, + {"_cheapr_cpp_set_rm_attributes", (DL_FUNC) &_cheapr_cpp_set_rm_attributes, 1}, + {"_cheapr_cpp_set_round", (DL_FUNC) &_cheapr_cpp_set_round, 2}, + {"_cheapr_cpp_set_sqrt", (DL_FUNC) &_cheapr_cpp_set_sqrt, 1}, + {"_cheapr_cpp_set_subtract", (DL_FUNC) &_cheapr_cpp_set_subtract, 2}, + {"_cheapr_cpp_set_trunc", (DL_FUNC) &_cheapr_cpp_set_trunc, 1}, + {"_cheapr_cpp_sset_df", (DL_FUNC) &_cheapr_cpp_sset_df, 2}, + {"_cheapr_cpp_sset_range", (DL_FUNC) &_cheapr_cpp_sset_range, 4}, + {"_cheapr_cpp_val_replace", (DL_FUNC) &_cheapr_cpp_val_replace, 4}, + {"_cheapr_cpp_vec_length", (DL_FUNC) &_cheapr_cpp_vec_length, 1}, + {"_cheapr_cpp_which_", (DL_FUNC) &_cheapr_cpp_which_, 2}, + {"_cheapr_cpp_which_na", (DL_FUNC) &_cheapr_cpp_which_na, 1}, + {"_cheapr_cpp_which_not_na", (DL_FUNC) &_cheapr_cpp_which_not_na, 1}, + {"_cheapr_cpp_which_val", (DL_FUNC) &_cheapr_cpp_which_val, 3}, + {"_cheapr_cpp_window_sequence", (DL_FUNC) &_cheapr_cpp_window_sequence, 4}, + {"_cheapr_is_compact_seq", (DL_FUNC) &_cheapr_is_compact_seq, 1}, + {"_cheapr_r_copy", (DL_FUNC) &_cheapr_r_copy, 1}, {NULL, NULL, 0} }; } diff --git a/src/gcd.cpp b/src/gcd.cpp index c99ccfb..5441780 100644 --- a/src/gcd.cpp +++ b/src/gcd.cpp @@ -5,11 +5,6 @@ template T cpp_sign(T x) { return (x > 0) - (x < 0); } -#define CHEAPR_INT_TO_INT64(x) ((long long int) (x == NA_INTEGER ? NA_INTEGER64 : x)) -#define CHEAPR_DBL_TO_INT64(x) ((long long int) (x != x ? NA_INTEGER64 : x)) -#define CHEAPR_INT64_TO_INT(x) ((int) (x == NA_INTEGER64 ? NA_INTEGER : x)) -#define CHEAPR_INT64_TO_DBL(x) ((double) (x == NA_INTEGER64 ? NA_REAL : x)) - [[cpp11::register]] double cpp_gcd2(double x, double y, double tol, bool na_rm){ double zero = 0.0; diff --git a/src/utils.cpp b/src/utils.cpp index 9d881ef..00dde23 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -140,24 +140,64 @@ std::string string_format( const std::string& format, Args ... args){ return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside } +// Simple format large integers +// same as `format(x, scientific = FALSE, trim = TRUE)` + [[cpp11::register]] -SEXP cpp_format_double_as_int64(SEXP x){ +SEXP cpp_format_numeric_as_int64(SEXP x){ R_xlen_t n = Rf_xlength(x); - SEXP out = Rf_protect(Rf_allocVector(STRSXP, n)); - double *p_x = REAL(x); - SEXP na_char = Rf_protect(Rf_mkChar("NA")); - for (R_xlen_t i = 0; i < n; ++i){ - if (cheapr_is_na_dbl(p_x[i])){ - SET_STRING_ELT(out, i, na_char); + switch (TYPEOF(x)){ + case INTSXP: { + SEXP out = Rf_protect(Rf_allocVector(STRSXP, n)); + int *p_x = INTEGER(x); + + for (R_xlen_t i = 0; i < n; ++i){ + if (cheapr_is_na_int(p_x[i])){ + SET_STRING_ELT(out, i, NA_STRING); + } else { + long long temp = p_x[i]; + std::string s = string_format("%lld", temp); + SET_STRING_ELT(out, i, Rf_mkChar(s.c_str())); + } + } + Rf_unprotect(1); + return out; + } + case REALSXP: { + SEXP out = Rf_protect(Rf_allocVector(STRSXP, n)); + if (is_int64(x)){ + long long *p_x = INTEGER64_PTR(x); + + for (R_xlen_t i = 0; i < n; ++i){ + if (cheapr_is_na_int64(p_x[i])){ + SET_STRING_ELT(out, i, NA_STRING); + } else { + long long temp = p_x[i]; + std::string s = string_format("%lld", temp); + SET_STRING_ELT(out, i, Rf_mkChar(s.c_str())); + } + } } else { - long long temp = p_x[i]; - std::string s = string_format("%lld", temp); - SET_STRING_ELT(out, i, Rf_mkChar(s.c_str())); + double *p_x = REAL(x); + + for (R_xlen_t i = 0; i < n; ++i){ + if (cheapr_is_na_dbl(p_x[i])){ + SET_STRING_ELT(out, i, NA_STRING); + } else { + long long temp = p_x[i]; + std::string s = string_format("%lld", temp); + SET_STRING_ELT(out, i, Rf_mkChar(s.c_str())); + } + } } + Rf_unprotect(1); + return out; + } + default: { + Rf_error("%s cannot handle an object of type %s", __func__, Rf_type2char(TYPEOF(x))); + } } - Rf_unprotect(2); - return out; } // Potentially useful for rolling calculations