简体   繁体   中英

Rcpp produces different output when not printing blank line

I'm trying to write a function that takes in a vector of 0's and 1's (input), and returns a vector equal to the first, but with each element overwritten by 0 if any previous element was 0 (res). The first element is 1 by default. To do this, for each i, I return the minimum of the ith element of the input vector and the previous result (prev_res).

When I run my function I get the wrong output (exactly the input), but when I include a call to std::cout to print a blank line, I get the expected result. Which seems weird!

I've attached the code below.

library(Rcpp)

cppFunction(
  'NumericVector any_zeroes_previously(IntegerVector input) {
  
  // ** input is a vector of 0 and 1, indicating if timeperiod_num==lag_timeperiod_num+1 **
  
  NumericVector res = NumericVector(input.length());

  for (int i=0; i<input.length(); i++) {
  int prev_res;
  if (i==0) {
  // first row of new group
  res[i] = 1;
  prev_res = 1;
  } else {
  // 2nd row of group onwards
  res[i] = std::min(input[i], prev_res);
  prev_res = res[i];
  
  // ** when next line is commented out, produces incorrect result **
  std::cout << "";
  }
  }
  return res;
  }')

test = c(1,1,0,1,0,0)

# expected result: 1 1 0 0 0 0
# result with print: 1 1 0 0 0 0
# result without print: 1 1 0 1 0 0
any_zeroes_previously(test)

You're using the variable prev_res uninitialized, which is undefined behavior and can be anything.

Every iteration of your for loop re-declares prev_res and if i != 0 you then take the minimum of input[i] and prev_res (any value). A simple fix is to take prev_res outside of the for loop:

cppFunction(
  'NumericVector any_zeroes_previously(IntegerVector input) {
  
  // ** input is a vector of 0 and 1, indicating if timeperiod_num==lag_timeperiod_num+1 **
  
  NumericVector res = NumericVector(input.length());

  int prev_res;
  for (int i=0; i<input.length(); i++) {
  if (i==0) {
  // first row of new group
  res[i] = 1;
  prev_res = 1;
  } else {
  // 2nd row of group onwards
  res[i] = std::min(input[i], prev_res);
  prev_res = res[i];
  
  // ** when next line is commented out, produces incorrect result **
  std::cout << "";
  }
  }
  return res;
  }')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM