NACO Pipeline Reference Manual  4.4.0
irplib_utils.h
1 /* $Id: irplib_utils.h,v 1.60 2013-08-21 14:55:14 cgarcia Exp $
2  *
3  * This file is part of the irplib package
4  * Copyright (C) 2002,2003 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: cgarcia $
23  * $Date: 2013-08-21 14:55:14 $
24  * $Revision: 1.60 $
25  * $Name: not supported by cvs2svn $
26  * $Log: not supported by cvs2svn $
27  * Revision 1.59 2013/03/15 09:06:06 jtaylor
28  * add irplib_aligned_{[mc]alloc,free}
29  *
30  * allow portable allocation of aligned memory for vectorization
31  *
32  * Revision 1.58 2013/03/15 09:05:28 jtaylor
33  * move isnan and isinf to header so it is inlineable and use gcc builtin for better performance
34  *
35  * Revision 1.57 2013/02/27 16:02:02 jtaylor
36  * add diagnostic pragma macros
37  *
38  * Revision 1.56 2012/08/06 06:14:18 llundin
39  * irplib_errorstate_warning(): Replaced by cpl_errorstate_dump_one_warning() from CPL 6.X
40  *
41  * Revision 1.55 2011/06/01 06:47:56 llundin
42  * skip_if_lt(): Fix previous edits switch of A and B in error message
43  *
44  * Revision 1.54 2011/05/26 08:08:56 llundin
45  * skip_if_lt(): Support printf-style error message, name-space protect temporary variables
46  *
47  * Revision 1.53 2011/05/09 07:51:18 llundin
48  * irplib_dfs_save_image_(): Modified from cpl_dfs_save_image(). irplib_dfs_save_image(): Use irplib_dfs_save_image_()
49  *
50  * Revision 1.52 2010/03/23 07:57:59 kmirny
51  * DFS08552, Documentation for irplib_frameset_sort
52  *
53  * Revision 1.51 2009/12/16 14:59:30 cgarcia
54  * Avoid name clash with index function
55  *
56  * Revision 1.50 2009/08/17 15:10:16 kmirny
57  *
58  * DFS07454 DFS07437
59  *
60  */
61 
62 #ifndef IRPLIB_UTILS_H
63 #define IRPLIB_UTILS_H
64 
65 /*-----------------------------------------------------------------------------
66  Includes
67  -----------------------------------------------------------------------------*/
68 
69 #include <cpl.h>
70 #include <math.h>
71 #include <stdarg.h>
72 
73 /*-----------------------------------------------------------------------------
74  Define
75  -----------------------------------------------------------------------------*/
76 
77 #define IRPLIB_XSTRINGIFY(TOSTRING) #TOSTRING
78 #define IRPLIB_STRINGIFY(TOSTRING) IRPLIB_XSTRINGIFY(TOSTRING)
79 
80 #if !defined __GNUC__ && !defined __inline__
81 #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
82 #define __inline__ inline
83 #else
84 #define __inline__
85 #endif
86 #endif
87 
88 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
89 #define IRPLIB_DIAG_PRAGMA_PUSH_IGN(x) \
90  _Pragma("GCC diagnostic push") \
91  _Pragma(IRPLIB_STRINGIFY(GCC diagnostic ignored #x))
92 #define IRPLIB_DIAG_PRAGMA_PUSH_ERR(x) \
93  _Pragma("GCC diagnostic push") \
94  _Pragma(IRPLIB_STRINGIFY(GCC diagnostic error #x))
95 #define IRPLIB_DIAG_PRAGMA_POP \
96  _Pragma("GCC diagnostic pop")
97 #else
98 #define IRPLIB_DIAG_PRAGMA_PUSH_IGN(x)
99 #define IRPLIB_DIAG_PRAGMA_PUSH_ERR(x)
100 #define IRPLIB_DIAG_PRAGMA_POP
101 #endif
102 
103 
104 /* FIXME: Remove when no longer used by any irplib-based pipelines */
105 /* Useful for debugging */
106 #define irplib_trace() do if (cpl_error_get_code()) { \
107  cpl_msg_debug(cpl_func, __FILE__ " at line %d: ERROR '%s' at %s", \
108  __LINE__, cpl_error_get_message(), cpl_error_get_where()); \
109  } else { \
110  cpl_msg_debug(cpl_func, __FILE__ " at line %d: OK", __LINE__); \
111  } while (0)
112 
113 #define irplib_error_recover(ESTATE, ...) \
114  do if (!cpl_errorstate_is_equal(ESTATE)) { \
115  cpl_msg_warning(cpl_func, __VA_ARGS__); \
116  cpl_msg_indent_more(); \
117  cpl_errorstate_dump(ESTATE, CPL_FALSE, \
118  cpl_errorstate_dump_one_warning); \
119  cpl_msg_indent_less(); \
120  cpl_errorstate_set(ESTATE); \
121  } while (0)
122 
123 
124 
125 /*----------------------------------------------------------------------------*/
126 /*
127  @brief Declare a function suitable for use with irplib_dfs_table_convert()
128  @param table_set_row The name of the function to declare
129  @see irplib_dfs_table_convert(), irplib_table_read_from_frameset()
130 
131 */
132 /*----------------------------------------------------------------------------*/
133 #define IRPLIB_UTIL_SET_ROW(table_set_row) \
134  cpl_boolean table_set_row(cpl_table *, \
135  const char *, \
136  int, \
137  const cpl_frame *, \
138  const cpl_parameterlist *)
139 
140 
141 /*----------------------------------------------------------------------------*/
142 /*
143  @brief Declare a function suitable for use with irplib_dfs_table_convert()
144  @param table_check The name of the function to declare
145  @see irplib_dfs_table_convert()
146 
147 */
148 /*----------------------------------------------------------------------------*/
149 #define IRPLIB_UTIL_CHECK(table_check) \
150  cpl_error_code table_check(cpl_table *, \
151  const cpl_frameset *, \
152  const cpl_parameterlist *)
153 
154 
155 /*----------------------------------------------------------------------------*/
156 /*
157  @brief Conditional skip to the (unqiue) return point of the function
158  @param CONDITION The condition to check
159  @see cpl_error_ensure()
160 
161  skip_if() takes one argument, which is a logical expression.
162  If the logical expression is false skip_if() takes no action and
163  program execution continues.
164  If the logical expression is true this indicates an error. In this case
165  skip_if() will set the location of the error to the point where it
166  was invoked in the recipe code (unless the error location is already in the
167  recipe code). If no error code had been set, then skip_if() will set one.
168  Finally, skip_if() causes program execution to skip to the macro 'end_skip'.
169  The macro end_skip is located towards the end of the function, after
170  which all resource deallocation and the function return is located.
171 
172  The use of skip_if() assumes the following coding practice:
173  1) Pointers used for dynamically allocated memory that they "own" shall always
174  point to either NULL or to allocated memory (including CPL-objects).
175  2) Such pointers may not be reused to point to memory whose deallocation
176  requires calls to different functions.
177  3) Pointers of type FILE should be set NULL when not pointing to an open
178  stream and their closing calls (fclose(), freopen(), etc.) following the
179  'end_skip' should be guarded against such NULL pointers.
180 
181  Error checking with skip_if() is encouraged due to the following advantages:
182  1) It ensures that a CPL-error code is set.
183  2) It ensures that the location of the error in the _recipe_ code is noted.
184  3) The error checking may be confined to a single concise line.
185  4) It is not necessary to replicate memory deallocation for every error
186  condition.
187  5) If more extensive error reporting/handling is required it is not precluded
188  by the use of skip_if().
189  6) It allows for a single point of function return.
190  7) It allows for optional, uniformly formatted debugging/tracing information
191  at each macro invocation.
192 
193  The implementation of skip_if() uses a goto/label construction.
194  According to Kerningham & Ritchie, The C Programming Language, 2nd edition,
195  Section 3.8:
196  "This organization is handy if the error-handling code is non-trivial,
197  and if errors can occur in several places."
198 
199  The use of goto for any other purpose should be avoided.
200 
201 */
202 /*----------------------------------------------------------------------------*/
203 #define skip_if(CONDITION) \
204  do { \
205  cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(), \
206  goto cleanup, "Propagating a pre-existing error"); \
207  cpl_error_ensure(!(CONDITION), cpl_error_get_code(), \
208  goto cleanup, "Propagating error");\
209  } while (0)
210 
211 /*----------------------------------------------------------------------------*/
212 /*
213  @brief Skip if A < B
214  @param A The 1st double to compare
215  @param B The 2nd double to compare
216  @param MSG A printf-style error message, 1st arg should be a string literal
217  @see skip_if()
218  @note A and B are evaluated exactly once
219 
220  If no CPL error is set, sets CPL_ERROR_DATA_NOT_FOUND on failure
221 */
222 /*----------------------------------------------------------------------------*/
223 #define skip_if_lt(A, B, ...) \
224  do { \
225  /* Name-space protected one-time only evaluation */ \
226  const double irplib_utils_a = (double)(A); \
227  const double irplib_utils_b = (double)(B); \
228  \
229  cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(), \
230  goto cleanup, "Propagating a pre-existing error"); \
231  if (irplib_utils_a < irplib_utils_b) { \
232  char * irplib_utils_msg = cpl_sprintf(__VA_ARGS__); \
233  (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND, \
234  "Need at least %g (not %g) %s", \
235  irplib_utils_b, irplib_utils_a, \
236  irplib_utils_msg); \
237  cpl_free(irplib_utils_msg); \
238  goto cleanup; \
239  } \
240  } while (0)
241 
242 /*----------------------------------------------------------------------------*/
243 /*
244  @brief Conditional skip on coding bug
245  @param CONDITION The condition to check
246  @see skip_if()
247  @note unlike assert() this check cannot be disabled
248  */
249 /*----------------------------------------------------------------------------*/
250 #define bug_if(CONDITION) \
251  do { \
252  cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(), \
253  goto cleanup, "Propagating an unexpected error, " \
254  "please report to " PACKAGE_BUGREPORT); \
255  cpl_error_ensure(!(CONDITION), CPL_ERROR_UNSPECIFIED, \
256  goto cleanup, "Internal error, please report to " \
257  PACKAGE_BUGREPORT); \
258  } while (0)
259 
260 /*----------------------------------------------------------------------------*/
261 /*
262  @brief Conditional skip with error creation
263  @param CONDITION The condition to check
264  @param ERROR The error code to set
265  @param MSG A printf-style error message. As a matter of
266  user-friendliness the message should mention any
267  value that caused the @em CONDITION to fail.
268  @see skip_if()
269  @note unlike assert() this check cannot be disabled
270  */
271 /*----------------------------------------------------------------------------*/
272 #define error_if(CONDITION, ERROR, ...) \
273  cpl_error_ensure(cpl_error_get_code() == CPL_ERROR_NONE && \
274  !(CONDITION), ERROR, goto cleanup, __VA_ARGS__)
275 
276 /*----------------------------------------------------------------------------*/
277 /*
278  @brief Propagate a preexisting error, if any
279  @param MSG A printf-style error message.
280  @see skip_if()
281  */
282 /*----------------------------------------------------------------------------*/
283 #define any_if(...) \
284  cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(), \
285  goto cleanup, __VA_ARGS__)
286 
287 /*----------------------------------------------------------------------------*/
288 /*
289  @brief Define the single point of resource deallocation and return
290  @see skip_if()
291  @note end_skip should be used exactly once in functions that use skip_if() etc
292 */
293 /*----------------------------------------------------------------------------*/
294 #define end_skip \
295  do { \
296  cleanup: \
297  if (cpl_error_get_code()) \
298  cpl_msg_debug(cpl_func, "Cleanup in " __FILE__ " line %u with " \
299  "error '%s' at %s", __LINE__, \
300  cpl_error_get_message(), cpl_error_get_where()); \
301  else \
302  cpl_msg_debug(cpl_func, "Cleanup in " __FILE__ " line %u", \
303  __LINE__); \
304  } while (0)
305 
306 
307 /*----------------------------------------------------------------------------*/
319 /*----------------------------------------------------------------------------*/
320 #define irplib_ensure(CONDITION, ec, ...) \
321  cpl_error_ensure(CONDITION, ec, goto cleanup, __VA_ARGS__)
322 
323 /*----------------------------------------------------------------------------*/
353 /*----------------------------------------------------------------------------*/
354 
355 #define irplib_check(COMMAND, ...) \
356  do { \
357  cpl_errorstate irplib_check_prestate = cpl_errorstate_get(); \
358  skip_if(0); \
359  COMMAND; \
360  irplib_trace(); \
361  irplib_ensure(cpl_errorstate_is_equal(irplib_check_prestate), \
362  cpl_error_get_code(), __VA_ARGS__); \
363  irplib_trace(); \
364  } while (0)
365 
366 /*-----------------------------------------------------------------------------
367  Function prototypes
368  -----------------------------------------------------------------------------*/
369 
370 cpl_error_code irplib_dfs_save_image(cpl_frameset *,
371  const cpl_parameterlist *,
372  const cpl_frameset *,
373  const cpl_image *,
374  cpl_type_bpp ,
375  const char *,
376  const char *,
377  const cpl_propertylist *,
378  const char *,
379  const char *,
380  const char *);
381 
382 
383 cpl_error_code irplib_dfs_save_propertylist(cpl_frameset *,
384  const cpl_parameterlist *,
385  const cpl_frameset *,
386  const char *,
387  const char *,
388  const cpl_propertylist *,
389  const char *,
390  const char *,
391  const char *);
392 
393 cpl_error_code irplib_dfs_save_imagelist(cpl_frameset *,
394  const cpl_parameterlist *,
395  const cpl_frameset *,
396  const cpl_imagelist *,
397  cpl_type_bpp ,
398  const char *,
399  const char *,
400  const cpl_propertylist *,
401  const char *,
402  const char *,
403  const char *);
404 
405 cpl_error_code irplib_dfs_save_table(cpl_frameset *,
406  const cpl_parameterlist *,
407  const cpl_frameset *,
408  const cpl_table *,
409  const cpl_propertylist *,
410  const char *,
411  const char *,
412  const cpl_propertylist *,
413  const char *,
414  const char *,
415  const char *);
416 
417 cpl_error_code irplib_dfs_save_image_(cpl_frameset *,
418  cpl_propertylist *,
419  const cpl_parameterlist *,
420  const cpl_frameset *,
421  const cpl_frame *,
422  const cpl_image *,
423  cpl_type ,
424  const char *,
425  const cpl_propertylist *,
426  const char *,
427  const char *,
428  const char *);
429 
430 void irplib_reset(void);
431 int irplib_compare_tags(cpl_frame *, cpl_frame *);
432 const char * irplib_frameset_find_file(const cpl_frameset *, const char *);
433 const cpl_frame * irplib_frameset_get_first_from_group(const cpl_frameset *,
434  cpl_frame_group);
435 
436 cpl_error_code irplib_apertures_find_max_flux(const cpl_apertures *, int *,
437  int);
438 
439 #if defined HAVE_ISNAN && HAVE_ISNAN != 0
440 #if !defined isnan && defined HAVE_DECL_ISNAN && HAVE_DECL_ISNAN == 0
441 /* HP-UX and Solaris may have isnan() available at link-time
442  without the prototype */
443 int isnan(double);
444 #endif
445 #endif
446 
447 cpl_error_code
448 irplib_dfs_table_convert(cpl_table *, cpl_frameset *, const cpl_frameset *,
449  int, char, const char *, const char *,
450  const cpl_parameterlist *, const char *,
451  const cpl_propertylist *, const cpl_propertylist *,
452  const char *, const char *, const char *,
453  cpl_boolean (*)(cpl_table *, const char *, int,
454  const cpl_frame *,
455  const cpl_parameterlist *),
456  cpl_error_code (*)(cpl_table *,
457  const cpl_frameset *,
458  const cpl_parameterlist *));
459 
460 cpl_error_code irplib_table_read_from_frameset(cpl_table *,
461  const cpl_frameset *,
462  int,
463  char,
464  const cpl_parameterlist *,
465  cpl_boolean (*)
466  (cpl_table *, const char *,
467  int, const cpl_frame *,
468  const cpl_parameterlist *));
469 
470 cpl_error_code irplib_image_split(const cpl_image *,
471  cpl_image *, cpl_image *, cpl_image *,
472  double, cpl_boolean,
473  double, cpl_boolean,
474  double, double,
475  cpl_boolean, cpl_boolean, cpl_boolean);
476 
477 void irplib_errorstate_dump_warning(unsigned, unsigned, unsigned);
478 void irplib_errorstate_dump_info(unsigned, unsigned, unsigned);
479 void irplib_errorstate_dump_debug(unsigned, unsigned, unsigned);
480 /* wrapper for replace deprecated function cpl_polynomial_fit_1d_create*/
481 cpl_polynomial * irplib_polynomial_fit_1d_create(
482  const cpl_vector * x_pos,
483  const cpl_vector * values,
484  int degree,
485  double * mse
486  );
487 cpl_polynomial * irplib_polynomial_fit_1d_create_chiq(
488  const cpl_vector * x_pos,
489  const cpl_vector * values,
490  int degree,
491  double * rechiq
492  );
493 /*----------------------------------------------------------------------------*/
501 cpl_error_code irplib_frameset_sort(
502  const cpl_frameset * self,
503  int* iindex,
504  double* exptime);
505 
506 
507 /* FIXME: add alloc_size(2) */
508 void * irplib_aligned_malloc(size_t alignment, size_t size) CPL_ATTR_ALLOC;
509 void * irplib_aligned_calloc(size_t alignment,
510  size_t nelem, size_t nbytes) CPL_ATTR_ALLOC;
511 void irplib_aligned_free (void * aligned_ptr);
512 
513 const cpl_frame *
514 irplib_frameset_get_first_const(cpl_frameset_iterator **iterator,
515  const cpl_frameset *frameset);
516 
517 const cpl_frame *
518 irplib_frameset_get_next_const(cpl_frameset_iterator *iterator);
519 
520 /*-----------------------------------------------------------------------------
521  Function inlines
522  -----------------------------------------------------------------------------*/
523 
524 
525 /*----------------------------------------------------------------------------*/
529 /*----------------------------------------------------------------------------*/
530 static __inline__ int irplib_isinf(double value)
531 {
532 /* documented only on 4.4, but available in at least 4.2 */
533 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)
534  return __builtin_isinf(value);
535 #elif defined HAVE_ISINF && HAVE_ISINF
536  return isinf(value);
537 #else
538  return value != 0 && value == 2 * value;
539 #endif
540 }
541 
542 
543 /*----------------------------------------------------------------------------*/
547 /*----------------------------------------------------------------------------*/
548 static __inline__ int irplib_isnan(double value)
549 {
550 /* documented only on 4.4, but available in at least 4.2 */
551 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)
552  return __builtin_isnan(value);
553 #elif defined HAVE_ISNAN && HAVE_ISNAN
554  return isnan(value);
555 #else
556  return value != value;
557 #endif
558 }
559 
560 #endif
cpl_error_code irplib_dfs_save_table(cpl_frameset *, const cpl_parameterlist *, const cpl_frameset *, const cpl_table *, const cpl_propertylist *, const char *, const char *, const cpl_propertylist *, const char *, const char *, const char *)
Save a table as a DFS-compliant pipeline product.
Definition: irplib_utils.c:351
void irplib_errorstate_dump_info(unsigned, unsigned, unsigned)
Dump a single CPL error at the CPL info level.
Definition: irplib_utils.c:157
cpl_error_code irplib_table_read_from_frameset(cpl_table *, const cpl_frameset *, int, char, const cpl_parameterlist *, cpl_boolean(*)(cpl_table *, const char *, int, const cpl_frame *, const cpl_parameterlist *))
Set the rows of a table with data from one or more (ASCII) files.
Definition: irplib_utils.c:989
void irplib_reset(void)
Reset IRPLIB state.
cpl_error_code irplib_apertures_find_max_flux(const cpl_apertures *, int *, int)
Find the aperture(s) with the greatest flux.
cpl_error_code irplib_dfs_save_propertylist(cpl_frameset *, const cpl_parameterlist *, const cpl_frameset *, const char *, const char *, const cpl_propertylist *, const char *, const char *, const char *)
Save a propertylist as a DFS-compliant pipeline product.
Definition: irplib_utils.c:256
cpl_error_code irplib_dfs_save_image_(cpl_frameset *, cpl_propertylist *, const cpl_parameterlist *, const cpl_frameset *, const cpl_frame *, const cpl_image *, cpl_type, const char *, const cpl_propertylist *, const char *, const char *, const char *)
Save an image as a DFS-compliant pipeline product.
Definition: irplib_utils.c:411
const cpl_frame * irplib_frameset_get_first_from_group(const cpl_frameset *, cpl_frame_group)
Find the first frame belonging to the given group.
cpl_error_code irplib_dfs_table_convert(cpl_table *, cpl_frameset *, const cpl_frameset *, int, char, const char *, const char *, const cpl_parameterlist *, const char *, const cpl_propertylist *, const cpl_propertylist *, const char *, const char *, const char *, cpl_boolean(*)(cpl_table *, const char *, int, const cpl_frame *, const cpl_parameterlist *), cpl_error_code(*)(cpl_table *, const cpl_frameset *, const cpl_parameterlist *))
Create a DFS product with one table from one or more (ASCII) file(s)
Definition: irplib_utils.c:860
void irplib_errorstate_dump_warning(unsigned, unsigned, unsigned)
Dump a single CPL error at the CPL warning level.
Definition: irplib_utils.c:130
void irplib_errorstate_dump_debug(unsigned, unsigned, unsigned)
Dump a single CPL error at the CPL debug level.
Definition: irplib_utils.c:177
cpl_error_code irplib_dfs_save_image(cpl_frameset *, const cpl_parameterlist *, const cpl_frameset *, const cpl_image *, cpl_type_bpp, const char *, const char *, const cpl_propertylist *, const char *, const char *, const char *)
Save an image as a DFS-compliant pipeline product.
Definition: irplib_utils.c:208
int irplib_compare_tags(cpl_frame *, cpl_frame *)
Comparison function to identify different input frames.
const char * irplib_frameset_find_file(const cpl_frameset *, const char *)
Find the filename with the given tag in a frame set.
cpl_error_code irplib_image_split(const cpl_image *, cpl_image *, cpl_image *, cpl_image *, double, cpl_boolean, double, cpl_boolean, double, double, cpl_boolean, cpl_boolean, cpl_boolean)
Split the values in an image in three according to two thresholds.
Definition: irplib_utils.c:665
cpl_error_code irplib_dfs_save_imagelist(cpl_frameset *, const cpl_parameterlist *, const cpl_frameset *, const cpl_imagelist *, cpl_type_bpp, const char *, const char *, const cpl_propertylist *, const char *, const char *, const char *)
Save an imagelist as a DFS-compliant pipeline product.
Definition: irplib_utils.c:303