GCC Code Coverage Report


Directory: ./
File: libfprint/nbis/mindtct/util.c
Date: 2024-09-16 14:36:32
Exec Total Coverage
Lines: 121 124 97.6%
Functions: 10 10 100.0%
Branches: 43 46 93.5%

Line Branch Exec Source
1 /*******************************************************************************
2
3 License:
4 This software and/or related materials was developed at the National Institute
5 of Standards and Technology (NIST) by employees of the Federal Government
6 in the course of their official duties. Pursuant to title 17 Section 105
7 of the United States Code, this software is not subject to copyright
8 protection and is in the public domain.
9
10 This software and/or related materials have been determined to be not subject
11 to the EAR (see Part 734.3 of the EAR for exact details) because it is
12 a publicly available technology and software, and is freely distributed
13 to any interested party with no licensing requirements. Therefore, it is
14 permissible to distribute this software as a free download from the internet.
15
16 Disclaimer:
17 This software and/or related materials was developed to promote biometric
18 standards and biometric technology testing for the Federal Government
19 in accordance with the USA PATRIOT Act and the Enhanced Border Security
20 and Visa Entry Reform Act. Specific hardware and software products identified
21 in this software were used in order to perform the software development.
22 In no case does such identification imply recommendation or endorsement
23 by the National Institute of Standards and Technology, nor does it imply that
24 the products and equipment identified are necessarily the best available
25 for the purpose.
26
27 This software and/or related materials are provided "AS-IS" without warranty
28 of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
29 NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
30 or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
31 licensed product, however used. In no event shall NIST be liable for any
32 damages and/or costs, including but not limited to incidental or consequential
33 damages of any kind, including economic damage or injury to property and lost
34 profits, regardless of whether NIST shall be advised, have reason to know,
35 or in fact shall know of the possibility.
36
37 By using this software, you agree to bear all risk relating to quality,
38 use and performance of the software and/or related materials. You agree
39 to hold the Government harmless from any claim arising from your use
40 of the software.
41
42 *******************************************************************************/
43
44
45 /***********************************************************************
46 LIBRARY: LFS - NIST Latent Fingerprint System
47
48 FILE: UTIL.C
49 AUTHOR: Michael D. Garris
50 DATE: 03/16/1999
51
52 Contains general support routines required by the NIST
53 Latent Fingerprint System (LFS).
54
55 ***********************************************************************
56 ROUTINES:
57 maxv()
58 minv()
59 minmaxs()
60 distance()
61 squared_distance()
62 in_int_list()
63 remove_from_int_list()
64 find_incr_position_dbl()
65 angle2line()
66 line2direction()
67 closest_dir_dist()
68 ***********************************************************************/
69
70 #include <stdio.h>
71 #include <lfs.h>
72
73 /*************************************************************************
74 **************************************************************************
75 #cat: maxv - Determines the maximum value in the given list of integers.
76 #cat: NOTE, the list is assumed to be NOT empty!
77
78 Input:
79 list - non-empty list of integers to be searched
80 num - number of integers in the list
81 Return Code:
82 Maximum - maximum value in the list
83 **************************************************************************/
84 5960 int maxv(const int *list, const int num)
85 {
86 5960 int i;
87 5960 int maxval;
88
89 /* NOTE: The list is assumed to be NOT empty. */
90 /* Initialize running maximum to first item in list. */
91 5960 maxval = list[0];
92
93 /* Foreach subsequent item in the list... */
94
2/2
✓ Branch 0 taken 77320 times.
✓ Branch 1 taken 5960 times.
83280 for(i = 1; i < num; i++){
95 /* If current item is larger than running maximum... */
96 77320 if(list[i] > maxval)
97 /* Set running maximum to the larger item. */
98 maxval = list[i];
99 /* Otherwise, skip to next item. */
100 }
101
102 /* Return the resulting maximum. */
103 5960 return(maxval);
104 }
105
106 /*************************************************************************
107 **************************************************************************
108 #cat: minv - Determines the minimum value in the given list of integers.
109 #cat: NOTE, the list is assumed to be NOT empty!
110
111 Input:
112 list - non-empty list of integers to be searched
113 num - number of integers in the list
114 Return Code:
115 Minimum - minimum value in the list
116 **************************************************************************/
117 5960 int minv(const int *list, const int num)
118 {
119 5960 int i;
120 5960 int minval;
121
122 /* NOTE: The list is assumed to be NOT empty. */
123 /* Initialize running minimum to first item in list. */
124 5960 minval = list[0];
125
126 /* Foreach subsequent item in the list... */
127
2/2
✓ Branch 0 taken 77320 times.
✓ Branch 1 taken 5960 times.
83280 for(i = 1; i < num; i++){
128 /* If current item is smaller than running minimum... */
129 77320 if(list[i] < minval)
130 /* Set running minimum to the smaller item. */
131 minval = list[i];
132 /* Otherwise, skip to next item. */
133 }
134
135 /* Return the resulting minimum. */
136 5960 return(minval);
137 }
138
139 /*************************************************************************
140 **************************************************************************
141 #cat: minmaxs - Takes a list of integers and identifies points of relative
142 #cat: minima and maxima. The midpoint of flat plateaus and valleys
143 #cat: are selected when they are detected.
144
145 Input:
146 items - list of integers to be analyzed
147 num - number of items in the list
148 Output:
149 ominmax_val - value of the item at each minima or maxima
150 ominmax_type - identifies a minima as '-1' and maxima as '1'
151 ominmax_i - index of item's position in list
152 ominmax_alloc - number of allocated minima and/or maxima
153 ominmax_num - number of detected minima and/or maxima
154 Return Code:
155 Zero - successful completion
156 Negative - system error
157 **************************************************************************/
158 22400 int minmaxs(int **ominmax_val, int **ominmax_type, int **ominmax_i,
159 int *ominmax_alloc, int *ominmax_num,
160 const int *items, const int num)
161 {
162 22400 int i, diff, state, start, loc;
163 22400 int *minmax_val, *minmax_type, *minmax_i, minmax_alloc, minmax_num;
164
165
166 /* Determine maximum length for allocation of buffers. */
167 /* If there are fewer than 3 items ... */
168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22400 times.
22400 if(num < 3){
169 /* Then no min/max is possible, so set allocated length */
170 /* to 0 and return. */
171 *ominmax_alloc = 0;
172 *ominmax_num = 0;
173 return(0);
174 }
175 /* Otherwise, set allocation length to number of items - 2 */
176 /* (one for the first item in the list, and on for the last). */
177 /* Every other intermediate point can potentially represent a */
178 /* min or max. */
179 22400 minmax_alloc = num - 2;
180 /* Allocate the buffers. */
181 22400 minmax_val = (int *)g_malloc(minmax_alloc * sizeof(int));
182 22400 minmax_type = (int *)g_malloc(minmax_alloc * sizeof(int));
183 22400 minmax_i = (int *)g_malloc(minmax_alloc * sizeof(int));
184
185 /* Initialize number of min/max to 0. */
186 22400 minmax_num = 0;
187
188 /* Start witht the first item in the list. */
189 22400 i = 0;
190
191 /* Get starting state between first pair of items. */
192 22400 diff = items[1] - items[0];
193
2/2
✓ Branch 0 taken 15466 times.
✓ Branch 1 taken 6934 times.
22400 if(diff > 0)
194 state = 1;
195
2/2
✓ Branch 0 taken 2275 times.
✓ Branch 1 taken 13191 times.
15466 else if (diff < 0)
196 state = -1;
197 else
198 2275 state = 0;
199
200 /* Set start location to first item in list. */
201 start = 0;
202
203 /* Bump to next item in list. */
204 i++;
205
206 /* While not at the last item in list. */
207
2/2
✓ Branch 0 taken 291200 times.
✓ Branch 1 taken 22400 times.
313600 while(i < num-1){
208
209 /* Compute difference between next pair of items. */
210 291200 diff = items[i+1] - items[i];
211 /* If items are increasing ... */
212
2/2
✓ Branch 0 taken 136243 times.
✓ Branch 1 taken 154957 times.
291200 if(diff > 0){
213 /* If previously increasing ... */
214
2/2
✓ Branch 0 taken 13998 times.
✓ Branch 1 taken 122245 times.
136243 if(state == 1){
215 /* Reset start to current location. */
216 start = i;
217 }
218 /* If previously decreasing ... */
219
2/2
✓ Branch 0 taken 13385 times.
✓ Branch 1 taken 613 times.
13998 else if (state == -1){
220 /* Then we have incurred a minima ... */
221 /* Compute midpoint of minima. */
222 13385 loc = (start + i)/2;
223 /* Store value at minima midpoint. */
224 13385 minmax_val[minmax_num] = items[loc];
225 /* Store type code for minima. */
226 13385 minmax_type[minmax_num] = -1;
227 /* Store location of minima midpoint. */
228 13385 minmax_i[minmax_num++] = loc;
229 /* Change state to increasing. */
230 13385 state = 1;
231 /* Reset start location. */
232 13385 start = i;
233 }
234 /* If previously level (this state only can occur at the */
235 /* beginning of the list of items) ... */
236 else {
237 /* If more than one level state in a row ... */
238
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 517 times.
613 if(i-start > 1){
239 /* Then consider a minima ... */
240 /* Compute midpoint of minima. */
241 96 loc = (start + i)/2;
242 /* Store value at minima midpoint. */
243 96 minmax_val[minmax_num] = items[loc];
244 /* Store type code for minima. */
245 96 minmax_type[minmax_num] = -1;
246 /* Store location of minima midpoint. */
247 96 minmax_i[minmax_num++] = loc;
248 /* Change state to increasing. */
249 96 state = 1;
250 /* Reset start location. */
251 96 start = i;
252 }
253 /* Otherwise, ignore single level state. */
254 else{
255 /* Change state to increasing. */
256 state = 1;
257 /* Reset start location. */
258 start = i;
259 }
260 }
261 }
262 /* If items are decreasing ... */
263
2/2
✓ Branch 0 taken 115673 times.
✓ Branch 1 taken 39284 times.
154957 else if(diff < 0){
264 /* If previously decreasing ... */
265
2/2
✓ Branch 0 taken 7092 times.
✓ Branch 1 taken 108581 times.
115673 if(state == -1){
266 /* Reset start to current location. */
267 start = i;
268 }
269 /* If previously increasing ... */
270
2/2
✓ Branch 0 taken 5430 times.
✓ Branch 1 taken 1662 times.
7092 else if (state == 1){
271 /* Then we have incurred a maxima ... */
272 /* Compute midpoint of maxima. */
273 5430 loc = (start + i)/2;
274 /* Store value at maxima midpoint. */
275 5430 minmax_val[minmax_num] = items[loc];
276 /* Store type code for maxima. */
277 5430 minmax_type[minmax_num] = 1;
278 /* Store location of maxima midpoint. */
279 5430 minmax_i[minmax_num++] = loc;
280 /* Change state to decreasing. */
281 5430 state = -1;
282 /* Reset start location. */
283 5430 start = i;
284 }
285 /* If previously level (this state only can occur at the */
286 /* beginning of the list of items) ... */
287 else {
288 /* If more than one level state in a row ... */
289
2/2
✓ Branch 0 taken 282 times.
✓ Branch 1 taken 1380 times.
1662 if(i-start > 1){
290 /* Then consider a maxima ... */
291 /* Compute midpoint of maxima. */
292 282 loc = (start + i)/2;
293 /* Store value at maxima midpoint. */
294 282 minmax_val[minmax_num] = items[loc];
295 /* Store type code for maxima. */
296 282 minmax_type[minmax_num] = 1;
297 /* Store location of maxima midpoint. */
298 282 minmax_i[minmax_num++] = loc;
299 /* Change state to decreasing. */
300 282 state = -1;
301 /* Reset start location. */
302 282 start = i;
303 }
304 /* Otherwise, ignore single level state. */
305 else{
306 /* Change state to decreasing. */
307 state = -1;
308 /* Reset start location. */
309 start = i;
310 }
311 }
312 }
313 /* Otherwise, items are level, so continue to next item pair. */
314
315 /* Advance to next item pair in list. */
316 291200 i++;
317 }
318
319 /* Set results to output pointers. */
320 22400 *ominmax_val = minmax_val;
321 22400 *ominmax_type = minmax_type;
322 22400 *ominmax_i = minmax_i;
323 22400 *ominmax_alloc = minmax_alloc;
324 22400 *ominmax_num = minmax_num;
325
326 /* Return normally. */
327 22400 return(0);
328 }
329
330 /*************************************************************************
331 **************************************************************************
332 #cat: distance - Takes two coordinate points and computes the
333 #cat: Euclidean distance between the two points.
334
335 Input:
336 x1 - x-coord of first point
337 y1 - y-coord of first point
338 x2 - x-coord of second point
339 y2 - y-coord of second point
340 Return Code:
341 Distance - computed Euclidean distance
342 **************************************************************************/
343 825781 double distance(const int x1, const int y1, const int x2, const int y2)
344 {
345 825781 double dx, dy, dist;
346
347 /* Compute delta x between points. */
348 825781 dx = (double)(x1 - x2);
349 /* Compute delta y between points. */
350 825781 dy = (double)(y1 - y2);
351 /* Compute the squared distance between points. */
352 825781 dist = (dx*dx) + (dy*dy);
353 /* Take square root of squared distance. */
354 825781 dist = sqrt(dist);
355
356 /* Return the squared distance. */
357 825781 return(dist);
358 }
359
360 /*************************************************************************
361 **************************************************************************
362 #cat: squared_distance - Takes two coordinate points and computes the
363 #cat: squared distance between the two points.
364
365 Input:
366 x1 - x-coord of first point
367 y1 - y-coord of first point
368 x2 - x-coord of second point
369 y2 - y-coord of second point
370 Return Code:
371 Distance - computed squared distance
372 **************************************************************************/
373 59516 double squared_distance(const int x1, const int y1, const int x2, const int y2)
374 {
375 59516 double dx, dy, dist;
376
377 /* Compute delta x between points. */
378 59516 dx = (double)(x1 - x2);
379 /* Compute delta y between points. */
380 59516 dy = (double)(y1 - y2);
381 /* Compute the squared distance between points. */
382 59516 dist = (dx*dx) + (dy*dy);
383
384 /* Return the squared distance. */
385 59516 return(dist);
386 }
387
388 /*************************************************************************
389 **************************************************************************
390 #cat: in_int_list - Determines if a specified value is store in a list of
391 #cat: integers and returns its location if found.
392
393 Input:
394 item - value to search for in list
395 list - list of integers to be searched
396 len - number of integers in search list
397 Return Code:
398 Zero or greater - first location found equal to search value
399 Negative - search value not found in the list of integers
400 **************************************************************************/
401 41640 int in_int_list(const int item, const int *list, const int len)
402 {
403 41640 int i;
404
405 /* Foreach item in list ... */
406
2/2
✓ Branch 0 taken 72437 times.
✓ Branch 1 taken 41614 times.
114051 for(i = 0; i < len; i++){
407 /* If search item found in list ... */
408
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 72411 times.
72437 if(list[i] == item)
409 /* Return the location in list where found. */
410 26 return(i);
411 }
412
413 /* If we get here, then search item not found in list, */
414 /* so return -1 ==> NOT FOUND. */
415 return(-1);
416 }
417
418 /*************************************************************************
419 **************************************************************************
420 #cat: remove_from_int_list - Takes a position index into an integer list and
421 #cat: removes the value from the list, collapsing the resulting
422 #cat: list.
423
424 Input:
425 index - position of value to be removed from list
426 list - input list of integers
427 num - number of integers in the list
428 Output:
429 list - list with specified integer removed
430 num - decremented number of integers in list
431 Return Code:
432 Zero - successful completion
433 Negative - system error
434 **************************************************************************/
435
436 /*************************************************************************
437 **************************************************************************
438 #cat: ind_incr_position_dbl - Takes a double value and a list of doubles and
439 #cat: determines where in the list the double may be inserted,
440 #cat: preserving the increasing sorted order of the list.
441
442 Input:
443 val - value to be inserted into the list
444 list - list of double in increasing sorted order
445 num - number of values in the list
446 Return Code:
447 Zero or Positive - insertion position in the list
448 **************************************************************************/
449 33683 int find_incr_position_dbl(const double val, double *list, const int num)
450 {
451 33683 int i;
452
453 /* Foreach item in double list ... */
454
2/2
✓ Branch 0 taken 83733 times.
✓ Branch 1 taken 7412 times.
91145 for(i = 0; i < num; i++){
455 /* If the value is smaller than the current item in list ... */
456
2/2
✓ Branch 0 taken 26271 times.
✓ Branch 1 taken 57462 times.
83733 if(val < list[i])
457 /* Then we found were to insert the value in the list maintaining */
458 /* an increasing sorted order. */
459 26271 return(i);
460
461 /* Otherwise, the value is still larger than current item, so */
462 /* continue to next item in the list. */
463 }
464
465 /* Otherwise, we never found a slot within the list to insert the */
466 /* the value, so place at the end of the sorted list. */
467 return(i);
468 }
469
470 /*************************************************************************
471 **************************************************************************
472 #cat: angle2line - Takes two coordinate points and computes the angle
473 #cat: to the line formed by the two points.
474
475 Input:
476 fx - x-coord of first point
477 fy - y-coord of first point
478 tx - x-coord of second point
479 ty - y-coord of second point
480 Return Code:
481 Angle - angle to the specified line
482 **************************************************************************/
483 123803 double angle2line(const int fx, const int fy, const int tx, const int ty)
484 {
485 123803 double dx, dy, theta;
486
487 /* Compute slope of line connecting the 2 specified points. */
488 123803 dy = (double)(fy - ty);
489 123803 dx = (double)(tx - fx);
490 /* If delta's are sufficiently small ... */
491
4/4
✓ Branch 0 taken 10317 times.
✓ Branch 1 taken 113486 times.
✓ Branch 2 taken 10311 times.
✓ Branch 3 taken 6 times.
123803 if((fabs(dx) < MIN_SLOPE_DELTA) && (fabs(dy) < MIN_SLOPE_DELTA))
492 theta = 0.0;
493 /* Otherwise, compute angle to the line. */
494 else
495 123797 theta = atan2(dy, dx);
496
497 /* Return the compute angle in radians. */
498 123803 return(theta);
499 }
500
501 /*************************************************************************
502 **************************************************************************
503 #cat: line2direction - Takes two coordinate points and computes the
504 #cat: directon (on a full circle) in which the first points
505 #cat: to the second.
506
507 Input:
508 fx - x-coord of first point (pointing from)
509 fy - y-coord of first point (pointing from)
510 tx - x-coord of second point (pointing to)
511 ty - y-coord of second point (pointing to)
512 ndirs - number of IMAP directions (in semicircle)
513 Return Code:
514 Direction - determined direction on a "full" circle
515 **************************************************************************/
516 3061 int line2direction(const int fx, const int fy,
517 const int tx, const int ty, const int ndirs)
518 {
519 3061 double theta, pi_factor;
520 3061 int idir, full_ndirs;
521 3061 static double pi2 = M_PI*2.0;
522
523 /* Compute angle to line connecting the 2 points. */
524 /* Coordinates are swapped and order of points reversed to */
525 /* account for 0 direction is vertical and positive direction */
526 /* is clockwise. */
527 3061 theta = angle2line(ty, tx, fy, fx);
528
529 /* Make sure the angle is positive. */
530 3061 theta += pi2;
531 3061 theta = fmod(theta, pi2);
532 /* Convert from radians to integer direction on range [0..(ndirsX2)]. */
533 /* Multiply radians by units/radian ((ndirsX2)/(2PI)), and you get */
534 /* angle in integer units. */
535 /* Compute number of directions on full circle. */
536 3061 full_ndirs = ndirs<<1;
537 /* Compute the radians to integer direction conversion factor. */
538 3061 pi_factor = (double)full_ndirs/pi2;
539 /* Convert radian angle to integer direction on full circle. */
540 3061 theta *= pi_factor;
541 /* Need to truncate precision so that answers are consistent */
542 /* on different computer architectures when rounding doubles. */
543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3061 times.
3061 theta = trunc_dbl_precision(theta, TRUNC_SCALE);
544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3061 times.
3061 idir = sround(theta);
545 /* Make sure on range [0..(ndirsX2)]. */
546 3061 idir %= full_ndirs;
547
548 /* Return the integer direction. */
549 3061 return(idir);
550 }
551
552 /*************************************************************************
553 **************************************************************************
554 #cat: closest_dir_dist - Takes to integer IMAP directions and determines the
555 #cat: closest distance between them accounting for
556 #cat: wrap-around either at the beginning or ending of
557 #cat: the range of directions.
558
559 Input:
560 dir1 - integer value of the first direction
561 dir2 - integer value of the second direction
562 ndirs - the number of possible directions
563 Return Code:
564 Non-negative - distance between the 2 directions
565 **************************************************************************/
566 410025 int closest_dir_dist(const int dir1, const int dir2, const int ndirs)
567 {
568 410025 int d1, d2, dist;
569
570 /* Initialize distance to -1 = INVALID. */
571 410025 dist = INVALID_DIR;
572
573 /* Measure shortest distance between to directions. */
574 /* If both neighbors are VALID ... */
575
2/2
✓ Branch 0 taken 390859 times.
✓ Branch 1 taken 19166 times.
410025 if((dir1 >= 0)&&(dir2 >= 0)){
576 /* Compute inner and outer distances to account for distances */
577 /* that wrap around the end of the range of directions, which */
578 /* may in fact be closer. */
579 390859 d1 = abs(dir2 - dir1);
580 390859 d2 = ndirs - d1;
581 390859 dist = min(d1, d2);
582 }
583 /* Otherwise one or both directions are INVALID, so ignore */
584 /* and return INVALID. */
585
586 /* Return determined closest distance. */
587 410025 return(dist);
588 }
589
590