Search code examples
cconvertersgsl

How to convert from double pointer to gsl vector?


So i created this function to convert from double pointer to gsl vector :

void convert_dpvect_gslvect(int N, double *x, gsl_vector *gx)
{
     
    gx->size = N;
    for (int i = 0; i < N; i++) {
        gx->data[i] = x[i];
    }
}

does that make sense? i want to make sure that it coverts correctly. I would really appreciate your help with this.


Solution

  • By looking at the online documentation for gsl lib (link) we can find functions that already do what you want to do. As a general rule, whenever using a type defined in a library you should look for the provided functions to handle such type.

    The rationale behind this is that they may take care of errors or other fields that you might forget while implementing your functions.

    In your specific case, it seems that you have a vector of double and you want to assign each element to the elements of a gsl_vector. I say this because you do:

    gx->data[i] = x[i]; // Access up to N elements from x
    

    What we want is then the provided library function

    void gsl_vector_set(gsl_vector *v, const size_t i, double x)
    
    This function sets the value of the i-th element of a vector v to x. If i lies outside the allowed range of 0 to size - 1 then the error handler is invoked. An inline version of this function is used when HAVE_INLINE is defined.
    

    In order to use it we need to be sure that we have allocated enough memory by creating a gsl_vector before. I assume that you have N elements, so the full code would be:

    
    // assume x is already initialized with N elements
    
    gsl_vector* V = gsl_vector_alloc(N);
    
    for (int i = 0; i < N; i++) {
        gsl_vector_set( V , i, x[i] );
    }
    
    

    Interestingly enough, by looking at the source code of gsl_vector_set it does something similar to what you came up with, but of course there are some nuisance that are crucial to the library, like checking the range and using the stride to account for different block sizes.

    
    // from https://github.com/ampl/gsl/blob/master/vector/gsl_vector_double
    
    
    INLINE_FUN
    void
    gsl_vector_set (gsl_vector * v, const size_t i, double x)
    {
    #if GSL_RANGE_CHECK
      if (GSL_RANGE_COND(i >= v->size))
        {
          GSL_ERROR_VOID ("index out of range", GSL_EINVAL);
        }
    #endif
      v->data[i * v->stride] = x;
    }