4

I'm sorry for the bad title, but nothing better came to my mind apart from "I don't understand this code". Please, feel free to propose a modification.

I'm reading this code. I've never seen a C function like this one:

static void
VL_XCAT(_vl_vlad_encode_, SFX)
(TYPE * enc,
 TYPE const * means, vl_size dimension, vl_size numClusters,
 TYPE const * data, vl_size numData,
 TYPE const * assignments,
 int flags)
{
    // function body
}

In particular I'm confused by (_vl_vlad_encode_, SFX). Up to know, all the functions headers that I've seen had only one "pair of round brackets" (the function's parameters), while here there are two pairs.

What does it mean the first one? I think that this is linked to later calls _vl_vlad_encode_f and _vl_vlad_encode_d, which don't appears anywhere else in the library code, but I can't understand how they're connected.

vgru
  • 49,838
  • 16
  • 120
  • 201
justHelloWorld
  • 6,478
  • 8
  • 58
  • 138
  • Perhaps `VL_XCAT` is a macro? Or it's a function that returns a function pointer? – Kerrek SB Dec 04 '16 at 22:47
  • 1
    `VL_XCAT` is just a [macro](https://github.com/vlfeat/vlfeat/blob/f363f3abf9e55cb117fdbdcdfe44b95ec838ca5f/vl/host.h#L112) which concatenates the two input parameters. – vgru Dec 04 '16 at 22:48

2 Answers2

5

VL_XCAT is a macro usually used to concatenate two tokens. (A ## B) which means it'll create a token from both arguments which is: _vl_vlad_encode_ and SFX - is probably define for type of floating point variable used (double/float)

I would say this'll choose between double and float function to use and use _vl_vlad_encode_f or _vl_vlad_encode_d based on defines.

So if

#define SFX d

it'll create _vl_vlad_encode_d after processing this line.

melpomene
  • 84,125
  • 8
  • 85
  • 148
koper89
  • 645
  • 3
  • 9
2

The VL_XCAT and VL_CAT function-like macros are in vl/host.h (same directory as the vlad.c file you linked).

VL_CAT(x,y) simply concatenates its arguments and VL_XCAT(x,y) is the same, except its arguments are macro-eXpanded:

#define VL_CAT(x,y) x##y
#define VL_XCAT(x,y) VL_CAT(x, y)

VL_XCAT(_vl_vlad_encode_, SFX) results in _vl_vlad_encode_f or _vl_vlad_encode_d, depending on how SFX is defined.

So you end up with this, for example, when #define SFX d is used (note that #define TYPE double is active at the same time):

static void
_vl_vlad_encode_d
(double * enc,
 double const * means, vl_size dimension, vl_size numClusters,
 double const * data, vl_size numData,
 double const * assignments,
 int flags)
{
    // function body
}

Looks like a normal function definition now, doesn't it?