LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

ListFindItem and Creating CompareFunction

I want to use the ListFindItem and the  FloatCompare function as the "CompareFunction".  I cannot find any examples as to how to do this. 
 
The help on ListFindItem says that the FloatCompare function is a "CompareFunction", but the compiler says that it is expecting a CompareFunction, and that FloatCompare is an integer function.
 
How can I use the ListFindItem function with the FloatCompare function as the CompareFunction? How would this look on paper?
 
Thanks
 
 
0 Kudos
Message 1 of 8
(3,952 Views)
 
You must define a call back funcion to wrap FloatCompare () to make it useful for ListFindItem ().
 
Define a function with prototype:

int CVICALLBACK CompareFunction(void *item1, void *item2)

Replace CompareFunction with any name you want.  This serves as a wrapper for the FloatCompare () function

last statement within callback wrapper should be:

return FloatCompare (*item1, item2);

 

robskii

0 Kudos
Message 2 of 8
(3,942 Views)

Oops!! bug: Do not use [return FloatCompare (*item1, item2)].

 

Replace FloatCompare with MyFloatCompareWrapper in ListFindItem() and scarf the following code.

 

Prototype:

int CVICALLBACK MyFloatCompareWrapper(void *item1, void *item2);

 

Function Definition:

int CVICALLBACK MyFloatCompareWrapper(void *item1, void *item2)

{

  return FloatCompare (item1, item2);

}

 

robskii

0 Kudos
Message 3 of 8
(3,935 Views)
OK, so that works - some of the time.
 
The FloatCompare function doesn't have much for documentation, but it may be performing a direct memory comparison unlike FP_Compare which does a "close enough" comparison (negating the floating point error).  True? Yes? No?
 
I was performing this find task with a subroutine that searched through a list of > 6000 floating point numbers until finding a match using the FP_Compare function - that worked fine. I was hoping to eliminate a few lines of code by using the ListFindItem function. 
 
Perhaps I need to build FP_Compare into a CompareFunction? Hmmmmmmm...
0 Kudos
Message 4 of 8
(3,933 Views)
Hi,

You should have no problem passing FloatCompare into ListFindItem like so:

int foundPosition = ListFindItem(list, &floatToFind, FRONT_OF_LIST, FloatCompare);

There are a couple things to be careful about when specifying positions.  Toolbox lists use 1-based positions -- the number 0 actually means END_OF_LIST, so if you try to find an item starting with position 0, you will never find it.  A return value of 0 does *not* mean the item was found at index 0, but rather means END_OF_LIST was reached without finding the item.  Also, with the toolbox list functions, -1 specifies FRONT_OF_LIST, rather than the end of the list (as is the case with user interface library functions).

You should not have problems with floating point error, because in order to search for a value, you must first store it in a float variable.  As long as your list's element size is sizeof(float), you will be comparing identical values, whether affected by floating point representation error or not.

I hope some of this is helpful for your situation.

Mert A.
National Instruments
0 Kudos
Message 5 of 8
(3,929 Views)

 

You got it cpoore!  delete the FloatCompare within the wrapper and replace it with FP_Compare ()!!

FP_Compare() gives control of the precision of the compare which I think you need in this case.

The key is the FP_CompareEpsilon from the toolbox.h file.  I think you can add this *.h file to your project and change the FP_CompareEpsilon until the comparison works to the desired presision on the list.

With the implementation below, one can add break points to make sure the values look OK.

 

 

 

function def:

int CVICALLBACK MyFloatCompareWrapper(void *item1, void *item2)

{

  static float itemA = *((float *) item1);

  static float itemB = *((float *) item2);

  return FP_Compare ((double) itemA , (double) itemB );

}

0 Kudos
Message 6 of 8
(3,920 Views)
It is true that you can have representaional problems if the numbers you expect to be "the same" are calculated by different means.  FloatCompare and DoubleCompare do not use an epsilon when determining equality.  FP_Compare is meant to compare double precision floating point numbers, and the FP_CompareEpsilon constant is designed to be a reasonable epsilon for double precision floating point numbers.  I would not suggest altering this tolerance to the point that it suits single precision round off errors, or else any other use of FP_Compare might be too lax in determining equality.  Instead, you could store your values as double precision numbers, or implement your callback function as a single precision fp comparison function with a built-in tolerance that suits your data.

Mert A.
National Instruments

Message Edited by Mert A. on 12-07-2005 07:14 PM

0 Kudos
Message 7 of 8
(3,915 Views)
This works fine and dandy.  Thanks for the help.
 
The final form was:
int CVICALLBACK MyFloatCompareWrapper(void *item1, void *item2)

{

  float itemA = *((float *) item1);

  float itemB = *((float *) item2);

  return FP_Compare ((double) itemA , (double) itemB );

}

 

The "static" declaration for itemA and itemB caused the compiler to return the error:

"Initializer must be constant"

Otherwise OK.

Chris

0 Kudos
Message 8 of 8
(3,877 Views)