Is it possible to translate the R function isTRUE to Rcpp? And if so, how?
The R function:
function (x)
is.logical(x) && length(x) == 1L && !is.na(x) && x
I am struggling with the first and third part. How can I check if the input is of type boolean or logical? And how can I test for NA when the input type is not known?
I know that I can check if the length is 1 with
x.length() == 1 / x.size() == 1
It is already implemented in this header file as
template <bool NA, typename T>
inline bool is_true( const Rcpp::sugar::SingleLogicalResult<NA,T>& x){
return const_cast< Rcpp::sugar::SingleLogicalResult<NA,T>& >(x).is_true() ;
}
That of course references another file ... and all the template-meta-programming is not for the faint of heart. You can also do what you sketch, see this Rcpp Gallery post about dynamic dispatch to see an example of testing for types at run-time.
Related
I have a function in C that gets run from R via .Call and the boolean parameter always gets evaluated as true. Here's a minimal reproducible example:
library(inline)
dummy <- cfunction(signature(x = "bool"),
body = '
int val = x?0:1;
SEXP fake = allocVector(LGLSXP, 5);
SEXP ans = allocVector(LGLSXP, val);
if (val== 1) {
return fake;
}
return ans;
')
dummy(FALSE)
dummy(TRUE)
Both of these function calls return logical(0)
That doesn't sound right, but I also do not think your code goes about this in the right way. In the still-small, still-fairly new package tidyCpp I am collecting a few convenience definitions. One of its examples is basically exactly your problem:
#include <tidyCpp>
// We use Rcpp here because it has cppFunction() and sourceCpp().
// We do not use any Rcpp headers.
// [[Rcpp::depends(tidyCpp)]]
// [[Rcpp::export]]
bool isItLogical(SEXP x) {
return R::isLogical(x);
}
/*** R
isItLogical(TRUE)
isItLogical(FALSE)
isItLogical(42)
*/
When I sourceCpp() this (using Rcpp just for the convenience of building, no real Rcpp code here) I see
> Rcpp::sourceCpp("~/git/tidycpp/inst/snippets/defineExamples.cpp")
>
isItLogical(TRUE)
[1] TRUE
>
isItLogical(FALSE)
[1] TRUE
>
isItLogical(42)
[1] FALSE
>
If we change it from isLogical (answering: is the incoming variable a boolean or not) to asLogical to return the boolean value instead it becomes
> Rcpp::sourceCpp("~/git/stackoverflow/66575428/answer.cpp")
>
asLogical(TRUE)
[1] TRUE
>
asLogical(FALSE)
[1] FALSE
>
asLogical(42) # not zero so ...
[1] TRUE
>
New function below.
#include <tidyCpp>
// We use Rcpp here because it has cppFunction() and sourceCpp().
// We do not use any Rcpp headers.
// [[Rcpp::depends(tidyCpp)]]
// [[Rcpp::export]]
bool asLogical(SEXP x) {
return R::asLogical(x);
}
/*** R
asLogical(TRUE)
asLogical(FALSE)
asLogical(42) # not zero so ...
*/
Obviously, you do not have to use tidyCpp and can just look at its sources to pick the respective C functions of the R API, but I find the naming conventions there a little inconsistent hence this small packages as a little shim around it...
Use asLogical to convert function arguments (which are type SEXP, never bool) to bool:
SEXP dummy(SEXP x) {
int val = asLogical(x);
if (val) {
return allocVector(LGLSXP, 5);
}
return ScalarLogical(0);
}
(though I tend to agree with Dirk that Rcpp is almost always the way to go, unless is a peculiar aversion to it, especially as a first step from R to using compiled code with R).
I have a Rcpp function that has an optional argument which is the maturity of a financial instrument. This can be given as a string (e.g. "2y") or as a integer. If no value is given, the function needs to use a default integer. How can I set the default value for that argument?
I have defined the function with a SEXP argument, the code tests if this is a string or not and depending on this transforms that maturity in an actual date in two different ways. However, I cannot set a default value for the SEXP argument. It seems like a basic question but I have googled quite a bit and could not find anything on this.
Date CPPConvertDate(Date ParamDate, SEXP MaturityDate = 1) {
Date Result ;
const int type_Matu = TYPEOF(MaturityDate) ;
if (type_Matu == 16){
std::string MaturityDate_string = as<std::string>(MaturityDate) ;
//' DO STUFF
} else {
int MaturityDate_int = as<int>(MaturityDate) ;
//' DO OTHER STUFF
}
return (Result) ;
}
Compiler tells me "Cannot initialize a parameter of type SEXP with an R value of type int" so it is pretty clear that I cannot use 1 a default value for MaturityDate. If possible I would like to avoid having two different functions, one with int arguments and one with string argument.
Listen to the compiler because it is a source of wisdown. SEXP has no assignment from 1 as it is a union type -- which is why we have all those wrap() functions to return a SEXP given all possible inputs.
So if it is a Date, use a date type. I have been doing that in RQuantLib (which after all lead to to Rcpp) for well over a decade. If you need a mixed type for different behaviour then methinks you will have a hard time coming up with a default value either way.
Also: not "RCPP". Rcpp, please.
In R the possibility exists to have a function that creates another function, e.g.
create_ax2 <- function(a) {
ax2 <- function(x) {
y <- a * x^2
return(y)
}
return(ax2)
}
The result of which is
> fun <- create_ax2(3)
> fun(1)
[1] 3
> fun(2)
[1] 12
> fun(2.5)
[1] 18.75
I have such a complicated create function in R which take a couple of arguments, sets some of the constants used in the returned function, does some intermediary computations etc... But the result is a function that is way too slow. Hence I tried to translate the code to C++ to use it with Rcpp. However, I can't figure out a way to construct a function inside a C++ function and return it to be used in R.
This is what I have so far:
Rcpp::Function createax2Rcpp(int a) {
double ax2(double x) {
return(a * pow(x, 2));
};
return (ax2);
}
This gives me the error 'function definition is not allowed here', I am stuck about how to create the function.
EDIT: The question RcppArmadillo pass user-defined function comes close, but as far as I can tell, it only provides a way to pass a C++ function to R. It does not provide a way to initialise some values in the C++ function before it is passed to R.
Ok, as far as I understand, you want a function returning function with a closure, a.k.a. " the function defined in the closure 'remembers' the environment in which it was created."
In C++11 and up it is quite possible to define such function, along the lines
std::function<double(double)> createax2Rcpp(int a) {
auto ax2 = [a](double x) { return(double(a) * pow(x, 2)); };
return ax2;
}
What happens, the anonymous class and object with overloaded operator() will be created, it will capture the closure and moved out of the creator function. Return will be captured into instance of std::function with type erasure etc.
But! C/C++ function in R requires to be of a certain type, which is narrower (as an opposite to wider, you could capture narrow objects into wide one, but not vice versa).
Thus, I don't know how to make from std::function a proper R function, looks like it is impossible.
Perhaps, emulation of the closure like below might help
static int __a;
double ax2(double x) {
return(__a * pow(x, 2));
}
Rcpp::Function createax2Rcpp(int a) {
__a = a;
return (ax2);
}
I was just wondering if there was a way to force a function to only accept certain data types, without having to check for it within the function; or, is this not possible because R's type-checking is done at runtime (as opposed to those programming languages, such as Java, where type-checking is done during compilation)?
For example, in Java, you have to specify a data type:
class t2 {
public int addone (int n) {
return n+1;
}
}
In R, a similar function might be
addone <- function(n)
{
return(n+1)
}
but if a vector is supplied, a vector will (obviously) be returned. If you only want a single integer to be accepted, then is the only way to do to have a condition within the function, along the lines of
addone <- function(n)
{
if(is.vector(n) && length(n)==1)
{
return(n+1)
} else
{
return ("You must enter a single integer")
}
}
Thanks,
Chris
This is entirely possible using S3 classes. Your example is somewhat contrived in the context or R, since I can't think of a practical reason why one would want to create a class of a single value. Nonetheless, this is possible. As an added bonus, I demonstrate how the function addone can be used to add the value of one to numeric vectors (trivial) and character vectors (so A turns to B, etc.):
Start by creating a generic S3 method for addone, utlising the S3 despatch mechanism UseMethod:
addone <- function(x){
UseMethod("addone", x)
}
Next, create the contrived class single, defined as the first element of whatever is passed to it:
as.single <- function(x){
ret <- unlist(x)[1]
class(ret) <- "single"
ret
}
Now create methods to handle the various classes. The default method will be called unless a specific class is defined:
addone.default <- function(x) x + 1
addone.character <- function(x)rawToChar(as.raw(as.numeric(charToRaw(x))+1))
addone.single <- function(x)x + 1
Finally, test it with some sample data:
addone(1:5)
[1] 2 3 4 5 6
addone(as.single(1:5))
[1] 2
attr(,"class")
[1] "single"
addone("abc")
[1] "bcd"
Some additional information:
Hadley's devtools wiki is a valuable source of information on all things, including the S3 object system.
The S3 method doesn't provide strict typing. It can quite easily be abused. For stricter object orientation, have a look at S4 classes, reference based classesor the proto package for Prototype object-based programming.
You could write a wrapper like the following:
check.types = function(classes, func) {
n = as.name
params = formals(func)
param.names = lapply(names(params), n)
handler = function() { }
formals(handler) = params
checks = lapply(seq_along(param.names), function(I) {
as.call(list(n('assert.class'), param.names[[I]], classes[[I]]))
})
body(handler) = as.call(c(
list(n('{')),
checks,
list(as.call(list(n('<-'), n('.func'), func))),
list(as.call(c(list(n('.func')), lapply(param.names, as.name))))
))
handler
}
assert.class = function(x, cls) {
stopifnot(cls %in% class(x))
}
And use it like
f = check.types(c('numeric', 'numeric'), function(x, y) {
x + y
})
> f(1, 2)
[1] 3
> f("1", "2")
Error: cls %in% class(x) is not TRUE
Made somewhat inconvenient by R not having decorators. This is kind of hacky
and it suffers from some serious problems:
You lose lazy evaluation, because you must evaluate an argument to determine
its type.
You still can't check the types until call time; real static type checking
lets you check the types even of a call that never actually happens.
Since R uses lazy evaluation, (2) might make type checking not very useful,
because the call might not actually occur until very late, or never.
The answer to (2) would be to add static type information. You could probably
do this by transforming expressions, but I don't think you want to go there.
I've found stopifnot() to be highly useful for these situations as well.
x <- function(n) {
stopifnot(is.vector(n) && length(n)==1)
print(n)
}
The reason it is so useful is because it provides a pretty clear error message to the user if the condition is false.
I have to copy certain elements from a std::map into a vector.
It should work like in this loop:
typedef int First;
typedef void* Second;
std::map<First, Second> map;
// fill map
std::vector<Second> mVec;
for (std::map<First, Second>::const_iterator it = map.begin(); it != map.end(); ++it) {
if (it->first % 2 == 0) {
mVec.push_back (it->second);
}
}
Since I'd like to avoid using any functors, but use boost::lambda instead, I tried using std::copy, but can't get it right.
std::copy (map.begin(), map.end(), std::back_inserter(mVec)
bind(&std::map<int, void*>::value_type::first, _1) % 2 == 0);
I'm new to lambda expressions, and I can't figure it out how to use them correctly.
I didn't get any useful results on Google or StackOverflow either.
This question is similar
What you would need in STL would be a transform_if algorithm. Then you would have to write:
transform_if (mymap.begin(), mymap.end(),
back_inserter(myvec),
bind(&std::map<First, Second>::value_type::second, _1) ,
(bind(&std::map<First, Second>::value_type::first, _1) % 2) == 0 );
The code for transform_if is taken from this unrelated question and it is:
template<class InputIterator, class OutputIterator, class UnaryFunction, class Predicate>
OutputIterator transform_if(InputIterator first,
InputIterator last,
OutputIterator result,
UnaryFunction f,
Predicate pred)
{
for (; first != last; ++first)
{
if( pred(*first) )
*result++ = f(*first);
}
return result;
}
I think there is no other way to perform both steps (transform and conditional copy) at once using STL algorithms.
You can use boost range adaptors to achieve that.
using namespace boost::adaptors;
boost::copy( map | filtered( [] (const pair<First,Second> &p)->bool {return p.first % 2 == 0;})
| transformed( [] (const pair<First,Second> &p) {return p.second;}),
std::back_inserter(mVec));