I'm working on a R package dealing with 3D meshes. I have a function which constructs a parametric mesh but for certain parameterizations it can generate duplicated vertices (numeric vectors of length 3). I need to find the duplicated vertices in order to merge them into a single vertex. I implemented an algorithm with Rcpp to do that.
There's a function for that in the Rvcg package: vcgClean(mymesh, sel = 0)
. It is very fast, and as compared to it, my C++ algorithm is very slow. Similary, the R base function duplicated
is highly faster.
Here is how my algorithm works. Say there are n vertices.
I take vertex 1, I compare it to vertices 2, 3, ..., n.
I take vertex 2, I compare it to vertices 3, 4, ..., n. Note that I could skip this comparison in case if this vertex has been marked as a duplicate of vertex 1 at the previous step. I don't do that. Anyway there's usually a small number of duplicates, so this is not the cause of the slowness.
And so on, vertex 3 is compared to vertices 4, 5, ..., n. Etc.
To compare two vertices, I test the near-equality of each coordinate:
bool test = nearEqual(v1(0), v2(0)) && nearEqual(v1(1), v2(1)) && nearEqual(v1(2), v2(2));
Before, I tested exact equality, this was slow as well. My nearEqual
function is:
bool nearEqual(double l, double r) {
return r == std::nextafter(l, r);
}
Why is my algorithm so slow? Is it due to the n-1 + n-2 + ... + 1
comparisons strategy? I don't see how I could do less comparisons. Or is it due to the nearEqual
function? Or what? The vertices are stored in a 3 x n
numeric matrix in Rcpp.
Edit
I've just tried another way to test near-equality of two columns but this is still slow:
const Rcpp::NumericMatrix::Column& v1 = Vertices.column(i);
const Rcpp::NumericMatrix::Column& v2 = Vertices.column(j);
bool test = Rcpp::max(Rcpp::abs(v1 - v2)) < 1e-16;