Does C have a "canned" find function?
Author |
Message |
Darren Wilto #1 / 14
|
 Does C have a "canned" find function?
Hello: I have used Matlab for several years, but for speed purposes it has been suggested that I convert a data interpolation program into C. I have always relied heavily on Matlab's built-in "find" function. Is there a similar function in the C library? Thanks, dcw PS: I = FIND(X) returns the indices of the vector X that are non-zero. For example, I = FIND(A>100), returns the indices of A (an array/matrix/vector) where A is greater than 100.
|
Wed, 09 Mar 2005 02:20:39 GMT |
|
 |
Stig Brautase #2 / 14
|
 Does C have a "canned" find function?
Quote:
> Hello: > I have used Matlab for several years, but for speed purposes it has been > suggested that I convert a data interpolation program into C. I have always > relied heavily on Matlab's built-in "find" function. Is there a similar > function in the C library?
Don't assume that everybody know what Matlab's "find" function does; explain what it does please. Stig -- brautaset.org
|
Wed, 09 Mar 2005 02:41:38 GMT |
|
 |
Tobias Oe #3 / 14
|
 Does C have a "canned" find function?
Quote:
>> Hello: >> I have used Matlab for several years, but for speed purposes it has been >> suggested that I convert a data interpolation program into C. I have >> always >> relied heavily on Matlab's built-in "find" function. Is there a similar >> function in the C library? > Don't assume that everybody know what Matlab's "find" function does; > explain what it does please.
Hi did in his post scriptum. Anyhow, there is no such function in c. But you can roll your own: struct indices{ int *indices; int n_alloc; int n_indices; Quote: };
struct indices *indices_create(void){ struct indices *ind_p=malloc(sizeof *ind_p); if(ind_p){ ind_p->indices=NULL; ind_p->n_alloc=0; ind_p->n_indices=0; } return ind_p; Quote: }
int indices_append(struct indices *ind_p,int i){ int *tmp=NULL; /* allocate memory for the new element if necessary */ if(ind_p->n_alloc==0){ /* first element */ tmp=malloc(sizeof int); if(tmp){ ind_p->n_alloc=1; } }else if(ind_p->n_alloc==ind_p->n_indices){ /* all slots are taken, grow the array */ tmp=realloc(ind_p->indices,ind_p->n_alloc*sizeof int*3/2){ if(tmp){ ind_p->n_alloc=3*ind_p->n_alloc/2; } }else{ /* there are slots left */ tmp=ind_p->indices; } if(tmp){ /* there is memory available copy the new element */ tmp[ind_p->n_indices]=i; ind_p->indices=tmp; ind_p->n_indices++; } return tmp!=NULL; Quote: }
struct indices *find(double *x,int n,int (*crit)(int x)){ struct indices *ind_p; int i; ind_p=indices_create(); if(ind_p){ for(i=0;i<n;i++){ if(crit(x[i]){ /* x[i] satisfies the criterion function */ indices_append(ind_p,i); } } } return ind_p; Quote: }
Not tested nor compiled Tobias. -- unix http://www.faqs.org/faqs/by-newsgroup/comp/comp.unix.programmer.html clc http://www.eskimo.com/~scs/C-faq/top.html fclc (french): http://www.isty-info.uvsq.fr/~rumeau/fclc/
|
Wed, 09 Mar 2005 03:24:00 GMT |
|
 |
David C #4 / 14
|
 Does C have a "canned" find function?
Quote:
> I = FIND(X) returns the indices of the vector X that are non-zero. For > example, I = FIND(A>100), returns the indices of A (an array/matrix/vector) > where A is greater than 100.
Doesn't this imply a definition for I where it may contain multiple values? There is no such function in the standard C library, but one shouldn't be too hard to write, once you clearly define the parameters. Using bsearch as a model, I came up woth something like this: void find(const void *array, size_t count, size_t elemsize, const int *indices, size_t indices_size, size_t *indices_used, int (*testfn)(const void *)); where: array is an array of values you're searching count is the number of elements in array elemsize is the size of each element in the array indices is an array of integers to hold the result indices_size is the size of indices indices_used points to the number of matches that were found, and may be greater than indices_size if indices is not big enough to hold the result. testfn is a function to determine if each element matches. it accepts an object pointer and returns 1 if there's a match, or zero if no match. Implementation: void find(const void *array, size_t count, size_t elemsize, const int *indices, size_t indices_size, size_t *indices_used, int (*testfn)(const void *)) { int current_elem, current_index; void *current_object current_index = 0; current_elem = 0; while(current_elem < count) { current_object = ((char *)array) + (elemsize * current_elem); if (testfn(current_object)) { if (current_index < indices_size) { indices[current_index] = current_elem; } current_index++; } current_elem++; } *indices_used = current_index; Quote: }
Example: typedef struct foo { /* The actual definition is immaterial */ } foo; int testfoo(foo *object) { /* This is some test function returning 0 or 1 */ } int main() { foo fooArray[1000]; int matches[1000]; int num_matches; int i; /* Pretend we did something here to load values into fooArray */ find(fooArray, 1000, sizeof(foo), matches, 1000, &num_matches, testfoo); printf("Matches found are array indices: \n") for (i=0; i<num_matches; i++) { printf("%d ", matches[i]); } printf("\n"); return 0; }
|
Wed, 09 Mar 2005 03:34:36 GMT |
|
 |
David C #5 / 14
|
 Does C have a "canned" find function?
Quote:
>> I have used Matlab for several years, but for speed purposes it has been >> suggested that I convert a data interpolation program into C. I have always >> relied heavily on Matlab's built-in "find" function. Is there a similar >> function in the C library? > Don't assume that everybody know what Matlab's "find" function does; > explain what it does please.
He did. You truncated the end of his message: >> PS: >> >> I = FIND(X) returns the indices of the vector X that are non-zero. >> For example, I = FIND(A>100), returns the indices of A (an >> array/matrix/vector) where A is greater than 100. -- David
|
Wed, 09 Mar 2005 03:35:59 GMT |
|
 |
Dann Corbi #6 / 14
|
 Does C have a "canned" find function?
Quote: > Hello: > I have used Matlab for several years, but for speed purposes it has been > suggested that I convert a data interpolation program into C. I have always > relied heavily on Matlab's built-in "find" function. Is there a similar > function in the C library? > Thanks, > dcw > PS: > I = FIND(X) returns the indices of the vector X that are non-zero. For > example, I = FIND(A>100), returns the indices of A (an
array/matrix/vector) Quote: > where A is greater than 100.
The C standard library does not contain a function to find a subset of a vector. I suspect you may be looking for "The Selection Problem" which is not solved intrinsically with any C library function. Or perhaps you need to sort the vector. Since I don't know why you need to locate a subset of the data, it is hard for me to say what you might be after. Here is selection in C -- maybe it will prove helpful: #include <stdlib.h> typedef double Etype; /* Choose your poison here. */ extern Etype RandomSelect(Etype * A, size_t p, size_t r, size_t i); extern size_t RandRange(size_t a, size_t b); extern size_t RandomPartition(Etype * A, size_t p, size_t r); extern size_t Partition(Etype * A, size_t p, size_t r); /* ** ** In the following code, every reference to CLR means: ** ** "Introduction to Algorithms" ** By Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest ** ISBN 0-07-013143-0 */ /* ** CLR, page 187 */ Etype RandomSelect(Etype A[], size_t p, size_t r, size_t i) { size_t q, k; if (p == r) return A[p]; q = RandomPartition(A, p, r); k = q - p + 1; if (i <= k) return RandomSelect(A, p, q, i); else return RandomSelect(A, q + 1, r, i - k); Quote: }
size_t RandRange(size_t a, size_t b) { size_t c = (size_t) ((double) rand() / ((double) RAND_MAX + 1) * (b - a)); return c + a; Quote: }
/* ** CLR, page 162 */ size_t RandomPartition(Etype A[], size_t p, size_t r) { size_t i = RandRange(p, r); Etype Temp; Temp = A[p]; A[p] = A[i]; A[i] = Temp; return Partition(A, p, r); Quote: }
/* ** CLR, page 154 */ size_t Partition(Etype A[], size_t p, size_t r) { Etype x, temp; size_t i, j; x = A[p]; i = p - 1; j = r + 1; for (;;) { do { j--; } while (!(A[j] <= x)); do { i++; } while (!(A[i] >= x)); if (i < j) { temp = A[i]; A[i] = A[j]; A[j] = temp; } else return j; } Quote: }
-- C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html "The C-FAQ Book" ISBN 0-201-84519-9 C.A.P. FAQ: ftp://cap.connx.com/pub/Chess%20Analysis%20Project%20FAQ.htm
|
Wed, 09 Mar 2005 03:34:08 GMT |
|
 |
Eric Sosma #7 / 14
|
 Does C have a "canned" find function?
Quote:
> > Hello: > > I have used Matlab for several years, but for speed purposes it has been > > suggested that I convert a data interpolation program into C. I have always > > relied heavily on Matlab's built-in "find" function. Is there a similar > > function in the C library? > Don't assume that everybody know what Matlab's "find" function does; > explain what it does please.
The explanation was in the piece you snipped. To the O.P.: No, the C library provides no such function. --
|
Wed, 09 Mar 2005 03:22:26 GMT |
|
 |
Mike Wahle #8 / 14
|
 Does C have a "canned" find function?
Quote: > Hello: > I have used Matlab for several years, but for speed purposes it has been > suggested that I convert a data interpolation program into C. I have always > relied heavily on Matlab's built-in "find" function. Is there a similar > function in the C library? > Thanks, > dcw > PS: > I = FIND(X) returns the indices of the vector X that are non-zero. For > example, I = FIND(A>100), returns the indices of A (an
array/matrix/vector) Quote: > where A is greater than 100.
The library has no such function, but it's not hard to write: #include <stdio.h> #include <stdlib.h> typedef enum { GT, LT /* (add any other operations you need) */ Quote: } op;
size_t find(int *vec, size_t elems, size_t *ind, op oper, int value) { size_t cnt = 0; size_t i = 0; int *p = ind; for(i = 0; i < elems; ++i) { int elem = vec[i]; switch(oper) { case GT: if(elem > value) { *p++ = i; ++cnt; } break; case LT: if(elem < value) { *p++ = i; ++cnt; } break; /* (add any other operations you need) */ default: /* ignore undefined operations */ break; } } return cnt; /* number of 'hits' (indices) */ Quote: }
int main() { /* test data */ int vector[] = {0, 105, 0, 256, 24, 100, 42, 0, 8, 456, 0}; size_t indices[sizeof vector / sizeof *vector] = {0}; /* (number of elements in array 'indices' *must* be at least equal to number of elements in array 'vector') */ size_t count = sizeof vector / sizeof *vector; /* convenience object */ size_t hits = 0; size_t i = 0; /* show vector */ puts("vector contents:"); for(i = 0; i < count; ++i) printf("element [%lu] == %d\n", (unsigned long)i, vector[i]); putchar('\n'); /* call the find function */ hits = find(vector, count, indices, GT, 100); /* show results */ puts("indices of values > 100:"); for(i = 0; i < hits; ++i) printf("%lu\n", (unsigned long)(indices[i])); return 0; Quote: }
Output: vector contents: element [0] == 0 element [1] == 105 element [2] == 0 element [3] == 256 element [4] == 24 element [5] == 100 element [6] == 42 element [7] == 0 element [8] == 8 element [9] == 456 element [10] == 0 indices of values > 100: 1 3 9 Warning: code not thoroughly tested. HTH, -Mike
|
Wed, 09 Mar 2005 04:13:49 GMT |
|
 |
Richard Heathfiel #9 / 14
|
 Does C have a "canned" find function?
Quote:
> > Hello: > > I have used Matlab for several years, but for speed purposes it has been > > suggested that I convert a data interpolation program into C. I have always > > relied heavily on Matlab's built-in "find" function. Is there a similar > > function in the C library? > Don't assume that everybody know what Matlab's "find" function does; > explain what it does please.
He did. "I = FIND(X) returns the indices of the vector X that are non-zero. For example, I = FIND(A>100), returns the indices of A (an array/matrix/vector) where A is greater than 100." Answer to OP: There is no standard function to do what you want, but such a function is not difficult to write. If the array is sorted, use a binary search. If not, use a linear search. --
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999. C FAQ: http://www.eskimo.com/~scs/C-faq/top.html K&R answers, C books, etc: http://users.powernet.co.uk/eton
|
Wed, 09 Mar 2005 03:51:10 GMT |
|
 |
Stig Brautase #10 / 14
|
 Does C have a "canned" find function?
Quote:
>>> I have used Matlab for several years, but for speed purposes it has been >>> suggested that I convert a data interpolation program into C. I have always >>> relied heavily on Matlab's built-in "find" function. Is there a similar >>> function in the C library? >> Don't assume that everybody know what Matlab's "find" function does; >> explain what it does please. > He did. You truncated the end of his message:
Oops... My apologies to the OP. Stig -- brautaset.org
|
Wed, 09 Mar 2005 07:55:13 GMT |
|
 |
Keith Thompso #11 / 14
|
 Does C have a "canned" find function?
Quote:
> > > Hello: > > > I have used Matlab for several years, but for speed purposes it has > > > been suggested that I convert a data interpolation program into C. > > > I have always relied heavily on Matlab's built-in "find" function. > > > Is there a similar function in the C library? > > Don't assume that everybody know what Matlab's "find" function does; > > explain what it does please. > He did. > "I = FIND(X) returns the indices of the vector X that are non-zero. For > example, I = FIND(A>100), returns the indices of A (an > array/matrix/vector) where A is greater than 100." > Answer to OP: There is no standard function to do what you want, but > such a function is not difficult to write. If the array is sorted, use a > binary search. If not, use a linear search.
A binary search won't help unless the condition is such that the matching values are contiguous. --
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst> Schroedinger does Shakespeare: "To be *and* not to be"
|
Thu, 10 Mar 2005 02:24:04 GMT |
|
 |
Richard Heathfiel #12 / 14
|
 Does C have a "canned" find function?
Quote: <snip> Quote: > > "I = FIND(X) returns the indices of the vector X that are non-zero. For > > example, I = FIND(A>100), returns the indices of A (an > > array/matrix/vector) where A is greater than 100." > > Answer to OP: There is no standard function to do what you want, but > > such a function is not difficult to write. If the array is sorted, use a > > binary search. If not, use a linear search. > A binary search won't help unless the condition is such that the > matching values are contiguous.
Right, which is why you have to sort it in such a way that they are! :-) --
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999. C FAQ: http://www.eskimo.com/~scs/C-faq/top.html K&R answers, C books, etc: http://users.powernet.co.uk/eton
|
Thu, 10 Mar 2005 02:33:28 GMT |
|
 |
David Thompso #13 / 14
|
 Does C have a "canned" find function?
... Quote: > if(ind_p->n_alloc==0){ > /* first element */ > tmp=malloc(sizeof int); > if(tmp){ > ind_p->n_alloc=1; > } > }else if(ind_p->n_alloc==ind_p->n_indices){ > /* all slots are taken, grow the array */ > tmp=realloc(ind_p->indices,ind_p->n_alloc*sizeof int*3/2){ > if(tmp){ > ind_p->n_alloc=3*ind_p->n_alloc/2; > }
Growing an initial allocation of 1 by 3/2 doesn't work, it's still 1. You need to either grow by a factor of (at least) 2 (in all cases, or at least the case of 1), or start with a larger base allocation. Given the usual space and time overhead of heap allocations, and especially for a small type like int, I prefer the latter. -- - David.Thompson 1 now at worldnet.att.net
|
Fri, 18 Mar 2005 07:28:06 GMT |
|
 |
Tobias Oe #14 / 14
|
 Does C have a "canned" find function?
Quote:
> ... >> if(ind_p->n_alloc==0){ >> /* first element */ >> tmp=malloc(sizeof int); >> if(tmp){ >> ind_p->n_alloc=1; >> } >> }else if(ind_p->n_alloc==ind_p->n_indices){ >> /* all slots are taken, grow the array */ >> tmp=realloc(ind_p->indices,ind_p->n_alloc*sizeof int*3/2){ >> if(tmp){ >> ind_p->n_alloc=3*ind_p->n_alloc/2; >> } > Growing an initial allocation of 1 by 3/2 doesn't work, it's still 1. > You need to either grow by a factor of (at least) 2 (in all cases, > or at least the case of 1), or start with a larger base allocation. > Given the usual space and time overhead of heap allocations, > and especially for a small type like int, I prefer the latter.
Good eye! Thanks for spotting that. Tobias. -- unix http://www.faqs.org/faqs/by-newsgroup/comp/comp.unix.programmer.html clc http://www.eskimo.com/~scs/C-faq/top.html fclc (french): http://www.isty-info.uvsq.fr/~rumeau/fclc/
|
Mon, 21 Mar 2005 03:33:55 GMT |
|
|
|