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