4

I am using the gnu scientific library (GSL). Say I have a gsl_vector like this: 7 0 -6 5 8 0 10 -2

That's a vector containing positive numbers, negative numbers, and zeros as elements.

I want to count the number of non-zero elements or zero elements in this gsl_vector. I know there is a function called count_if for a C++ Vector. But I search through the gsl_vector.h and gsl_blas.h, there is no function equal to that. I can go though all the elements by assessing them though gsl_vector_get() and then ask the if question.

int counter = 0;

for(int i = 0;i<length_of_the_gsl_vector;++i){ 
  if(fabs(gsl_vector_get(y,i))<0.5) ++counter;
}

return counter;

But I have been wondering for almost a day whether there is such a function already in GSL that is much more efficient.

Or maybe there is a count_if function for gsl_array ?

Romain Francois
  • 17,432
  • 3
  • 51
  • 77
blur
  • 53
  • 6
  • gsl_vector_get does index validation, that's going to be the main performance killer – CapelliC Nov 27 '12 at 10:57
  • sure, and that's why I wanna go around it. I also searched for a conversion from gsl_vector to a C++ Vector so that I can use the count_if function in C++, but without success yet. – blur Nov 27 '12 at 11:23
  • An array should really be accessible (as they state) with std::valarray model. Such statement authorize you to use std::iterators and std::count_if (with lambda, if possible). – CapelliC Nov 27 '12 at 11:28
  • I am not sure that I understand you. first, how can I convert a gsl_vector to an array? And second how does the count_if function works for an array? Can you please give an example? – blur Nov 27 '12 at 11:53

2 Answers2

2

You can get hold of the data pointer by using gsl_vector_ptr, then use std::count_if on pointers:

struct Predicate{
    inline bool operator()(double x) const {
        return fabs(x) < 0.5 ;
    }
} ;

int res = std::count_if( 
    gsl_vector_ptr(y,0), gsl_vector_ptr(y,0) + size, 
    Predicate()
) ;
Romain Francois
  • 17,432
  • 3
  • 51
  • 77
  • thank you very much. on my computer I have to use gel_vector_ptr(y,0), gel_vector_ptr(y, size-1) instead. the result is always one less than the result should be. And I compared the time used with the primitive method I presented earlier. they differ slightly and the primitive method performed a heart bit faster... – blur Nov 27 '12 at 15:05
  • I have edited the answer to use `gsl_vector_get` correctly. Also using a functor to remove issues with dereferencing the function pointer. This version should perform better. – Romain Francois Nov 27 '12 at 15:16
  • no, the gsl_vector_get plus if method still is slightly faster. Besides, I don't know what went wrong here, the result still is one count less than it should be. – blur Nov 27 '12 at 17:18
1

They state that GSL implements std::valarray model, I read such statement as authorizing me to use something like:

gsl_block vec;
/* initialize ... */
std::valarray<double> a(vec.data, vec.size);
/* use std:: galore */
CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • of course, how could I forget there is another type called block in GSL. But well, this is embarrassing, I do not speak the language that well to get the solution you are implying. It'd be very kind if you could show me a small code like Romain did. – blur Nov 27 '12 at 15:12