Setting a `NULL` default for a parameter in Rcpp function - rcpp

I want to set the default value of a parameter to NULL in an Rcpp function and do some calculation based on the parameter if the parameter is not NULL. An example of such a code would be
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
int test_null(Nullable<DataFrame> p1 = R_NilValue){
if(p1.isNull()){
NumericMatrix T(2,2);
Rcout << T << std::endl;
}
else{
NumericMatrix T(p1.nrow());
Rcout << T << std::endl;
}
return (42);
}
However, I am not able to compile this function and am getting an error message
error: no member named 'nrow' in 'Rcpp::Nullable<Rcpp::DataFrame_Impl<PreserveStorage> >'
which tells me that there is no nrow defined for a Nullable DataFrame. Is there any other way to do implement a default NULL value for a parameter (i.e., a DataFrame) in Rcpp so that I can calculate other properties (no. or rows, columns etc.) of the DataFrame when it is not NULL.
Any help would be greatly appreciated!
Thanks you!
SN248

You were very close. You missed one instantiation: a Nullable<> is not yet the same as its template type---we need to create an object first.
So here is your code with corrected whitespace ;-) and the missing line plus a test invocation of each case:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
int test_null(Nullable<DataFrame> p1 = R_NilValue){
if (p1.isNull()) {
NumericMatrix T(2,2);
Rcout << T << std::endl;
} else {
DataFrame S(p1);
NumericMatrix T(S.nrow());
Rcout << T << std::endl;
}
return (42);
}
/*** R
test_null(NULL)
test_null(data.frame(a=1:3, b=letters[1:3]))
*/
For which I get the expected result:
R> Rcpp::sourceCpp("~/git/stackoverflow/61701367/answer.cpp")
R> test_null(NULL)
0.00000 0.00000
0.00000 0.00000
[1] 42
R> test_null(data.frame(a=1:3, b=letters[1:3]))
0.00000 0.00000 0.00000
0.00000 0.00000 0.00000
0.00000 0.00000 0.00000
[1] 42
R>

Related

How to make an array of pointers and make the user enter the size of it?

I want to make an array, and inside this array there are pointers, like this:
int *arrp[size]; and I want the user to enter the size of it.
I tried to do this:
#include <iostream>
using namespace std;
int main ()
{
int size;
cout << "Enter the size of the array of pointers" << endl;
cin >> size;
int *arrp[size];
return 0;
}
but this doesn't work.
I also tried to do this:
#include <iostream>
using namespace std;
int main ()
{
int size;
cout << "Enter the size of the array of pointers" << endl;
cin >> size;
int* arrp[] = new int[size];
return 0;
}
also doesn't work, can someone help?
The error of the first code is that the size must be constant, I tried to fix that by writing the 2nd code but it gives an error for the word "new" in line 9:
E0520 initialization with '{...}' expected for aggregate object
and another error for the size in the same line:
C2440 'initializing': cannot convert from 'int *' to 'int *[]'
To make an array of pointers you should type: int** arr = new int*[size]
we type 2 stars '*', the first mean a pointer to an integer, the second means a pointer to the pointer to the integer, and then we make a place in the memory for those pointers by typing = new int*[size], you can use this as a 2D array that stored in the heap (not the stack) go to this website to know the difference: https://www.geeksforgeeks.org/stack-vs-heap-memory-allocation/.
to know more about how to use an array of pointers to a pointer to an integers you can see this video: https://www.youtube.com/watch?v=gNgUMA_Ur0U&ab_channel=TheCherno.

Invoke the element in `Rcpp::List` for futher use directly

In an application, I use List to contain some variables (double, arma::mat and other types), and then take the arma::mat component in this list for futher use directly, such as matrix addition. However, some error is thrown.
Below is a toy example to throw the same error as I met:
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
arma::mat f(){
arma::mat x = arma::randn(3, 4) ;
List y = List::create( ::Named("a") = arma::randn(3, 4) ) ;
return x - y["a"] ;
}
The error information is
ambiguous overload for 'operator-' (operand types are 'arma::mat'
{aka 'arma::Mat<double>'} and 'Rcpp::Vector<19>::NameProxy' {aka
'Rcpp::internal::generic_name_proxy<19, Rcpp::PreserveStorage>'})
Is there any way to use the y["a"] directly in numerical computation?
You need cast back from the SEXP type you create when adding to an (R or Rcpp, it's the same) List. Correcting that and adding a missing exports tag gives us what is below where I also added the sample invocation (another nice feature).
Code
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
// [[Rcpp::export]]
arma::mat f(){
arma::mat x = arma::randn(3, 4) ;
List y = List::create( ::Named("a") = arma::randn(3, 4) ) ;
return x - Rcpp::as<arma::mat>(y["a"]);
}
/*** R
set.seed(42) # reproducible RNG draws
f()
*/
Output
> Rcpp::sourceCpp("~/git/stackoverflow/71612260/answer.cpp")
>
set.seed(42) # reproducible RNG draws
>
f()
[,1] [,2] [,3] [,4]
[1,] -0.471335 -2.337283 1.205825 0.537811
[2,] 0.119150 1.251941 0.486474 -0.513627
[3,] 3.309860 -0.654003 -0.146678 -0.835439
>

C++11: how to use accumulate / lambda function to calculate the sum of all sizes from a vector of string?

For a vector of strings, return the sum of each string's size.
I tried to use accumulate, together with a lambda function (Is it the best way of calculating what I want in 1-line?)
Codes are written in wandbox (https://wandbox.org/permlink/YAqXGiwxuGVZkDPT)
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
using namespace std;
int main() {
vector<string> v = {"abc", "def", "ghi"};
size_t totalSize = accumulate(v.begin(), v.end(), [](string s){return s.size();});
cout << totalSize << endl;
return 0;
}
I expect to get a number (9), however, errors are returned:
/opt/wandbox/gcc-head/include/c++/10.0.0/bits/stl_numeric.h:135:39: note: 'std::__cxx11::basic_string' is not derived from 'const __gnu_cxx::__normal_iterator<_Iterator, _Container>'
135 | __init = _GLIBCXX_MOVE_IF_20(__init) + *__first;
I want to know how to fix my codes? Thanks.
That's because you do not use std::accumulate properly. Namely, you 1) did not specify the initial value and 2) provided unary predicate instead of a binary. Please check the docs.
The proper way to write what you want would be:
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
using namespace std;
int main() {
vector<string> v = {"abc", "def", "ghi"};
size_t totalSize = accumulate(v.begin(), v.end(), 0,
[](size_t sum, const std::string& str){ return sum + str.size(); });
cout << totalSize << endl;
return 0;
}
Both issues are fixed in this code:
0 is specified as initial value, because std::accumulate needs to know where to start, and
The lambda now accepts two parameters: accumulated value, and the next element.
Also note how std::string is passed by const ref into the lambda, while you passed it by value, which was leading to string copy on each invocation, which is not cool

Error using Rcpp::Nullable with RcppArmadillo types

I'm using RcppArmadillo in my R package and I would like to use the Rcpp::Nullable in the parameter list.
NumericVector d_snb(NumericVector& x,
Nullable<arma::mat> size_param = R_NilValue,
const int& infinite = 100000, const bool& log_v = false)
This gives an error like:
Error: package or namespace load failed for ‘packagex’ in dyn.load(file, DLLpath = DLLpath, ...): unable to load shared object '/usr/local/lib/R/3.4/site-library/packagex/libs/packagex.so': dlopen(/usr/local/lib/R/3.4/site-library/packagex/libs/packagex.so, 6):
Symbol not found: __Z5d_snbRN4Rcpp6VectorILi14ENS_15PreserveStorageEEENS_8NullableIS2_EES5_S5_RKiRKb
Referenced from: /usr/local/lib/R/3.4/site-library/packagex/libs/packagex.so
Expected in: flat namespace in /usr/local/lib/R/3.4/site-library/packagex/libs/packagex.so
Error: loading failed
Execution halted
The only possible solution right now seems to get the parameter as NumericVector and then get contents and then cast it into Armadillo types.
NumericVector d_snb(NumericVector& x,
Nullable<NumericVector> size_param = R_NilValue ...)
{
...
if(size_param.isNotNull()) {
arma::mat test(NumericVector(size_param));
param_check++;
}
...
}
This gives a warning:
d_snb.cpp:36:21: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
arma::mat test(NumericVector(size_param));
^~~~~~~~~~~~~~~~~~~~~~~~~~~
d_snb.cpp:36:22: note: add a pair of parentheses to declare a variable
arma::mat test(NumericVector(size_param));
^
( )
1 warning generated.
What's the best way to go about this ?
Yes, Rcpp::Nullable<> works only around SEXP-based Rcpp types.
So you have to do the two-step procedure you found. But I think you can do one simpler: arma::mat test = Rcpp::as<arma::mat>(size_param);
Here is a complete example which compiles (but does 'nothing'):
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
void d_snb(Rcpp::NumericVector& x,
Rcpp::Nullable<Rcpp::NumericVector> size_param = R_NilValue) {
if (size_param.isNotNull()) {
arma::vec test = Rcpp::as<arma::vec>(size_param);
test.print("vector");
}
Rcpp::Rcout << x << std::endl;
}
And a quick demo:
R> sourceCpp("/tmp/so44102346.cpp")
R> d_snb(c(1,2,3))
1 2 3
R> d_snb(c(1,2,3), c(4,5,6))
vector
4.0000
5.0000
6.0000
1 2 3
R>

Reading a value in associative array creates a new key

I have code such as this. I use
pvalueholder is class that is polymorphic , it can hold all sort of types, string..etc..
It also can have a type undefined.
typedef hash_map<pvalueholder,pvalueholder,pvaluehasher > hashtype;
hashtype h;
pvalueholder v;
v="c";
h[v]=5; // h has one element
pvalueholder v2=h[v]; // here h gets a new key/value how is that possible?
cout << (string) (h[v]) << endl; // here h gets another new key/value how is that possible?
int i =0;
for (hashtype::iterator h1=h.begin(); h1!=h.end();h1++)
{
cout << "no: " << i++ << endl;
} // this prints three lines, it should print one...
Two values are undefined here, the third one is 5 as expected.
size_t pvaluehasher::operator() (const pvalueholder& p) const
{
cout << "hashvalue:" << p.value->hashvalue() << endl;
return p.value->hashvalue();
}
returns
Here is what is printed:
hashvalue:84696444
hashvalue:84696444
hashvalue:84696444
returns:1
hashvalue:84696444
returns:1
hashvalue:84696444
returns:1
returns:1
hashvalue:84696444
Do you have any ideas what it may be?
Thank you.
Solution:
the function operator()(parameter1,parameter2) needs to be different in case of Microsoft STL.
For microsoft, it needs to return less than relationship between parameter1 and parameter2.
For gcc, it needs to return equality. I returned equality.
The comparison function for the keys was not correct...
The function returned true for equality while it has to return less than in case of Microsoft STL.
My guess would be that your hash function is incorrect - meaning it produces different hash values given the same key "c".
Show the declaration for pvalueholder and full code for pvaluehasher.
It's almost impossible to comment on hash_map, because it's never been standardized, and the existing implementations aren't entirely consistent. Worse, your code doesn't seem to be correct or compilable as it stands -- some places the value associated with the key seems to be an int, and other places a string.
Using std::tr1::unordered_map and fixing the rest of the code to compile and seem reasonable, like this:
#include <unordered_map>
#include <iostream>
#include <string>
using namespace std;
typedef std::tr1::unordered_map<std::string, int> hashtype;
std::ostream &operator<<(std::ostream &os, std::pair<std::string, int> const &d) {
return os << d.first << ": " << d.second;
}
int main() {
hashtype h;
std::string v = "c";
h[v]=5; // h has one element
int v2=h[v];
cout << h[v] << endl;
int i =0;
for (hashtype::iterator h1=h.begin(); h1!=h.end();h1++)
{
cout << *h1 << endl;
} // this prints three lines, it should print one...
return 0;
}
The output I get is:
5
c: 5
This seems quite reasonable -- we've inserted only one item, as expected.
Solution: the function operator()(parameter1,parameter2) needs to be different in case of Microsoft STL. For microsoft, it needs to return less than relationship between parameter1 and parameter2. For gcc, it needs to return equality. I returned equality. The comparison function for the keys was not correct... The function returned true for equality while it has to return less than in case of Microsoft STL.

Resources