James Crow
James Crow

Reputation: 31

Mysterious C++ syntax

I am trying to walk through and understand a chi squared program that uses intrinsic for speed. In this process I have come across a line of code I can’t understand.

I have tried reviewing textbooks, Google and search of this site with no luck. I think the problem is that without knowing anything about the syntax, I can’t describes the search in terms or keyword sufficiently to get any pertinent results.

Here is the line of code I don’t understand:

float (*chi2_float)(const int, const float*, const float*) = chi2_baseline_float;

And here is the function that contains it:

float chi2_float(const int dim, const float* const x, const float* const y) {
    float (*chi2_float)(const int, const float*, const float*) = chi2_baseline_float;
#ifdef __SSE__
    chi2_float = chi2_intrinsic_float;
#endif
    return chi2_float(dim, x, y);
}

It looks to me that it is probably declaring and defining a function and when I comment out the line and re-compile I get:

error C2659: '=' : function as left operand on line chi2_float = chi2_intrinsic_float;

I can send the .h file that contains this function if needed but it is as you would expect from the parameters.

Any help would be greatly appreciated.

Upvotes: 3

Views: 347

Answers (5)

Michael Burr
Michael Burr

Reputation: 340168

This:

float (*chi2_float)(const int, const float*, const float*)= chi2_baseline_float;

declares a function pointer names chi2_float and assigned to it a pointer to the function named chi_baseline_float.

Then, if the __SSE__ macro is defined, the pointer is reassigned with a pointer to the function chi2_intrinsic_float.

The net effect of all this is something similar to:

float chi2_float(const int dim, const float* const x, const float* const y) 
{
#ifdef __SSE__
    return chi2_intrinsic_float(dim, x, y);
#else
    return chi2_baseline_float(dim, x, y);
#endif
}

Upvotes: 7

Michael J
Michael J

Reputation: 7939

Michael Burr suggested the following:

float chi2_float(const int dim, const float* const x, const float* const y) 
{
#ifdef __SSE__
    return chi2_intrinsic_float(dim, x, y);
#else
    return chi2_baseline_float(dim, x, y);
#endif
}

Ignoring the compiler's optimiser for a moment; this may be improved. Mr Burr's solution uses two function calls: main() (or whatever) calls chi2_float() which then calls the appropriate implementation. That can be reduced to just one function call with the following:

#ifdef __SSE__
    #define chi2_float(dim, x, y) chi2_intrinsic_float(dim, x, y)
#else
    #define chi2_float(dim, x, y) chi2_baseline_float(dim, x, y)
#endif

The same result can likely be achieved by declaring Mr Burr's chi2_float() as "inline".

However, returning to the real world (where compilers aggressively optimise code), you would expect a good optimiser to remove the extra function call, thus rendering Mr Burr's solution to be just as fast.

I have posted this discussion for completeness. Although this does not improve on Mr Burr's solution, it adds a bit more context. Technically it ought to have been a comment, rather than a new answer, but it isn't possible to format source code in a comment. Such is life.

Upvotes: 1

David Hammen
David Hammen

Reputation: 33106

float chi2_float(const int dim, const float* const x, const float* const y) {
   float (*chi2_float)(const int, const float*, const float*) = chi2_baseline_float;
#ifdef __SSE__
   chi2_float = chi2_intrinsic_float;
#endif
   return chi2_float(dim, x, y);
}

Ugly.

The first thing to do to fix this code is to use something other than the function name as the name of the function pointer variable. That this variable shadows the name of the function is, I think, the source of James Crow's confusion.

The second thing to do to fix this code is to get rid of the function pointer entirely, resulting in the code Michael Burr posted in his answer.

Upvotes: 1

oHo
oHo

Reputation: 54541

The code of your question with some comments:

// beginning of the definition of function chi2_float 
float chi2_float(const int dim, const float* const x, const float* const y) {
    // declare the variable chi2_float as a function pointer
    // set variable chi2_float to the address of the function chi2_baseline_float
    float (*chi2_float)(const int, const float*, const float*) = chi2_baseline_float;
// if macro __SSE__ is defined (if the compiler enables SSE instructions set)
// [this is your case because you got an error in the below line when you have commented the above line] 
#ifdef __SSE__
    // then preprocessor adds the following line that sets again the variable chi2_float (but to another function) 
    chi2_float = chi2_intrinsic_float;
#endif
    // call the function pointed by the variable chi2_float
    return chi2_float(dim, x, y);
}

Upvotes: 1

dma
dma

Reputation: 1809

The line in question is setting a variable of type function pointer to one of two other functions depending on the value of __SSE__.

It then calls the function pointed to by chi2_float and returns the result.

Upvotes: 11

Related Questions