forked from tidyverse/dplyr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hybrid_minmax.cpp
71 lines (60 loc) · 1.95 KB
/
hybrid_minmax.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include "pch.h"
#include <dplyr/main.h>
#include <dplyr/HybridHandlerMap.h>
#include <dplyr/Result/ILazySubsets.h>
#include <dplyr/Result/MinMax.h>
using namespace Rcpp;
using namespace dplyr;
template<template <int, bool, bool> class Tmpl, bool MINIMUM, bool NA_RM>
Result* minmax_prototype_impl(SEXP arg, bool is_summary) {
if (!hybridable(arg)) return 0;
switch (TYPEOF(arg)) {
case INTSXP:
return new Tmpl<INTSXP, MINIMUM, NA_RM>(arg, is_summary);
case REALSXP:
return new Tmpl<REALSXP, MINIMUM, NA_RM>(arg, is_summary);
default:
break;
}
return 0;
}
template<template <int, bool, bool> class Tmpl, bool MINIMUM>
Result* minmax_prototype(SEXP call, const ILazySubsets& subsets, int nargs) {
using namespace dplyr;
// we only can handle 1 or two arguments
if (nargs == 0 || nargs > 2) return 0;
// the first argument is the data to operate on
SEXP arg = CADR(call);
bool is_summary = false;
if (TYPEOF(arg) == SYMSXP) {
SymbolString name = SymbolString(Symbol(arg));
if (subsets.has_variable(name)) {
is_summary = subsets.is_summary(name);
arg = subsets.get_variable(name);
}
else return 0;
} else {
return 0;
}
if (nargs == 1) {
return minmax_prototype_impl<Tmpl, MINIMUM, false>(arg, is_summary);
} else if (nargs == 2) {
SEXP arg2 = CDDR(call);
// we know how to handle fun( ., na.rm = TRUE/FALSE )
if (TAG(arg2) == R_NaRmSymbol) {
SEXP narm = CAR(arg2);
if (TYPEOF(narm) == LGLSXP && LENGTH(narm) == 1) {
if (LOGICAL(narm)[0] == TRUE) {
return minmax_prototype_impl<Tmpl, MINIMUM, true>(arg, is_summary);
} else {
return minmax_prototype_impl<Tmpl, MINIMUM, false>(arg, is_summary);
}
}
}
}
return 0;
}
void install_minmax_handlers(HybridHandlerMap& handlers) {
handlers[Rf_install("min")] = minmax_prototype<dplyr::MinMax, true>;
handlers[Rf_install("max")] = minmax_prototype<dplyr::MinMax, false>;
}