Rcpp: strange value from NumericVector type transform between Rcpp and R

Dear all, I am writting a sub-function which may be called by other functions within Rcpp.
The function is masking a NumericVector (x) by two parameters (min and max), as written in R as below:

R_maskminmax= function(x,min=NULL,max=NULL,maskmin=min,maskmax=max){
  if(!is.null(min)) x[x<min]=maskmin
  if(!is.null(max)) x[x>max]=maskmax
  return(x)
}

However, I am not familiar with C++, when I trying to write in Rcpp, I get a strange value of 1.26318e-311 which is expected to be 0.0. I think this is related to the transform between NumericVector and double type, Would you please help me to check the script and point out which.

#include <Rcpp.h>
#include <iostream>
using namespace std;
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector maskminmax0(NumericVector x, 
                         Rcpp::Nullable<NumericVector> min=R_NilValue, 
                         Rcpp::Nullable<NumericVector> max=R_NilValue, 
                         const double maskmin=0.1, const double maskmax=0.5){
  NumericVector tmpx, minthreshold, maxthreshold; 
  NumericVector out = clone(x);
  if (min.isNotNull()) {
    minthreshold=Rcpp::as<NumericVector>(min);
    out[out<minthreshold[0]]=maskmin;
  }
  if (max.isNotNull()) {
    maxthreshold=Rcpp::as<NumericVector>(max);
    out[out>=maxthreshold[0]]=maskmax;
  }
  return out;
}


// [[Rcpp::export]]
NumericVector maskminmax(NumericVector x, 
                         Rcpp::Nullable<NumericVector> min=R_NilValue, 
                         Rcpp::Nullable<NumericVector> max=R_NilValue, 
                         Rcpp::Nullable<NumericVector> maskmin=R_NilValue,
                         Rcpp::Nullable<NumericVector> maskmax=R_NilValue) {
  NumericVector tmpx, minthreshold, maxthreshold; 
  NumericVector out = clone(x);
  double newmin, newmax;
  if (min.isNotNull()) {
    minthreshold=Rcpp::as<NumericVector>(min);
    if(maskmin.isNotNull()){
      tmpx=Rcpp::as<NumericVector>(maskmin);
      newmin=tmpx[0];
    }else{
      newmin=minthreshold[0];
    }
    Rcout << "newmin=" << newmin << endl;
    out[out<minthreshold[0]]=newmin;
  }
  if (max.isNotNull()) {
    maxthreshold=Rcpp::as<NumericVector>(max);
    if(maskmax.isNotNull()) {
      tmpx=Rcpp::as<NumericVector>(maskmax);
      newmax=tmpx[0];
    }else{
      newmax=maxthreshold[0];
    }
    out[out>=maxthreshold[0]]=newmax;
  }
  return out;
}


// [[Rcpp::export]]
NumericVector testmaskminmax(NumericVector x, 
                             Rcpp::Nullable<NumericVector> min=R_NilValue, 
                             Rcpp::Nullable<NumericVector> max=R_NilValue) {
  NumericVector maskmin=0.0, maskmax=0.0;
  NumericVector out=clone(x);
  out=maskminmax0(x,min,max,maskmin[0],maskmax[0]);
  Rcout << "out0=" << out << endl;
  out=maskminmax(x,min,max,maskmin,maskmax);
  Rcout << "out=" << out << endl;
  return out;
}

/*** R
maskminmax0(1:5,min=3,maskmin=0.0)
maskminmax(1:5,min=3,maskmin=0.0)
testmaskminmax(1:5,min=3)
*/

maskminmax0(1:5,min=3,maskmin=0.0)
[1] 0 0 3 4 5

maskminmax(1:5,min=3,maskmin=0.0)
newmin=0
[1] 0 0 3 4 5

testmaskminmax(1:5,min=3)
out0=1.26318e-311 1.26318e-311 3 4 5
newmin=1.26318e-311
out=1.26318e-311 1.26318e-311 3 4 5
[1] 1.263178e-311 1.263178e-311 3.000000e+00 4.000000e+00 5.000000e+00

I'm not a C++ guy at all, but this sure looks like a floating point artifact.

Thanks for your reminder.
I find the error is caused from the below code:
NumericVector maskmin=0.0, maskmax=0.0;
If it is replaced by:
NumericVector maskmin={0.0}, maskmax={0.0};

However, I would be gratefull if any one could give me some suggestions on the type transform between double, NumericVector, especially if a NULL parameter is used as default.
for example, I have tried another way to use a NUllable double type for maskmin, but it not works with out=maskminmax(x,min,max,0.0,0.0). see the below code:

// [[Rcpp::export]]
NumericVector maskminmax(NumericVector x, 
                         Rcpp::Nullable<NumericVector> min=R_NilValue, 
                         Rcpp::Nullable<NumericVector> max=R_NilValue, 
                         Rcpp::Nullable<double> maskmin=R_NilValue,
                         Rcpp::Nullable<double> maskmax=R_NilValue) {
  NumericVector minthreshold, maxthreshold; 
  NumericVector out = clone(x);
  double newmin, newmax;
  if (min.isNotNull()) {
    minthreshold=Rcpp::as<NumericVector>(min);
    if(maskmin.isNotNull()){
      newmin=Rcpp::as<double>(maskmin);
    }else{
      newmin=minthreshold[0];
    }
    Rcout << "newmin=" << newmin << endl;
    out[out<minthreshold[0]]=newmin;
  }
  if (max.isNotNull()) {
    maxthreshold=Rcpp::as<NumericVector>(max);
    if(maskmax.isNotNull()) {
      newmax=Rcpp::as<double>(maskmax);
    }else{
      newmax=maxthreshold[0];
    }
    out[out>=maxthreshold[0]]=newmax;
  }
  return out;
}


// [[Rcpp::export]]
NumericVector testmaskminmax(NumericVector x, 
                             Rcpp::Nullable<NumericVector> min=R_NilValue, 
                             Rcpp::Nullable<NumericVector> max=R_NilValue) {
  double maskmin=0.0, maskmax=0.0;
  NumericVector out=clone(x);
  Rcout << "out0=" << out << endl;
  out=maskminmax(x,min,max); // works well
  out=maskminmax(x,min,max,0.0,0.0); //not works
  out=maskminmax(x,min,max,maskmin,maskmax); // also not works
  Rcout << "out=" << out << endl;
  return out;
}
1 Like

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.