Reputation: 155
I am trying to return the inner product of two vectors in .C with R. After this I want the function to return true if the inner product is equal to zero and false otherwise. I have written a small .cpp function that calculates the inner product correct. When I have a vector of length 2 e.g a <- c(5,-5) b <- c(5,5)
this returns 0 as the result and true as the result is equal to zero.
However when I increase the length of the vector in the R calling code e.g a <- c(5,-5,4) b <- c(5,5,4)
It returns 16 as the result which is fine but it returns true which is incorrect as the result is not equal to zero.
Can anybody help understand what I am doing wrong here?
The code is below for .C
#include <R.h>
extern "C" {
void test(int * x1, int * x2, int * len, int * result, bool * tf)
{
int n = *len;
*result = 0;
for (int i = 0; i < n; i++)
{
*result = *result + x1[i] * x2[i];
if (*result == 0)
{
*tf = TRUE;
}
}
}
}
I have changed this to the code
#include <R.h>
extern "C" {
void test (int * x1, int * x2, int * len, int * result, int * tf)
// void test (int * x1, int * x2, int * result)
{
int n = *len ;
*result = 0;
for (int i = 0; i < n; i++)
*result += x1[i] * x2[i];
*tf = *result == 0;
}
}
and when i use R to call this as below
a <- c(-5,5,4)
b <- c(5,5,3)
len <- length(a)
c <- 0
ans <- FALSE
.C("test", x1 = as.integer(a), x2 = as.integer(b),
len = as.integer(length(a)),
result = as.integer(c),
tf = as.logical(ans))
The output is
$x1
[1] -5 5 4
$x2
[1] 5 5 3
$len
[1] 3
$result
[1] 12
$tf
[1] TRUE
Since Result is not 0 tf should be FALSE and it is when the vector is of length 1 or 2. Only when I increase it to length 3 or more does this happen. Can anyone help please?
Upvotes: 0
Views: 454
Reputation: 405
Your code is buggy. Here is the fixed version:
#include <R.h>
extern "C" {
void isOrthn (int * x1, int * x2, int * len, int * result, bool * tf)
{
int n = *len ;
*result = 0;
for (int i = 0; i < n; i++)
*result += x1[i] * x2[i];
*tf = *result == 0;
}
}
Basically, you could get out without ever initializing tf. By moving the test outside the loop, it is simpler, cleaner and one clearly sees that *tf's value is functionally dependent on the result being 0.
Upvotes: 1
Reputation: 368439
Briefly:
Do not use .C()
, its use is discouraged in all new code (cf discussions on r-devel in the last few years).
Your code has a logic error in that it does not compute the full inner product before testing: complete the loop
Below is how I would write this in RcppArmadillo:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
bool checkInner(const arma::vec a, const arma::vec b) {
double ip = arma::as_scalar(a.t() * b);
return ip == 0.0;
}
/*** R
checkInner( c(1,2), c(-2,1))
checkInner( 1:3, 2:4 )
*/
We just sourceCpp(...)
the file, and it is compiled, linked, loaded and the R code at the bottom is run as well:
R> sourceCpp("/tmp/inner.cpp")
R> checkInner( c(1,2), c(-2,1))
[1] TRUE
R> checkInner( 1:3, 2:4 )
[1] FALSE
R>
Upvotes: 2