irplib_utils.c

00001 /* $Id: irplib_utils.c,v 1.85 2013-07-04 12:10:55 jtaylor Exp $
00002  *
00003  * This file is part of the irplib package
00004  * Copyright (C) 2002,2003 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: jtaylor $
00023  * $Date: 2013-07-04 12:10:55 $
00024  * $Revision: 1.85 $
00025  * $Name: not supported by cvs2svn $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                    Includes
00034  -----------------------------------------------------------------------------*/
00035 #include "irplib_utils.h"
00036 
00037 #include <cpl.h>
00038 #include <math.h>
00039 
00040 #include <string.h>
00041 #include <assert.h>
00042 #include <stdlib.h>
00043 #include <errno.h>
00044 
00045 
00046 
00047 /*-----------------------------------------------------------------------------
00048                            Defines
00049  -----------------------------------------------------------------------------*/
00050 
00051 /* TEMPORARY SUPPORT OF CPL 5.x */
00052 #ifndef CPL_SIZE_FORMAT
00053 #define CPL_SIZE_FORMAT "d"
00054 #define cpl_size int
00055 #endif
00056 /* END TEMPORARY SUPPORT OF CPL 5.x */
00057 
00058 #ifndef inline
00059 #define inline /* inline */
00060 #endif
00061 
00062 /*-----------------------------------------------------------------------------
00063                            Missing Function Prototypes
00064  -----------------------------------------------------------------------------*/
00065 
00066 /*-----------------------------------------------------------------------------
00067                            Private Function Prototypes
00068  -----------------------------------------------------------------------------*/
00069 
00070 inline static double irplib_data_get_double(const void *, cpl_type, int)
00071 #ifdef CPL_HAVE_GNUC_NONNULL
00072      __attribute__((nonnull))
00073 #endif
00074     ;
00075 
00076 inline static void irplib_data_set_double(void *, cpl_type, int, double)
00077 #ifdef CPL_HAVE_GNUC_NONNULL
00078      __attribute__((nonnull))
00079 #endif
00080     ;
00081 
00082 
00083 static
00084 void irplib_errorstate_dump_one_level(void (*)(const char *,
00085                                                const char *, ...)
00086   #ifdef __GNUC__
00087       __attribute__((format (printf, 2, 3)))
00088   #endif
00089                                       , unsigned, unsigned, unsigned);
00090 static double frame_get_exptime(const cpl_frame * pframe);
00091 static void quicksort(int* index, double* exptime, int left, int right);
00092 
00093 static cpl_error_code irplib_dfs_product_save(cpl_frameset *,
00094                                               cpl_propertylist *,
00095                                               const cpl_parameterlist *,
00096                                               const cpl_frameset *,
00097                                               const cpl_frame *,
00098                                               const cpl_imagelist *,
00099                                               const cpl_image *,
00100                                               cpl_type,
00101                                               const cpl_table *,
00102                                               const cpl_propertylist *,
00103                                               const char *,
00104                                               const cpl_propertylist *,
00105                                               const char *,
00106                                               const char *,
00107                                               const char *);
00108 
00109 /*----------------------------------------------------------------------------*/
00113 /*----------------------------------------------------------------------------*/
00117 /*----------------------------------------------------------------------------*/
00129 /*----------------------------------------------------------------------------*/
00130 void irplib_errorstate_dump_warning(unsigned self, unsigned first,
00131                                     unsigned last)
00132 {
00133 
00134     irplib_errorstate_dump_one_level(&cpl_msg_warning, self, first, last);
00135 
00136 }
00137 
00138 static cpl_polynomial * irplib_polynomial_fit_1d_create_common(
00139         const cpl_vector    *   x_pos,
00140         const cpl_vector    *   values,
00141         int                     degree,
00142         double              *   mse,
00143         double              *  rechisq
00144         );
00145 
00146 /*----------------------------------------------------------------------------*/
00156 /*----------------------------------------------------------------------------*/
00157 void irplib_errorstate_dump_info(unsigned self, unsigned first,
00158                                     unsigned last)
00159 {
00160 
00161     irplib_errorstate_dump_one_level(&cpl_msg_info, self, first, last);
00162 
00163 }
00164 
00165 
00166 /*----------------------------------------------------------------------------*/
00176 /*----------------------------------------------------------------------------*/
00177 void irplib_errorstate_dump_debug(unsigned self, unsigned first,
00178                                     unsigned last)
00179 {
00180 
00181     irplib_errorstate_dump_one_level(&cpl_msg_debug, self, first, last);
00182 
00183 }
00184 
00185 
00186 /*----------------------------------------------------------------------------*/
00207 /*----------------------------------------------------------------------------*/
00208 cpl_error_code irplib_dfs_save_image(cpl_frameset            * allframes,
00209                                      const cpl_parameterlist * parlist,
00210                                      const cpl_frameset      * usedframes,
00211                                      const cpl_image         * image,
00212                                      cpl_type_bpp              bpp,
00213                                      const char              * recipe,
00214                                      const char              * procat,
00215                                      const cpl_propertylist  * applist,
00216                                      const char              * remregexp,
00217                                      const char              * pipe_id,
00218                                      const char              * filename)
00219 {
00220     cpl_errorstate     prestate = cpl_errorstate_get();
00221     cpl_propertylist * prolist  = applist ? cpl_propertylist_duplicate(applist)
00222         : cpl_propertylist_new();
00223 
00224     cpl_propertylist_update_string(prolist, CPL_DFS_PRO_CATG, procat);
00225 
00226     irplib_dfs_save_image_(allframes, NULL, parlist, usedframes, NULL, image,
00227                            bpp, recipe, prolist, remregexp, pipe_id, filename);
00228 
00229     cpl_propertylist_delete(prolist);
00230 
00231     cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
00232 
00233     return CPL_ERROR_NONE;
00234 
00235 }
00236 
00237 /*----------------------------------------------------------------------------*/
00254 /*----------------------------------------------------------------------------*/
00255 cpl_error_code
00256 irplib_dfs_save_propertylist(cpl_frameset            * allframes,
00257                              const cpl_parameterlist * parlist,
00258                              const cpl_frameset      * usedframes,
00259                              const char              * recipe,
00260                              const char              * procat,
00261                              const cpl_propertylist  * applist,
00262                              const char              * remregexp,
00263                              const char              * pipe_id,
00264                              const char              * filename)
00265 {
00266     cpl_errorstate     prestate = cpl_errorstate_get();
00267     cpl_propertylist * prolist  = applist ? cpl_propertylist_duplicate(applist)
00268         : cpl_propertylist_new();
00269 
00270     cpl_propertylist_update_string(prolist, CPL_DFS_PRO_CATG, procat);
00271 
00272     cpl_dfs_save_propertylist(allframes, NULL, parlist, usedframes, NULL,
00273                               recipe, prolist, remregexp, pipe_id, filename);
00274 
00275     cpl_propertylist_delete(prolist);
00276 
00277     cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
00278 
00279     return CPL_ERROR_NONE;
00280 
00281 }
00282 
00283 /*----------------------------------------------------------------------------*/
00302 /*----------------------------------------------------------------------------*/
00303 cpl_error_code irplib_dfs_save_imagelist(cpl_frameset            * allframes,
00304                                          const cpl_parameterlist * parlist,
00305                                          const cpl_frameset      * usedframes,
00306                                          const cpl_imagelist     * imagelist,
00307                                          cpl_type_bpp              bpp,
00308                                          const char              * recipe,
00309                                          const char              * procat,
00310                                          const cpl_propertylist  * applist,
00311                                          const char              * remregexp,
00312                                          const char              * pipe_id,
00313                                          const char              * filename)
00314 {
00315     cpl_errorstate     prestate = cpl_errorstate_get();
00316     cpl_propertylist * prolist  = applist ? cpl_propertylist_duplicate(applist)
00317         : cpl_propertylist_new();
00318 
00319     cpl_propertylist_update_string(prolist, CPL_DFS_PRO_CATG, procat);
00320 
00321     cpl_dfs_save_imagelist(allframes, NULL, parlist, usedframes, NULL,
00322                            imagelist, bpp, recipe, prolist, remregexp, pipe_id,
00323                            filename);
00324 
00325     cpl_propertylist_delete(prolist);
00326 
00327     cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
00328 
00329     return CPL_ERROR_NONE;
00330 }
00331 
00332 /*----------------------------------------------------------------------------*/
00350 /*----------------------------------------------------------------------------*/
00351 cpl_error_code irplib_dfs_save_table(cpl_frameset            * allframes,
00352                                      const cpl_parameterlist * parlist,
00353                                      const cpl_frameset      * usedframes,
00354                                      const cpl_table         * table,
00355                                      const cpl_propertylist  * tablelist,
00356                                      const char              * recipe,
00357                                      const char              * procat,
00358                                      const cpl_propertylist  * applist,
00359                                      const char              * remregexp,
00360                                      const char              * pipe_id,
00361                                      const char              * filename)
00362 {
00363 
00364     cpl_errorstate     prestate = cpl_errorstate_get();
00365     cpl_propertylist * prolist  = applist ? cpl_propertylist_duplicate(applist)
00366         : cpl_propertylist_new();
00367 
00368     cpl_propertylist_update_string(prolist, CPL_DFS_PRO_CATG, procat);
00369 
00370     cpl_dfs_save_table(allframes, NULL, parlist, usedframes, NULL,
00371                            table, tablelist, recipe, prolist, remregexp,
00372                            pipe_id, filename);
00373 
00374     cpl_propertylist_delete(prolist);
00375 
00376     cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
00377 
00378     return CPL_ERROR_NONE;
00379 }
00380 
00381 
00382 
00383 /*----------------------------------------------------------------------------*/
00410 /*----------------------------------------------------------------------------*/
00411 cpl_error_code irplib_dfs_save_image_(cpl_frameset            * allframes,
00412                                       cpl_propertylist        * header,
00413                                       const cpl_parameterlist * parlist,
00414                                       const cpl_frameset      * usedframes,
00415                                       const cpl_frame         * inherit,
00416                                       const cpl_image         * image,
00417                                       cpl_type                  type,
00418                                       const char              * recipe,
00419                                       const cpl_propertylist  * applist,
00420                                       const char              * remregexp,
00421                                       const char              * pipe_id,
00422                                       const char              * filename)
00423 {
00424     return
00425         irplib_dfs_product_save(allframes, header, parlist, usedframes, inherit,
00426                                 NULL, image, type, NULL, NULL, recipe,
00427                                 applist, remregexp, pipe_id, filename)
00428         ? cpl_error_set_where(cpl_func) : CPL_ERROR_NONE;
00429 
00430 }
00431 
00432 
00433 /*----------------------------------------------------------------------------*/
00457 /*----------------------------------------------------------------------------*/
00458 
00459 static
00460 cpl_error_code irplib_dfs_product_save(cpl_frameset            * allframes,
00461                                        cpl_propertylist        * header,
00462                                        const cpl_parameterlist * parlist,
00463                                        const cpl_frameset      * usedframes,
00464                                        const cpl_frame         * inherit,
00465                                        const cpl_imagelist     * imagelist,
00466                                        const cpl_image         * image,
00467                                        cpl_type                  type,
00468                                        const cpl_table         * table,
00469                                        const cpl_propertylist  * tablelist,
00470                                        const char              * recipe,
00471                                        const cpl_propertylist  * applist,
00472                                        const char              * remregexp,
00473                                        const char              * pipe_id,
00474                                        const char              * filename) {
00475 
00476     const char       * procat;
00477     cpl_propertylist * plist;
00478     cpl_frame        * product_frame;
00479     /* Inside this function the product-types are numbered:
00480        0: imagelist
00481        1: table
00482        2: image
00483        3: propertylist only
00484     */
00485     const unsigned     pronum
00486         = imagelist != NULL ? 0 : table != NULL ? 1 :  (image != NULL ? 2 : 3);
00487     const char       * proname[] = {"imagelist", "table", "image",
00488                                     "propertylist"};
00489     /* FIXME: Define a frame type for an imagelist and when data-less */
00490     const int          protype[] = {CPL_FRAME_TYPE_ANY, CPL_FRAME_TYPE_TABLE,
00491                                     CPL_FRAME_TYPE_IMAGE, CPL_FRAME_TYPE_ANY};
00492     cpl_error_code     error = CPL_ERROR_NONE;
00493 
00494 
00495     /* No more than one of imagelist, table and image may be non-NULL */
00496     /* tablelist may only be non-NULL when table is non-NULL */
00497     if (imagelist != NULL) {
00498         assert(pronum == 0);
00499         assert(image == NULL);
00500         assert(table == NULL);
00501         assert(tablelist == NULL);
00502     } else if (table != NULL) {
00503         assert(pronum == 1);
00504         assert(imagelist == NULL);
00505         assert(image == NULL);
00506     } else if (image != NULL) {
00507         assert(pronum == 2);
00508         assert(imagelist == NULL);
00509         assert(table == NULL);
00510         assert(tablelist == NULL);
00511     } else {
00512         assert(pronum == 3);
00513         assert(imagelist == NULL);
00514         assert(table == NULL);
00515         assert(tablelist == NULL);
00516         assert(image == NULL);
00517     }
00518 
00519     cpl_ensure_code(allframes  != NULL, CPL_ERROR_NULL_INPUT);
00520     cpl_ensure_code(parlist    != NULL, CPL_ERROR_NULL_INPUT);
00521     cpl_ensure_code(usedframes != NULL, CPL_ERROR_NULL_INPUT);
00522     cpl_ensure_code(recipe     != NULL, CPL_ERROR_NULL_INPUT);
00523     cpl_ensure_code(applist    != NULL, CPL_ERROR_NULL_INPUT);
00524     cpl_ensure_code(pipe_id    != NULL, CPL_ERROR_NULL_INPUT);
00525     cpl_ensure_code(filename   != NULL, CPL_ERROR_NULL_INPUT);
00526 
00527     procat = cpl_propertylist_get_string(applist, CPL_DFS_PRO_CATG);
00528 
00529     cpl_ensure_code(procat     != NULL, cpl_error_get_code());
00530 
00531     cpl_msg_info(cpl_func, "Writing FITS %s product(%s): %s", proname[pronum],
00532                  procat, filename);
00533 
00534     product_frame = cpl_frame_new();
00535 
00536     /* Create product frame */
00537     error |= cpl_frame_set_filename(product_frame, filename);
00538     error |= cpl_frame_set_tag(product_frame, procat);
00539     error |= cpl_frame_set_type(product_frame, protype[pronum]);
00540     error |= cpl_frame_set_group(product_frame, CPL_FRAME_GROUP_PRODUCT);
00541     error |= cpl_frame_set_level(product_frame, CPL_FRAME_LEVEL_FINAL);
00542 
00543     if (error) {
00544         cpl_frame_delete(product_frame);
00545         return cpl_error_set_where(cpl_func);
00546     }
00547 
00548     if (header != NULL) {
00549         cpl_propertylist_empty(header);
00550         plist = header;
00551     } else {
00552         plist = cpl_propertylist_new();
00553     }
00554 
00555     /* Add any QC parameters here */
00556     if (applist != NULL) error = cpl_propertylist_copy_property_regexp(plist,
00557                                                                        applist,
00558                                                                        ".", 0);
00559 
00560     /* Add DataFlow keywords */
00561     if (!error)
00562         error = cpl_dfs_setup_product_header(plist, product_frame, usedframes,
00563                                              parlist, recipe, pipe_id,
00564                                              "PRO-1.15", inherit);
00565 
00566     if (remregexp != NULL && !error) {
00567         cpl_errorstate prestate = cpl_errorstate_get();
00568         (void)cpl_propertylist_erase_regexp(plist, remregexp, 0);
00569         if (!cpl_errorstate_is_equal(prestate)) error = cpl_error_get_code();
00570     }
00571 
00572     if (!error) {
00573         switch (pronum) {
00574             case 0:
00575                 error = cpl_imagelist_save(imagelist, filename, type, plist,
00576                                            CPL_IO_CREATE);
00577                 break;
00578             case 1:
00579                 error = cpl_table_save(table, plist, tablelist, filename,
00580                                        CPL_IO_CREATE);
00581                 break;
00582             case 2:
00583                 error = cpl_image_save(image, filename, type, plist,
00584                                        CPL_IO_CREATE);
00585                 break;
00586             default:
00587                 /* case 3: */
00588                 error = cpl_propertylist_save(plist, filename, CPL_IO_CREATE);
00589         }
00590     }
00591 
00592     if (!error) {
00593         /* Insert the frame of the saved file in the input frameset */
00594         error = cpl_frameset_insert(allframes, product_frame);
00595 
00596     } else {
00597         cpl_frame_delete(product_frame);
00598     }
00599 
00600     if (plist != header) cpl_propertylist_delete(plist);
00601 
00602     cpl_ensure_code(!error, error);
00603 
00604     return CPL_ERROR_NONE;
00605 
00606 }    
00607 
00608 
00609 /*----------------------------------------------------------------------------*/
00664 /*----------------------------------------------------------------------------*/
00665 cpl_error_code irplib_image_split(const cpl_image * self,
00666                                   cpl_image * im_low,
00667                                   cpl_image * im_mid,
00668                                   cpl_image * im_high,
00669                                   double th_low,
00670                                   cpl_boolean isleq_low,
00671                                   double th_high,
00672                                   cpl_boolean isgeq_high,
00673                                   double alt_low,
00674                                   double alt_high,
00675                                   cpl_boolean isbad_low,
00676                                   cpl_boolean isbad_mid,
00677                                   cpl_boolean isbad_high)
00678 {
00679 
00680     const void       * selfdata = cpl_image_get_data_const(self);
00681     /* hasbpm reduces check-overhead if self does not have a bpm, and if
00682        self is also passed as an output image, that ends up with bad pixels */
00683     /* FIXME: Need a proper way to know if a bpm has been allocated :-((((((( */
00684     const cpl_boolean  hasbpm
00685         = cpl_image_count_rejected(self) ? CPL_TRUE : CPL_FALSE;
00686     const cpl_binary * selfbpm = hasbpm
00687         ? cpl_mask_get_data_const(cpl_image_get_bpm_const(self)) : NULL;
00688     const cpl_type     selftype = cpl_image_get_type(self);
00689     const int          nx = cpl_image_get_size_x(self);
00690     const int          ny = cpl_image_get_size_y(self);
00691     const int          npix = nx * ny;
00692     const cpl_boolean  do_low   = im_low  != NULL;
00693     const cpl_boolean  do_mid   = im_mid  != NULL;
00694     const cpl_boolean  do_high  = im_high != NULL;
00695     void             * lowdata  = NULL;
00696     void             * middata  = NULL;
00697     void             * highdata = NULL;
00698     cpl_binary       * lowbpm   = NULL;
00699     cpl_binary       * midbpm   = NULL;
00700     cpl_binary       * highbpm  = NULL;
00701     const cpl_type     lowtype
00702         = do_low ? cpl_image_get_type(im_low) : CPL_TYPE_INVALID;
00703     const cpl_type     midtype
00704         = do_mid ? cpl_image_get_type(im_mid) : CPL_TYPE_INVALID;
00705     const cpl_type     hightype
00706         = do_high ? cpl_image_get_type(im_high) : CPL_TYPE_INVALID;
00707     int i;
00708 
00709 
00710     cpl_ensure_code(self != NULL,                CPL_ERROR_NULL_INPUT);
00711     cpl_ensure_code(do_low || do_mid || do_high, CPL_ERROR_NULL_INPUT);
00712     cpl_ensure_code(th_low <= th_high,           CPL_ERROR_ILLEGAL_INPUT);
00713 
00714     if (do_low) {
00715         cpl_ensure_code(cpl_image_get_size_x(im_low) == nx,
00716                         CPL_ERROR_INCOMPATIBLE_INPUT);
00717         cpl_ensure_code(cpl_image_get_size_y(im_low) == ny,
00718                         CPL_ERROR_INCOMPATIBLE_INPUT);
00719         lowdata = cpl_image_get_data(im_low);
00720     }
00721 
00722     if (do_mid) {
00723         cpl_ensure_code(cpl_image_get_size_x(im_mid) == nx,
00724                         CPL_ERROR_INCOMPATIBLE_INPUT);
00725         cpl_ensure_code(cpl_image_get_size_y(im_mid) == ny,
00726                         CPL_ERROR_INCOMPATIBLE_INPUT);
00727         middata = cpl_image_get_data(im_mid);
00728     }
00729 
00730     if (do_high) {
00731         cpl_ensure_code(cpl_image_get_size_x(im_high) == nx,
00732                         CPL_ERROR_INCOMPATIBLE_INPUT);
00733         cpl_ensure_code(cpl_image_get_size_y(im_high) == ny,
00734                         CPL_ERROR_INCOMPATIBLE_INPUT);
00735         highdata = cpl_image_get_data(im_high);
00736     }
00737 
00738     /* From this point a failure would indicate a serious bug in CPL */
00739 
00740     for (i = 0; i < npix; i++) {
00741         const double value = irplib_data_get_double(selfdata, selftype, i);
00742         cpl_boolean  isalt_low   = do_low;
00743         cpl_boolean  isalt_mid   = do_mid;
00744         cpl_boolean  isalt_high  = do_high;
00745         cpl_boolean  setbad_low  = do_low;
00746         cpl_boolean  setbad_mid  = do_mid;
00747         cpl_boolean  setbad_high = do_high;
00748         const void * setdata     = NULL;
00749         double       alt_mid     = 0.0; /* Avoid (false) uninit warning */
00750 
00751         if (isleq_low ? value <= th_low : value < th_low) {
00752             if (do_low) {
00753                 isalt_low = CPL_FALSE;
00754                 irplib_data_set_double(lowdata, lowtype, i, value);
00755                 setbad_low = hasbpm && selfbpm[i];
00756                 setdata = lowdata;
00757             }
00758             alt_mid = alt_low;
00759         } else if (isgeq_high ? value >= th_high : value > th_high) {
00760             if (do_high) {
00761                 isalt_high = CPL_FALSE;
00762                 irplib_data_set_double(highdata, hightype, i, value);
00763                 setbad_high = hasbpm && selfbpm[i];
00764                 setdata = highdata;
00765             }
00766             alt_mid = alt_high;
00767         } else if (do_mid) {
00768             isalt_mid = CPL_FALSE;
00769             irplib_data_set_double(middata, midtype, i, value);
00770             setbad_mid = hasbpm && selfbpm[i];
00771             setdata = middata;
00772         }
00773 
00774         if (isalt_low && lowdata != setdata) {
00775             irplib_data_set_double(lowdata, lowtype, i, alt_low);
00776             setbad_low = isbad_low;
00777         }
00778         if (isalt_mid && middata != setdata) {
00779             irplib_data_set_double(middata, midtype, i, alt_mid);
00780             setbad_mid = isbad_mid;
00781         }
00782         if (isalt_high && highdata != setdata) {
00783             irplib_data_set_double(highdata, hightype, i, alt_high);
00784             setbad_high = isbad_high;
00785         }
00786 
00787         if (setbad_low) {
00788             if (lowbpm == NULL) lowbpm
00789                 = cpl_mask_get_data(cpl_image_get_bpm(im_low));
00790             lowbpm[i] = CPL_BINARY_1;
00791         }
00792         if (setbad_mid) {
00793             if (midbpm == NULL) midbpm
00794                 = cpl_mask_get_data(cpl_image_get_bpm(im_mid));
00795             midbpm[i] = CPL_BINARY_1;
00796         }
00797         if (setbad_high) {
00798             if (highbpm == NULL) highbpm
00799                 = cpl_mask_get_data(cpl_image_get_bpm(im_high));
00800             highbpm[i] = CPL_BINARY_1;
00801         }
00802     }
00803 
00804     return CPL_ERROR_NONE;
00805 
00806 }
00807 
00808 
00809 /*----------------------------------------------------------------------------*/
00857 /*----------------------------------------------------------------------------*/
00858 
00859 cpl_error_code
00860 irplib_dfs_table_convert(cpl_table               * self,
00861                          cpl_frameset            * allframes,
00862                          const cpl_frameset      * useframes,
00863                          int                       maxlinelen,
00864                          char                      commentchar,
00865                          const char              * product_name,
00866                          const char              * procatg,
00867                          const cpl_parameterlist * parlist,
00868                          const char              * recipe_name,
00869                          const cpl_propertylist  * mainlist,
00870                          const cpl_propertylist  * extlist,
00871                          const char              * remregexp,
00872                          const char              * instrume,
00873                          const char              * pipe_id,
00874                          cpl_boolean (*table_set_row)
00875                          (cpl_table *, const char *, int,
00876                           const cpl_frame *,
00877                           const cpl_parameterlist *),
00878                          cpl_error_code (*table_check)
00879                          (cpl_table *,
00880                           const cpl_frameset *,
00881                           const cpl_parameterlist *))
00882 {
00883 
00884     const char       * filename;
00885     cpl_propertylist * applist    = NULL;
00886     cpl_errorstate     prestate   = cpl_errorstate_get();
00887     cpl_error_code     error;
00888     char             * fallback_filename = NULL;
00889 
00890     cpl_ensure_code(self         != NULL, CPL_ERROR_NULL_INPUT);
00891     cpl_ensure_code(allframes    != NULL, CPL_ERROR_NULL_INPUT);
00892     cpl_ensure_code(useframes    != NULL, CPL_ERROR_NULL_INPUT);
00893     cpl_ensure_code(procatg      != NULL, CPL_ERROR_NULL_INPUT);
00894     cpl_ensure_code(parlist      != NULL, CPL_ERROR_NULL_INPUT);
00895     cpl_ensure_code(recipe_name  != NULL, CPL_ERROR_NULL_INPUT);
00896     cpl_ensure_code(instrume     != NULL, CPL_ERROR_NULL_INPUT);
00897     cpl_ensure_code(pipe_id      != NULL, CPL_ERROR_NULL_INPUT);
00898 
00899     cpl_ensure_code(!irplib_table_read_from_frameset(self, useframes,
00900                                                      maxlinelen,
00901                                                      commentchar,
00902                                                      parlist,
00903                                                      table_set_row),
00904                     cpl_error_get_code());
00905 
00906     if (table_check != NULL && (table_check(self, useframes, parlist) ||
00907                                 !cpl_errorstate_is_equal(prestate))) {
00908         return cpl_error_set_message(cpl_func, cpl_error_get_code(),
00909                                      "Consistency check of table failed");
00910     }
00911 
00912     fallback_filename = cpl_sprintf("%s" CPL_DFS_FITS, recipe_name);
00913     filename = product_name != NULL ? product_name : fallback_filename;
00914 
00915     applist = mainlist == NULL
00916         ? cpl_propertylist_new() : cpl_propertylist_duplicate(mainlist);
00917 
00918     error = cpl_propertylist_update_string(applist, "INSTRUME", instrume);
00919 
00920     if (!error)
00921         error = irplib_dfs_save_table(allframes, parlist, useframes, self,
00922                                       extlist, recipe_name, procatg, applist,
00923                                       remregexp, pipe_id, filename);
00924 
00925     cpl_propertylist_delete(applist);
00926     cpl_free(fallback_filename);
00927 
00928     /* Propagate the error, if any */
00929     cpl_ensure_code(!error, error);
00930 
00931     return CPL_ERROR_NONE;
00932 
00933 }
00934 
00935 
00936 
00937 /*----------------------------------------------------------------------------*/
00986 /*----------------------------------------------------------------------------*/
00987 
00988 cpl_error_code
00989 irplib_table_read_from_frameset(cpl_table               * self,
00990                                 const cpl_frameset      * useframes,
00991                                 int                       maxlinelen,
00992                                 char                      commentchar,
00993                                 const cpl_parameterlist * parlist,
00994                                 cpl_boolean (*table_set_row)
00995                                 (cpl_table *, const char *, int,
00996                                  const cpl_frame *,
00997                                  const cpl_parameterlist *))
00998 {
00999 
01000     const cpl_frame  * rawframe;
01001     char             * linebuffer = NULL;
01002     FILE             * stream     = NULL;
01003     int                nfiles     = 0;
01004     int                nrow       = cpl_table_get_nrow(self);
01005     int                irow       = 0;
01006     cpl_errorstate     prestate   = cpl_errorstate_get();
01007 
01008     cpl_ensure_code(self         != NULL, CPL_ERROR_NULL_INPUT);
01009     cpl_ensure_code(useframes    != NULL, CPL_ERROR_NULL_INPUT);
01010     cpl_ensure_code(maxlinelen > 0, CPL_ERROR_ILLEGAL_INPUT);
01011     cpl_ensure_code(parlist      != NULL, CPL_ERROR_NULL_INPUT);
01012     cpl_ensure_code(table_set_row != NULL, CPL_ERROR_NULL_INPUT);
01013 
01014     linebuffer = cpl_malloc(maxlinelen);
01015 
01016     for (rawframe = cpl_frameset_get_first_const(useframes);
01017          rawframe != NULL;
01018          rawframe = cpl_frameset_get_next_const(useframes), nfiles++) {
01019 
01020         const char * rawfile = cpl_frame_get_filename(rawframe);
01021         const char * done; /* Indicate when the reading is done */
01022         const int irowpre = irow;
01023         int iirow = 0;
01024         int ierror;
01025 
01026         if (rawfile == NULL) break; /* Should not happen... */
01027 
01028         stream = fopen(rawfile, "r");
01029 
01030         if (stream == NULL) {
01031 #if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
01032             cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO, "Could not "
01033                                   "open %s for reading", rawfile);
01034 #else
01035             cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO, "Could not "
01036                                   "open file for reading");
01037 #endif
01038             break;
01039         }
01040 
01041         for (;(done = fgets(linebuffer, maxlinelen, stream)) != NULL; iirow++) {
01042 
01043             if (linebuffer[0] != commentchar) {
01044                 cpl_boolean didset;
01045 #if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
01046                 const int prerow = irow;
01047 #endif
01048 
01049                 if (irow == nrow) {
01050                     nrow += nrow ? nrow : 1;
01051                     if (cpl_table_set_size(self, nrow)) break;
01052                 }
01053 
01054                 didset = table_set_row(self, linebuffer, irow, rawframe,
01055                                        parlist);
01056                 if (didset) irow++;
01057 
01058                 if (!cpl_errorstate_is_equal(prestate)) {
01059                     if (didset)
01060 #if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
01061                         cpl_error_set_message(cpl_func, cpl_error_get_code(),
01062                                               "Failed to set table row %d "
01063                                               "using line %d from %d. file %s",
01064                                               1+prerow, iirow+1,
01065                                               nfiles+1, rawfile);
01066                     else
01067                         cpl_error_set_message(cpl_func, cpl_error_get_code(),
01068                                               "Failure with line %d from %d. "
01069                                               "file %s", iirow+1,
01070                                               nfiles+1, rawfile);
01071 #else
01072                         cpl_error_set_message(cpl_func, cpl_error_get_code(),
01073                                               "Failed to set table row"
01074                                               "using catalogue line");
01075                     else
01076                         cpl_error_set_message(cpl_func, cpl_error_get_code(),
01077                                               "Failure with catalogue line");
01078 #endif
01079 
01080                     break;
01081                 }
01082             }
01083         }
01084         if (done != NULL) break;
01085 
01086         ierror = fclose(stream);
01087         stream = NULL;
01088         if (ierror) break;
01089 
01090 
01091         if (irow == irowpre)
01092             cpl_msg_warning(cpl_func, "No usable lines in the %d. file: %s",
01093                             1+nfiles, rawfile);
01094     }
01095 
01096     cpl_free(linebuffer);
01097     if (stream != NULL) fclose(stream);
01098 
01099     /* Check for premature end */
01100     cpl_ensure_code(rawframe == NULL, cpl_error_get_code());
01101 
01102     if (irow == 0) {
01103 #if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
01104         return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
01105                                      "No usable lines in the %d input "
01106                                      "frame(s)", nfiles);
01107 #else
01108         return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
01109                                      "No usable lines in the input frame(s)");
01110 #endif
01111     }
01112 
01113     /* Resize the table to the actual number of rows set */
01114     cpl_ensure_code(!cpl_table_set_size(self, irow), cpl_error_get_code());
01115 
01116     return CPL_ERROR_NONE;
01117 }
01118 
01119 
01120 
01121 /*----------------------------------------------------------------------------*/
01133 /*----------------------------------------------------------------------------*/
01134 void irplib_reset(void)
01135 {
01136     return;
01137 }
01138 
01139 /*----------------------------------------------------------------------------*/
01146 /*----------------------------------------------------------------------------*/
01147 int irplib_compare_tags(
01148         cpl_frame   *   frame1,
01149         cpl_frame   *   frame2)
01150 {
01151     const char            *   v1 ;
01152     const char            *   v2 ;
01153 
01154     /* Test entries */
01155     if (frame1==NULL || frame2==NULL) return -1 ;
01156 
01157     /* Get the tags */
01158     if ((v1 = cpl_frame_get_tag(frame1)) == NULL) return -1 ;
01159     if ((v2 = cpl_frame_get_tag(frame2)) == NULL) return -1 ;
01160 
01161     /* Compare the tags */
01162     if (strcmp(v1, v2)) return 0 ;
01163     else return 1 ;
01164 }
01165 
01166 /*----------------------------------------------------------------------------*/
01182 /*----------------------------------------------------------------------------*/
01183 const char * irplib_frameset_find_file(const cpl_frameset * self,
01184                                       const char * tag)
01185 {
01186     const cpl_frame * frame = cpl_frameset_find_const(self, tag);
01187 
01188 
01189     cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
01190 
01191     if (frame == NULL) return NULL;
01192 
01193     if (cpl_frameset_find_const(self, NULL))
01194         cpl_msg_warning(cpl_func,
01195             "Frameset has more than one file with tag: %s",
01196                         tag);
01197 
01198     return cpl_frame_get_filename(frame);
01199 
01200 }
01201 
01202 /*----------------------------------------------------------------------------*/
01212 /*----------------------------------------------------------------------------*/
01213 const
01214 cpl_frame * irplib_frameset_get_first_from_group(const cpl_frameset * self,
01215                                                  cpl_frame_group      group)
01216 {
01217     const cpl_frame * frame;
01218 
01219     cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
01220 
01221     for (frame = cpl_frameset_get_first_const(self); frame != NULL ;
01222          frame = cpl_frameset_get_next_const(self)) {
01223         if (cpl_frame_get_group(frame) == group) break;
01224     }
01225     return frame;
01226 }
01227 
01228 /*----------------------------------------------------------------------------*/
01247 /*----------------------------------------------------------------------------*/
01248 cpl_error_code irplib_apertures_find_max_flux(const cpl_apertures * self,
01249                                               int * ind, int nfind)
01250 {
01251     const int    nsize = cpl_apertures_get_size(self);
01252     int          ifind;
01253 
01254 
01255     cpl_ensure_code(nsize > 0,      cpl_error_get_code());
01256     cpl_ensure_code(ind,          CPL_ERROR_NULL_INPUT);
01257     cpl_ensure_code(nfind > 0,      CPL_ERROR_ILLEGAL_INPUT);
01258     cpl_ensure_code(nfind <= nsize, CPL_ERROR_ILLEGAL_INPUT);
01259 
01260     for (ifind=0; ifind < nfind; ifind++) {
01261         double maxflux = -1;
01262         int maxind = -1;
01263         int i;
01264         for (i=1; i <= nsize; i++) {
01265             int k;
01266 
01267             /* The flux has to be the highest among those not already found */
01268             for (k=0; k < ifind; k++) if (ind[k] == i) break;
01269 
01270             if (k == ifind) {
01271                 /* i has not been inserted into ind */
01272                 const double flux = cpl_apertures_get_flux(self, i);
01273 
01274                 if (maxind < 0 || flux > maxflux) {
01275                     maxind = i;
01276                     maxflux = flux;
01277                 }
01278             }
01279         }
01280         ind[ifind] = maxind;
01281     }
01282 
01283     return CPL_ERROR_NONE;
01284 
01285 }
01286 
01291 /*----------------------------------------------------------------------------*/
01302 /*----------------------------------------------------------------------------*/
01303 inline static
01304 double irplib_data_get_double(const void * self, cpl_type type, int i)
01305 {
01306 
01307     double value;
01308 
01309 
01310     switch (type) {
01311     case CPL_TYPE_FLOAT:
01312         {
01313             const float * pself = (const float*)self;
01314             value = (double)pself[i];
01315             break;
01316         }
01317     case CPL_TYPE_INT:
01318         {
01319             const int * pself = (const int*)self;
01320             value = (double)pself[i];
01321             break;
01322         }
01323     default: /* case CPL_TYPE_DOUBLE */
01324         {
01325             const double * pself = (const double*)self;
01326             value = pself[i];
01327             break;
01328         }
01329     }
01330 
01331     return value;
01332 
01333 }
01334 
01335 
01336 /*----------------------------------------------------------------------------*/
01347 /*----------------------------------------------------------------------------*/
01348 inline static
01349 void irplib_data_set_double(void * self, cpl_type type, int i, double value)
01350 {
01351 
01352     switch (type) {
01353     case CPL_TYPE_FLOAT:
01354         {
01355             float * pself = (float*)self;
01356             pself[i] = (float)value;
01357             break;
01358         }
01359     case CPL_TYPE_INT:
01360         {
01361             int * pself = (int*)self;
01362             pself[i] = (int)value;
01363             break;
01364         }
01365     default: /* case CPL_TYPE_DOUBLE */
01366         {
01367             double * pself = (double*)self;
01368             pself[i] = value;
01369             break;
01370         }
01371     }
01372 }
01373 
01374 
01375 
01376 
01377 
01378 /*----------------------------------------------------------------------------*/
01389 /*----------------------------------------------------------------------------*/
01390 static
01391 void irplib_errorstate_dump_one_level(void (*messenger)(const char *,
01392                                                         const char *, ...),
01393                                       unsigned self, unsigned first,
01394                                       unsigned last)
01395 {
01396 
01397     const cpl_boolean is_reverse = first > last ? CPL_TRUE : CPL_FALSE;
01398     const unsigned    newest     = is_reverse ? first : last;
01399     const unsigned    oldest     = is_reverse ? last : first;
01400     const char      * revmsg     = is_reverse ? " in reverse order" : "";
01401 
01402 
01403     /*
01404     cx_assert( messenger != NULL );
01405     cx_assert( oldest <= self );
01406     cx_assert( newest >= self );
01407     */
01408 
01409     if (newest == 0) {
01410         messenger(cpl_func, "No error(s) to dump");
01411         /* cx_assert( oldest == 0); */
01412     } else {
01413         /*
01414           cx_assert( oldest > 0);
01415           cx_assert( newest >= oldest);
01416         */
01417         if (self == first) {
01418             if (oldest == 1) {
01419                 messenger(cpl_func, "Dumping all %u error(s)%s:", newest,
01420                           revmsg);
01421             } else {
01422                 messenger(cpl_func, "Dumping the %u most recent error(s) "
01423                           "out of a total of %u errors%s:",
01424                           newest - oldest + 1, newest, revmsg);
01425             }
01426             cpl_msg_indent_more();
01427         }
01428 
01429         messenger(cpl_func, "[%u/%u] '%s' (%u) at %s", self, newest,
01430                   cpl_error_get_message(), cpl_error_get_code(),
01431                   cpl_error_get_where());
01432 
01433         if (self == last) cpl_msg_indent_less();
01434     }
01435 }
01436 
01437 cpl_polynomial * irplib_polynomial_fit_1d_create_chiq(
01438         const cpl_vector    *   x_pos,
01439         const cpl_vector    *   values,
01440         int                     degree,
01441         double              *   rechisq
01442         )
01443  {
01444     return irplib_polynomial_fit_1d_create_common(x_pos, values, degree, NULL, rechisq);
01445  }
01446 cpl_polynomial * irplib_polynomial_fit_1d_create(
01447         const cpl_vector    *   x_pos,
01448         const cpl_vector    *   values,
01449         int                     degree,
01450         double              *   mse
01451         )
01452 {
01453 
01454     return irplib_polynomial_fit_1d_create_common(x_pos, values, degree, mse, NULL);
01455 }
01456 static cpl_polynomial * irplib_polynomial_fit_1d_create_common(
01457         const cpl_vector    *   x_pos,
01458         const cpl_vector    *   values,
01459         int                     degree,
01460         double              *   mse,
01461         double              *  rechisq
01462         )
01463 {
01464     cpl_polynomial * fit1d = NULL;
01465     cpl_size loc_degree = (cpl_size)degree ;
01466     int x_size = 0;
01467     fit1d = cpl_polynomial_new(1);
01468     x_size = cpl_vector_get_size(x_pos);    
01469     if(fit1d != NULL && x_size > 1)
01470     {
01471         cpl_matrix     * samppos = NULL;
01472         cpl_vector     * fitresidual = NULL;
01473         cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
01474         samppos = cpl_matrix_wrap(1, x_size,
01475                                   (double*)cpl_vector_get_data_const(x_pos));
01476         cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
01477         fitresidual = cpl_vector_new(x_size);
01478         cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
01479         cpl_polynomial_fit(fit1d, samppos, NULL, values, NULL,
01480                            CPL_FALSE, NULL, &loc_degree);
01481         cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
01482         cpl_vector_fill_polynomial_fit_residual(fitresidual, values, NULL,
01483                                                 fit1d, samppos, rechisq);
01484         cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
01485         if (mse)
01486         {
01487             *mse = cpl_vector_product(fitresidual, fitresidual)
01488                 / cpl_vector_get_size(fitresidual);
01489         }
01490         cpl_matrix_unwrap(samppos);
01491         cpl_vector_delete(fitresidual);
01492     }
01493     return fit1d;
01494 }
01495 
01496 static void quicksort(int* iindex, double* exptime, int left, int right)
01497 {
01498     int i = left;
01499     int j = right;
01500     int pivot = (i + j) / 2;
01501     double index_value = exptime[pivot];
01502     do
01503     {
01504         while(exptime[i] < index_value) i++;
01505         while(exptime[j] > index_value) j--;
01506         if (i <= j)
01507         {
01508             if(i < j)
01509             {
01510                 int tmp = iindex[i];
01511                 double dtmp = exptime[i];
01512                 iindex[i]=iindex[j];
01513                 iindex[j]=tmp;
01514                 exptime[i] = exptime[j];
01515                 exptime[j] = dtmp;
01516             }
01517             i++;
01518             j--;
01519         }
01520     } while (i <= j);
01521 
01522     if (i < right)
01523     {
01524         quicksort(iindex, exptime, i, right);
01525     }
01526     if (left < j)
01527     {
01528         quicksort(iindex, exptime,left, j);
01529     }
01530 }
01531 cpl_error_code irplib_frameset_sort(const cpl_frameset *  self, int* iindex, double* exptime)
01532 {
01533     int sz = 0;
01534     int i = 0;
01535     const cpl_frame* tmp_frame = 0;
01536     cpl_error_code error = CPL_ERROR_NONE;
01537     sz = cpl_frameset_get_size(self);
01538 
01539     /* 1. get an array of frames */
01540     tmp_frame = cpl_frameset_get_first_const(self);
01541     while(tmp_frame)
01542     {
01543         exptime[i] = frame_get_exptime(tmp_frame);
01544         iindex[i] = i;
01545         tmp_frame = cpl_frameset_get_next_const(self);
01546         i++;
01547     }
01548     /* 2.sort */
01549     quicksort(iindex, exptime, 0, sz - 1);
01550 
01551     return error;
01552 }
01553 
01554 static double frame_get_exptime(const cpl_frame * pframe)
01555 {
01556     double dval = 0;
01557     cpl_propertylist * plist =
01558         cpl_propertylist_load_regexp(cpl_frame_get_filename(pframe), 0,
01559                                      "EXPTIME", CPL_FALSE);
01560     if(plist) {
01561         dval = cpl_propertylist_get_double(plist, "EXPTIME");
01562         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01563             cpl_msg_error(cpl_func, "error during reading EXPTIME key from "
01564                           "the frame [%s]", cpl_frame_get_filename(pframe));
01565         }
01566     }
01567     /* Free and return */
01568     cpl_propertylist_delete(plist);
01569     return dval;
01570 }
01571 
01572 
01573 /*----------------------------------------------------------------------------*/
01587 /*----------------------------------------------------------------------------*/
01588 void * irplib_aligned_malloc(size_t alignment, size_t size)
01589 {
01590 #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L
01591     return aligned_alloc(alignment, size);
01592 #elif defined HAVE_POSIX_MEMALIGN && defined HAVE_DECL_POSIX_MEMALIGN
01593     void *ptr;
01594     if (alignment == 1)
01595         return malloc (size);
01596     if (alignment == 2 || (sizeof (void *) == 8 && alignment == 4))
01597         alignment = sizeof (void *);
01598     if (posix_memalign (&ptr, alignment, size) == 0)
01599         return ptr;
01600     else
01601         return NULL;
01602 #else
01603     /* copied from gmm_malloc.h in gcc-4.8 */
01604     void * malloc_ptr;
01605     void * aligned_ptr;
01606 
01607     /* Error if align is not a power of two.  */
01608     if (alignment & (alignment - 1)) {
01609         errno = EINVAL;
01610         return NULL;
01611     }
01612 
01613     if (size == 0)
01614         return NULL;
01615 
01616     /* Assume malloc'd pointer is aligned at least to sizeof (void*).
01617        If necessary, add another sizeof (void*) to store the value
01618        returned by malloc. Effectively this enforces a minimum alignment
01619        of sizeof double. */
01620     if (alignment < 2 * sizeof (void *))
01621         alignment = 2 * sizeof (void *);
01622 
01623     malloc_ptr = malloc (size + alignment);
01624     if (!malloc_ptr)
01625         return NULL;
01626 
01627     /* Align  We have at least sizeof (void *) space below malloc'd ptr. */
01628     aligned_ptr = (void *) (((size_t) malloc_ptr + alignment)
01629                             & ~((size_t) (alignment) - 1));
01630 
01631     /* Store the original pointer just before p.  */
01632     *(((void **) aligned_ptr) - 1) = malloc_ptr;
01633 
01634     return aligned_ptr;
01635 #endif
01636 }
01637 
01638 
01639 /*----------------------------------------------------------------------------*/
01649 /*----------------------------------------------------------------------------*/
01650 void * irplib_aligned_calloc(size_t alignment, size_t nelem, size_t nbytes)
01651 {
01652     void * buffer = irplib_aligned_malloc(alignment, nelem * nbytes);
01653     if (buffer == NULL)
01654         return NULL;
01655     /* cast to aligned pointer helps compilers to emit better (builtin) code */
01656     memset((size_t *)buffer, 0, nelem * nbytes);
01657     return buffer;
01658 }
01659 
01660 
01661 /*----------------------------------------------------------------------------*/
01669 /*----------------------------------------------------------------------------*/
01670 void irplib_aligned_free (void * aligned_ptr)
01671 {
01672 #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L
01673   free(aligned_ptr);
01674 #elif defined HAVE_POSIX_MEMALIGN && defined HAVE_DECL_POSIX_MEMALIGN
01675   free(aligned_ptr);
01676 #else
01677   if (aligned_ptr)
01678       free (*(((void **) aligned_ptr) - 1));
01679 #endif
01680 }
Generated on Mon Feb 17 15:01:44 2014 for NACO Pipeline Reference Manual by  doxygen 1.6.3