Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,8 @@ export(vec_math_base)
export(vec_names)
export(vec_names2)
export(vec_order)
export(vec_pall)
export(vec_pany)
export(vec_proxy)
export(vec_proxy_compare)
export(vec_proxy_equal)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# vctrs (development version)

* New `vec_pany()` and `vec_pall()`, parallel variants of `any()` and `all()` (in the same way that `pmin()` and `pmax()` are parallel variants of `min()` and `max()`).

* The deprecated C callable for `vec_is_vector()` has been removed.

* Fixed the C level signature for the `exp_short_init_compact_seq()` callable.
Expand Down
104 changes: 104 additions & 0 deletions R/parallel.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#' Parallel `any()` and `all()`
#'
#' @description
#' These functions are variants of [any()] and [all()] that work in parallel on
#' multiple inputs at once. They work similarly to how [pmin()] and [pmax()] are
#' parallel variants of [min()] and [max()].
#'
#' @inheritParams rlang::args_error_context
#'
#' @param ... Logical vectors of equal size.
#'
#' @param .missing Value to use when a missing value is encountered. One of:
#'
#' - `NA` to propagate missing values. With this, missings are treated the
#' same way as `|` or `&`.
#'
#' - `FALSE` to treat missing values as `FALSE`.
#'
#' - `TRUE` to treat missing values as `TRUE`.
#'
#' @param .size An optional output size. Only useful to specify if it is possible
#' for no inputs to be provided.
#'
#' @param .arg Argument name used in error messages.
#'
#' @returns A logical vector the same size as the vectors in `...`.
#'
#' @details
#' `vec_pany()` and `vec_pall()` are consistent with [any()] and [all()] when
#' there are no inputs to process in parallel:
#'
#' - `any()` returns `FALSE` with no inputs. Similarly, `vec_pany(.size = 1)`
#' returns `FALSE`.
#'
#' - `all()` returns `TRUE` with no inputs. Similarly, `vec_pall(.size = 1)`
#' returns `TRUE`.
#'
#' @name parallel-operators
#'
#' @examples
#' a <- c(TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, NA, NA, NA)
#' b <- c(TRUE, FALSE, NA, TRUE, FALSE, NA, TRUE, FALSE, NA)
#'
#' # Default behavior treats missings like `|` does
#' vec_pany(a, b)
#' a | b
#'
#' # Default behavior treats missings like `&` does
#' vec_pall(a, b)
#' a & b
#'
#' # Remove missings from the computation, like `na_rm = TRUE`
#' vec_pany(a, b, .missing = FALSE)
#' (a & !is.na(a)) | (b & !is.na(b))
#'
#' vec_pall(a, b, .missing = TRUE)
#' (a | is.na(a)) & (b | is.na(b))
#'
#' # `vec_pall()` can be used to implement a `dplyr::filter()` style API
#' df <- data_frame(id = seq_along(a), a = a, b = b)
#'
#' keep_rows <- function(x, ...) {
#' vec_slice(x, vec_pall(..., .missing = FALSE))
#' }
#' drop_rows <- function(x, ...) {
#' vec_slice(x, !vec_pall(..., .missing = FALSE))
#' }
#'
#' # "Keep / Drop the rows when both a and b are TRUE"
#' # These form complements of one another, even with `NA`s.
#' keep_rows(df, a, b)
#' drop_rows(df, a, b)
#'
#' # Same empty behavior as `any()` and `all()`
#' vec_pany(.size = 1)
#' any()
#'
#' vec_pall(.size = 1)
#' all()
NULL

#' @rdname parallel-operators
#' @export
vec_pany <- function(
...,
.missing = NA,
.size = NULL,
.arg = "",
.error_call = current_env()
) {
.Call(ffi_vec_pany, list2(...), .missing, .size, environment())
}

#' @rdname parallel-operators
#' @export
vec_pall <- function(
...,
.missing = NA,
.size = NULL,
.arg = "",
.error_call = current_env()
) {
.Call(ffi_vec_pall, list2(...), .missing, .size, environment())
}
4 changes: 4 additions & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ reference:
- vec_identify_runs
- vec_expand_grid

- title: Reducers
contents:
- vec_pall

- title: New classes
contents:
- list_of
Expand Down
104 changes: 104 additions & 0 deletions man/parallel-operators.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 41 additions & 0 deletions src/decl/parallel-decl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
static
r_obj* vec_parallel(
r_obj* xs,
enum vec_parallel_missing missing,
r_ssize size,
struct vctrs_arg* p_xs_arg,
struct r_lazy error_call,
enum vec_parallel_variant parallel
);

static inline
void vec_parallel_init(const int* v_x, enum vec_parallel_missing missing, r_ssize size, int* v_out);
static inline
void vec_parallel_init_missing_as_na(const int* v_x, r_ssize size, int* v_out);
static inline
void vec_parallel_init_missing_as_false(const int* v_x, r_ssize size, int* v_out);
static inline
void vec_parallel_init_missing_as_true(const int* v_x, r_ssize size, int* v_out);

static inline
void vec_pany_fill(const int* v_x, enum vec_parallel_missing missing, r_ssize size, int* v_out);
static inline
void vec_pall_fill(const int* v_x, enum vec_parallel_missing missing, r_ssize size, int* v_out);
static inline
void vec_pany_fill_missing_as_na(const int* v_x, r_ssize size, int* v_out);
static inline
void vec_pall_fill_missing_as_na(const int* v_x, r_ssize size, int* v_out);
static inline
void vec_pany_fill_missing_as_false(const int* v_x, r_ssize size, int* v_out);
static inline
void vec_pall_fill_missing_as_false(const int* v_x, r_ssize size, int* v_out);
static inline
void vec_pany_fill_missing_as_true(const int* v_x, r_ssize size, int* v_out);
static inline
void vec_pall_fill_missing_as_true(const int* v_x, r_ssize size, int* v_out);

static
enum vec_parallel_missing parse_vec_parallel_missing(r_obj* missing, struct r_lazy error_call);

static
r_ssize compute_size(r_ssize size, r_obj* xs);
4 changes: 4 additions & 0 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ extern r_obj* ffi_vec_replace_when(r_obj*, r_obj*, r_obj*, r_obj*);
extern r_obj* ffi_vec_recode_values(r_obj*, r_obj*, r_obj*, r_obj*, r_obj*, r_obj*, r_obj*, r_obj*, r_obj*);
extern r_obj* ffi_vec_replace_values(r_obj*, r_obj*, r_obj*, r_obj*, r_obj*, r_obj*);
extern r_obj* ffi_vec_if_else(r_obj*, r_obj*, r_obj*, r_obj*, r_obj*, r_obj*);
extern r_obj* ffi_vec_pany(r_obj*, r_obj*, r_obj*, r_obj*);
extern r_obj* ffi_vec_pall(r_obj*, r_obj*, r_obj*, r_obj*);


// Maturing
Expand Down Expand Up @@ -372,6 +374,8 @@ static const R_CallMethodDef CallEntries[] = {
{"ffi_vec_recode_values", (DL_FUNC) &ffi_vec_recode_values, 9},
{"ffi_vec_replace_values", (DL_FUNC) &ffi_vec_replace_values, 6},
{"ffi_vec_if_else", (DL_FUNC) &ffi_vec_if_else, 6},
{"ffi_vec_pany", (DL_FUNC) &ffi_vec_pany, 4},
{"ffi_vec_pall", (DL_FUNC) &ffi_vec_pall, 4},
{"ffi_exp_vec_cast", (DL_FUNC) &exp_vec_cast, 2},
{NULL, NULL, 0}
};
Expand Down
Loading