/*                                                                              *
 *   This file is part of the ESO UVES Pipeline                                 *
 *   Copyright (C) 2004,2005 European Southern Observatory                      *
 *                                                                              *
 *   This library is free software; you can redistribute it and/or modify       *
 *   it under the terms of the GNU General Public License as published by       *
 *   the Free Software Foundation; either version 2 of the License, or          *
 *   (at your option) any later version.                                        *
 *                                                                              *
 *   This program is distributed in the hope that it will be useful,            *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
 *   GNU General Public License for more details.                               *
 *                                                                              *
 *   You should have received a copy of the GNU General Public License          *
 *   along with this program; if not, write to the Free Software                *
 *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA       *
 *                                                                              */
 
/*
 * $Author: amodigli $
 * $Date: 2010-09-24 09:31:49 $
 * $Revision: 1.14 $
 * $Name: not supported by cvs2svn $
 *
 */

/*-----------------------------------------------------------------------------
                                Includes
 -----------------------------------------------------------------------------*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <uves_utils.h>
#include <uves_dfs.h>
#include <uves_utils_cpl.h>
#include <uves_utils_polynomial.h>
#include <uves_utils_wrappers.h>
#include <uves_error.h>

#include <cpl_test.h>
#include <cpl.h>
#include <string.h>
#include <stdlib.h>

/*-----------------------------------------------------------------------------
                            Defines
 -----------------------------------------------------------------------------*/

/*
 *   The following is duplicated from CPL's unit test
 *   to test the workaround for cpl_table_erase_selected()
 */




#ifdef VERBOSE

#define test_data(r,f,m)    \
printf(m);                  \
fflush(stdout);             \
fflush(stderr);             \
r = f;                      \
if (!r) {                   \
  printf("Failure\n");      \
                  \
  return 1;                 \
}                           \
printf("OK\n")

#else

#define test_data(r,f,m)    \
r = f;                      \
if (!r) {                   \
  printf(m);                \
  printf("Failure\n");      \
                  \
  return 1;                 \
}

#endif


/*
 * Test for functions returning 0 on success.
 *
 * f = function call
 * m = message
 */

#ifdef VERBOSE

#define test(f,m)           \
printf(m);                  \
fflush(stdout);             \
fflush(stderr);             \
if (f) {                    \
  printf("Failure\n");      \
                  \
  return 1;                 \
}                           \
printf("OK\n")

#else

#define test(f,m)           \
if (f) {                    \
  printf(m);                \
  printf("Failure\n");      \
                  \
  return 1;                 \
}

#endif

/*
 * Test for expected failure in functions returning 0 on success.
 *
 * e = expected error code
 * f = function call
 * m = message
 */

#ifdef VERBOSE

#define test_failure(e,f,m)                                         \
printf(m);                                                          \
fflush(stdout);                                                     \
fflush(stderr);                                                     \
if (f != e) {                                                       \
  printf("\n");                                                     \
  printf("     Received error: \"%s\"\n", cpl_error_get_message()); \
  cpl_error_set("cpl_table-test", e);                               \
  printf("     Expected error: \"%s\"\n", cpl_error_get_message()); \
                  \
  return 1;                                                         \
}                                                                   \
cpl_error_reset();                                                  \
printf("OK\n")

#else

#define test_failure(e,f,m)                                         \
if (f != e) {                                                       \
  printf(m);                                                        \
  printf("\n");                                                     \
  printf("     Received error: \"%s\"\n", cpl_error_get_message()); \
  cpl_error_set("cpl_table-test", e);                               \
  printf("     Expected error: \"%s\"\n", cpl_error_get_message()); \
                  \
  return 1;                                                         \
}                                                                   \
cpl_error_reset()

#endif


/*
 * Test for functions returning an expected integer value.
 *
 * e = expected value
 * f = function call
 * m = message
 */

#ifdef VERBOSE

#define test_ivalue(e,f,m)                        \
printf(m);                                        \
fflush(stdout);                                   \
fflush(stderr);                                   \
itest = f;                                        \
if (itest != e) {                                 \
  printf("Received %d, expected %d\n", itest, e); \
                  \
  return 1;                                       \
}                                                 \
printf("OK\n")

#else

#define test_ivalue(e,f,m)                        \
itest = f;                                        \
if (itest != e) {                                 \
  printf(m);                                      \
  printf("Received %d, expected %d\n", itest, e); \
                  \
  return 1;                                       \
}

#endif


/*
 * Test for functions returning an expected pointer value.
 *
 * e = expected value
 * f = function call
 * m = message
 */

#ifdef VERBOSE

#define test_pvalue(e,f,m)                        \
printf(m);                                        \
fflush(stdout);             \
fflush(stderr);             \
ptest = f;                                        \
if (ptest != e) {                                 \
  printf("Received %p, expected %p\n", ptest, e); \
                  \
  return 1;                                       \
}                                                 \
printf("OK\n")

#else

#define test_pvalue(e,f,m)                        \
ptest = f;                                        \
if (ptest != e) {                                 \
  printf(m);                                      \
  printf("Received %p, expected %p\n", ptest, e); \
                  \
  return 1;                                       \
}

#endif

/*
 * Test for functions returning an expected floating point value.
 *
 * e = expected value
 * t = tolerance on expected value
 * f = function call
 * m = message
 */
  
#ifdef VERBOSE

#define test_fvalue(e,t,f,m)                      \
printf(m);                                        \
fflush(stdout);             \
fflush(stderr);             \
ftest = f;                                        \
if (fabs(ftest - (e)) > t) {                        \
  printf("Received %f, expected %f\n", ftest, e); \
                  \
  return 1;                                       \
}                                                 \
printf("OK\n")

#else

#define test_fvalue(e,t,f,m)                      \
ftest = f;                                        \
if (fabs(ftest - (e)) > t) {                        \
  printf(m);                                      \
  printf("Received %f, expected %f\n", ftest, e); \
                  \
  return 1;                                       \
}

#endif

/*
 * Test for functions returning an expected character string.
 *
 * e = expected value
 * f = function call
 * m = message
 */

#ifdef VERBOSE

#define test_svalue(e,f,m)                        \
printf(m);                                        \
fflush(stdout);             \
fflush(stderr);             \
stest = f;                                        \
if (strcmp(e,stest)) {                            \
  printf("Received %s, expected %s\n", stest, e); \
                  \
  return 1;                                       \
}                                                 \
printf("OK\n")

#else

#define test_svalue(e,f,m)                        \
stest = f;                                        \
if (strcmp(e,stest)) {                            \
  printf(m);                                      \
  printf("Received %s, expected %s\n", stest, e); \
                  \
  return 1;                                       \
}

#endif



/*-----------------------------------------------------------------------------
                            Functions prototypes
 -----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
                            Implementation
 -----------------------------------------------------------------------------*/



/*----------------------------------------------------------------------------*/
/**
 * @defgroup uves_utils_test   Utility function unit tests
 */
/*----------------------------------------------------------------------------*/
/**@{*/
#define MAX_SIZE 4096
static void
uves_filter_cosmic_test(void)
{

  //const char* src_dir="/data1/uves/valentina/";
  const char* src_dir="/media/disk/uves/valentina/";
  //const char* src_dir="./";
   const char* input="PA1_D2B_001.fits";
   //const char* input="cleaned.fits";
   char cosmic_name[MAX_SIZE];
   char filter_name[MAX_SIZE];
   char clean_name[MAX_SIZE];
   char mask_name[MAX_SIZE];
   const double sky=150.;
   const double gain=1.84;
   const double ron=4.1;
   const int ns=4;
   int sx=0;
   int sy=0;

   const double rc=2;
   cpl_frame* frm=NULL;
   cpl_image* inp=NULL;
   cpl_image* flt=NULL;
   cpl_image* out=NULL;
   cpl_image* msk=NULL;
   cpl_propertylist* h=NULL;
   sprintf(cosmic_name,"%s%s",src_dir,input);
   sprintf(filter_name,"%s","filter.fits");
   sprintf(clean_name,"%s","cleaned.fits");
   sprintf(mask_name,"%s","mask.fits");
   check_nomsg(frm=cpl_frame_new());
   check_nomsg(cpl_frame_set_filename(frm,cosmic_name));
   check_nomsg(cpl_frame_set_type(frm,CPL_FRAME_TYPE_IMAGE));
   check_nomsg(cpl_frame_set_group(frm,CPL_FRAME_GROUP_RAW));

   check_nomsg(inp=cpl_image_load(cosmic_name,CPL_TYPE_FLOAT,0,0));
   check_nomsg(h=cpl_propertylist_load(cosmic_name,0));
   check_nomsg(sx=cpl_image_get_size_x(inp));
   check_nomsg(sy=cpl_image_get_size_y(inp));

   check_nomsg(msk=cpl_image_new(sx,sy,CPL_TYPE_INT));

   check_nomsg(uves_rcosmic(inp,&flt,&out,&msk,sky,ron,gain,ns,rc));
   check_nomsg(cpl_image_save(flt,filter_name,CPL_BPP_IEEE_FLOAT,
                              h,CPL_IO_DEFAULT));
   check_nomsg(cpl_image_save(msk,mask_name,CPL_BPP_IEEE_FLOAT,
                              h,CPL_IO_DEFAULT));
   check_nomsg(cpl_image_save(out,clean_name,CPL_BPP_IEEE_FLOAT,
                              h,CPL_IO_DEFAULT));


  cleanup:
   uves_free_frame(&frm);
   cpl_propertylist_delete(h);
   uves_free_image(&inp);
   uves_free_image(&out);
   uves_free_image(&flt);
   uves_free_image(&msk);

   return;
}


static void
uves_find_property_test(void)
{
    uves_propertylist *header = uves_propertylist_new();

    uves_propertylist_append_int(header, "INTVAL", 3);
    uves_propertylist_append_double(header, "HELLO", 98.12);
    uves_propertylist_append_int(header, "INTVAL", 3);
    uves_propertylist_append_double(header, "HELLO", 98.12);
    uves_propertylist_append_int(header, "INTVAL", 3);
    
    /* Now CPL sets an error status (not catched by UVES propertylist wrapper)
       on the first 3 extensions as they miss the keyword. 
       We need to comment out those: or FIX uves_propertylist.c
    TO_BE_FIXED
    cpl_test( uves_find_property(header, "INTVAL", 0) != NULL);
    cpl_test( uves_find_property(header, "INTVAL", 1) != NULL);
    cpl_test( uves_find_property(header, "INTVAL", 2) != NULL);
    cpl_test( uves_find_property(header, "INTVAL", 3) == NULL);
    cpl_test( uves_find_property(header, "INTVAL", 4) == NULL);
    */

    uves_free_propertylist(&header);

    return;
}

static void
uves_average_reject_test(void)
{
    cpl_table *table = cpl_table_new(100);
    int i;

    cpl_table_new_column(table, "X", CPL_TYPE_DOUBLE);
    cpl_table_set_double(table, "X", 0, 100);
    cpl_table_set_double(table, "X", 1, 101);
    cpl_table_set_double(table, "X", 2, 2000); /* Outlier here */
    cpl_table_set_double(table, "X", 3,  98);
    cpl_table_set_double(table, "X", 4, 103);
    cpl_table_set_double(table, "X", 5, 102);
    cpl_table_set_double(table, "X", 6, 100);
    cpl_table_set_double(table, "X", 7, 103);
    cpl_table_set_double(table, "X", 8, 100);
    cpl_table_set_double(table, "X", 9, 99);

    srand(0); /* For reproducability */
    for (i = 10; i < 100; i++)
        {
            cpl_table_set_double(table, "X", i, 100 + 3*uves_gaussrand());
            
        }
    {
        double kappa = 4.0;
        double expected_avg = 100;
        double tolerance = 3.0;
        
        cpl_test( 2000 - 100 > kappa * cpl_table_get_column_stdev(table, "X"));

        cpl_test_abs( uves_average_reject(table, "X", "temp", kappa),
                         expected_avg, tolerance);
    }
    cpl_test_eq( cpl_table_get_nrow(table), 99);
    cpl_test_abs( cpl_table_get_double(table, "X", 0, NULL), 100, 0.1);
    cpl_test_abs( cpl_table_get_double(table, "X", 1, NULL), 101, 0.1);
    cpl_test_abs( cpl_table_get_double(table, "X", 2, NULL),  98, 0.1);
    cpl_test_abs( cpl_table_get_double(table, "X", 3, NULL), 103, 0.1);

    uves_free_table(&table);

    return;
}                     

static void
uves_polynomial_fit_2d_test(void)
{
    unsigned size = 4;
    cpl_bivector *xy_pos = cpl_bivector_new(size);
    cpl_vector *values = cpl_vector_new(size);
    cpl_vector *sigmas = NULL;
    int deg1 = 0;
    int deg2 = 0;
    polynomial *solution;

    /* "good" input */
    cpl_bivector_get_x_data(xy_pos)[0] = 1;
    cpl_bivector_get_x_data(xy_pos)[1] = 2;
    cpl_bivector_get_x_data(xy_pos)[2] = 3;
    cpl_bivector_get_x_data(xy_pos)[3] = 4;

    cpl_bivector_get_y_data(xy_pos)[0] = 4;
    cpl_bivector_get_y_data(xy_pos)[1] = 3;
    cpl_bivector_get_y_data(xy_pos)[2] = 2;
    cpl_bivector_get_y_data(xy_pos)[3] = 1;

    cpl_vector_get_data(values)[0] = 17;
    cpl_vector_get_data(values)[1] = 17;
    cpl_vector_get_data(values)[2] = 17;
    cpl_vector_get_data(values)[3] = 17;

    solution = uves_polynomial_fit_2d(xy_pos, values, sigmas,
                                      deg1, deg2,
                                      NULL, NULL, NULL); /* mse, red_chisq, variance */

    cpl_test(solution != NULL);
    cpl_test_abs(uves_polynomial_evaluate_2d(solution, 1, 1), 17, 0.001);


    /* Degenerate input */
    deg1 = 1;
    deg2 = 1;
    cpl_bivector_get_x_data(xy_pos)[0] = 1;
    cpl_bivector_get_x_data(xy_pos)[1] = 1;
    cpl_bivector_get_x_data(xy_pos)[2] = 1;
    cpl_bivector_get_x_data(xy_pos)[3] = 1;

    cpl_bivector_get_y_data(xy_pos)[0] = 1;
    cpl_bivector_get_y_data(xy_pos)[1] = 1;
    cpl_bivector_get_y_data(xy_pos)[2] = 1;
    cpl_bivector_get_y_data(xy_pos)[3] = 1;


    uves_polynomial_delete(&solution);
    solution = uves_polynomial_fit_2d(xy_pos, values, sigmas,
                                      deg1, deg2,
                                      NULL, NULL, NULL); /* mse, red_chisq, variance */

    cpl_test(cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX);
    uves_error_reset();
    cpl_test(solution == NULL);
    


    uves_polynomial_delete(&solution);
    uves_free_bivector(&xy_pos);
    uves_free_vector(&values);

    return;
}



static int table_erase_selected(void)
{

  int         nrows = 10;
  int         i, j, k, null, error;
  int         pp;
  int         itest;
  double      ftest;
  const char *stest;
  void       *ptest;
  char        message[80];

  int        *iArray;
  float      *fArray;
  double     *dArray;
  double     *ddArray;
  char      **sArray;

  int        icheck[25];
  float      fcheck[25];
  double     dcheck[25];
  const char      *scheck[25];

  const char      *unit;
  const char      *names[2];
  int        reverse[2];

  cpl_table  *table;
  cpl_table  *copia;
  cpl_array  *array;

  uves_propertylist  *reflist;

/*
  uves_propertylist  *list1;
  uves_propertylist  *list2;
*/

  iArray = cpl_malloc(nrows * sizeof(int));
  fArray = cpl_malloc(nrows * sizeof(float));
  dArray = cpl_malloc(nrows * sizeof(double));
  ddArray = cpl_malloc(nrows * sizeof(double));
  sArray = cpl_malloc(nrows * sizeof(char *));

  iArray[0] = 5;
  iArray[1] = 0;
  iArray[2] = 2;
  iArray[3] = 8;
  iArray[4] = 9;
  iArray[5] = 3;
  iArray[6] = 7;
  iArray[7] = 1;
  iArray[8] = 4;
  iArray[9] = 6;

  fArray[0] = 5.1;
  fArray[1] = 0.1;
  fArray[2] = 2.1;
  fArray[3] = 8.1;
  fArray[4] = 9.1;
  fArray[5] = 3.1;
  fArray[6] = 7.1;
  fArray[7] = 1.1;
  fArray[8] = 4.1;
  fArray[9] = 6.1;

  ddArray[0] = dArray[0] = 5.11;
  ddArray[1] = dArray[1] = 0.11;
  ddArray[2] = dArray[2] = 2.11;
  ddArray[3] = dArray[3] = 8.11;
  ddArray[4] = dArray[4] = 9.11;
  ddArray[5] = dArray[5] = 3.11;
  ddArray[6] = dArray[6] = 7.11;
  ddArray[7] = dArray[7] = 1.11;
  ddArray[8] = dArray[8] = 4.11;
  ddArray[9] = dArray[9] = 6.11;

  sArray[0] = cpl_strdup("caaa");
  sArray[1] = cpl_strdup("abcd");
  sArray[2] = cpl_strdup("aaaa");
  sArray[3] = cpl_strdup("daaa");
  sArray[4] = cpl_strdup("acde");
  sArray[5] = cpl_strdup("baaa");
  sArray[6] = cpl_strdup("aaaa");
  sArray[7] = cpl_strdup("acde");
  sArray[8] = cpl_strdup(" sss");
  sArray[9] = cpl_strdup("daaa");


  /*
   *  Testing begins here
   */

  /*
   *  Testing tables with zero rows.
   */

  test_data(table, cpl_table_new(0), "Creating a table without rows... ");

  test(cpl_table_new_column(table, "Int", CPL_TYPE_INT), 
                            "Creating empty Integer column... ");
  test(cpl_table_new_column(table, "Float", CPL_TYPE_FLOAT), 
                            "Creating empty Float column... ");
  test(cpl_table_new_column(table, "Double", CPL_TYPE_DOUBLE), 
                            "Creating empty Double column... ");
  test(cpl_table_new_column(table, "String", CPL_TYPE_STRING), 
                            "Creating empty String column... ");
  test(cpl_table_new_column_array(table, "AInt", 
                                  CPL_TYPE_INT | CPL_TYPE_POINTER, 0),
                                  "Creating empty IntegerArray column... ");
  test(cpl_table_new_column_array(table, "AFloat", 
                                  CPL_TYPE_FLOAT | CPL_TYPE_POINTER, 0),
                                  "Creating empty FloatArray column... ");
  test(cpl_table_new_column_array(table, "ADouble", 
                                  CPL_TYPE_DOUBLE | CPL_TYPE_POINTER, 0),
                                  "Creating empty DoubleArray column... ");

  test_ivalue(0, cpl_table_get_nrow(table), "Check zero table length... ");
  test_ivalue(7, cpl_table_get_ncol(table), "Check zero table width... ");

  test_ivalue(0, cpl_table_get_column_depth(table, "Double"), 
              "Check \"Double\" depth... ");

  test_ivalue(0, cpl_table_get_column_depth(table, "AInt"), 
              "Check \"AInt\" depth... ");

  test(cpl_table_set_size(table, 1), "Expanding table to one row... ");

  test_ivalue(1, cpl_table_get_nrow(table), "Check table with one row... ");

  test(cpl_table_set_size(table, 0), "Deleting all rows from table... ");

  test_ivalue(0, cpl_table_get_nrow(table), 
              "Check again zero table length... ");

  test(cpl_table_erase_column(table, "Double"),
                              "Delete zero-column \"Double\"... ");

  test_ivalue(6, cpl_table_get_ncol(table), "Check zero-column removal... ");

  test(cpl_table_erase_column(table, "AInt"),
                              "Delete zero-column \"AInt\"... ");

  test_ivalue(5, cpl_table_get_ncol(table), 
              "Check zero-column array removal... ");

  test_pvalue(NULL, cpl_table_get_data_float(table, "Float"),
                            "Check NULL pointer to column Float... ");

  test_failure(CPL_ERROR_NULL_INPUT, 
               cpl_table_erase_selected(NULL),
               "Erase selected on NULL table... ");

  test(cpl_table_erase_selected(table),
       "Erase selected on empty table... ");

  test_failure(CPL_ERROR_NULL_INPUT, 
               cpl_table_set_column_unit(NULL, "Float", "arcsec"),
               "Try to assign unit to NULL table... ");

  test_failure(CPL_ERROR_NULL_INPUT, 
               cpl_table_set_column_unit(table, NULL, "arcsec"),
               "Try to assign unit to NULL column... ");

  test_failure(CPL_ERROR_DATA_NOT_FOUND, 
               cpl_table_set_column_unit(table, "Double", "arcsec"),
               "Try to assign unit to non existing column... ");

  test(cpl_table_set_column_unit(table, "Float", "arcsec"),
               "Assign unit 'arcsec' to column Float... ");

  if (strcmp(unit = (char *)cpl_table_get_column_unit(table, "Float"), 
      "arcsec")) {
    printf("Check column unit... ");
    printf("Expected \"arcsec\", obtained \"%s\"\n", unit);
    
    return 1;
  }

  test(cpl_table_set_column_unit(table, "Float", NULL),
               "Assign unit NULL to column Float... ");

  test_pvalue(NULL, (char *)cpl_table_get_column_unit(table, "Float"),
              "Get unit NULL from column Float... ");

  test(cpl_table_set_size(table, 1), "Expanding again table to one row... ");

  test(cpl_table_erase_invalid_rows(table), "Pruning table to zero... ");

  test_ivalue(1, cpl_table_get_nrow(table),
                       "Checking zero-table length after pruning... ");

  test_ivalue(0, cpl_table_get_ncol(table),
                       "Checking zero-table width after pruning... ");

  cpl_table_delete(table);

/* %%% */

  /*
   *  Testing tables with more rows
   */

  test_data(table, cpl_table_new(nrows), "Creating the test table... ");

  test(cpl_table_wrap_int(table, iArray, "Integer"), 
                                         "Wrapping the Integer column... ");

//  test_pvalue(iArray, cpl_table_unwrap(table, "Integer"),
//                                         "Unwrap the Integer column data... ");
  cpl_table_unwrap(table, "Integer");

  test(cpl_table_wrap_int(table, iArray, "Integer"), 
                                         "Creating the Integer column... ");

  test(cpl_table_wrap_double(table, dArray, "Double"), 
                                         "Creating the Double column... ");

  test(cpl_table_wrap_double(table, ddArray, "DoubleDouble"), 
                                  "Creating the DoubleDouble column... ");

  test(cpl_table_wrap_string(table, sArray, "String"),
                                         "Creating the String column... ");

  test(cpl_table_new_column(table, "Float", CPL_TYPE_FLOAT),
                                         "Creating the Float column... ");

  for (i = 0; i < nrows; i++) {
    sprintf(message, "Writing to row %d of the Float column... ", i);
    test(cpl_table_set_float(table, "Float", i, fArray[i]), message);
  }

  test(cpl_table_new_column_array(table, "AInt", 
                                  CPL_TYPE_INT | CPL_TYPE_POINTER, 2),
                                  "Creating the ArrayInt column... ");

  test(cpl_table_new_column_array(table, "AFloat", CPL_TYPE_FLOAT, 2),
                                  "Creating the ArrayFloat column... ");

  test(cpl_table_new_column_array(table, "ADouble", 
                                  CPL_TYPE_DOUBLE | CPL_TYPE_POINTER, 2),
                                  "Creating the ArrayDouble column... ");

  test_ivalue(2, cpl_table_get_column_depth(table, "AInt"), 
              "Check \"AInt\" depth (2)... ");

  k = 0;
  array = cpl_array_new(2, CPL_TYPE_INT);
  for (i = 0; i < nrows; i++) {
    for (j = 0; j < 2; j++) {
      sprintf(message, 
              "Writing element %d of array %d of the AInt column... ", j, i);
      k++;
      test(cpl_array_set_int(array, j, k), message);
    }
    sprintf(message, "Setting array at position %d of the AInt column... ", i);
    test(cpl_table_set_array(table, "AInt", i, array), message);
  }
  cpl_array_delete(array);

  k = 0;
  for (i = 0; i < nrows; i++) {
    sprintf(message, "Getting array %d of the AInt column... ", i);
    test_data(array, (cpl_array *)cpl_table_get_array(table, "AInt", i), 
              message);
    for (j = 0; j < 2; j++) {
      sprintf(message,
              "Reading element %d of array %d of the AInt column... ", j, i);
      k++;
      test_ivalue(k, cpl_array_get_int(array, j, NULL), message);
    }
  }

  k = 0;
  array = cpl_array_new(2, CPL_TYPE_FLOAT);
  for (i = 0; i < nrows; i++) {
    for (j = 0; j < 2; j++) {
      sprintf(message, 
              "Writing element %d of array %d of the AFloat column... ", j, i);
      k++;
      test(cpl_array_set_float(array, j, k), message);
    }
    sprintf(message, 
            "Setting array at position %d of the AFloat column... ", i);
    test(cpl_table_set_array(table, "AFloat", i, array), message);
  }
  cpl_array_delete(array);
  
  k = 0;
  for (i = 0; i < nrows; i++) {
    sprintf(message, "Getting array %d of the AFloat column... ", i);
    test_data(array, (cpl_array *)cpl_table_get_array(table, "AFloat", i),  
              message);
    for (j = 0; j < 2; j++) {
      sprintf(message,
              "Reading element %d of array %d of the AFloat column... ", j, i);
      k++;
      test_fvalue((float)k, 0.0001, 
            cpl_array_get_float(array, j, NULL), message);
    }
  }

  k = 0;
  array = cpl_array_new(2, CPL_TYPE_DOUBLE);
  for (i = 0; i < nrows; i++) {
    for (j = 0; j < 2; j++) {
      sprintf(message, 
              "Writing element %d of array %d of the ADouble column... ", j, i);
      k++;
      test(cpl_array_set_double(array, j, k), message);
    }
    sprintf(message, 
            "Setting array at position %d of the ADouble column... ", i);
    test(cpl_table_set_array(table, "ADouble", i, array), message);
  }
  cpl_array_delete(array);
  
  k = 0;
  for (i = 0; i < nrows; i++) {
    sprintf(message, "Getting array %d of the ADouble column... ", i);
    test_data(array, (cpl_array *)cpl_table_get_array(table, "ADouble", i),
              message);
    for (j = 0; j < 2; j++) {
      sprintf(message,
              "Reading element %d of array %d of the ADouble column... ", j, i);
      k++;
      test_fvalue((float)k, 0.0001, 
            cpl_array_get_double(array, j, NULL), message);
    }
  }

  test_ivalue(2, cpl_table_get_column_depth(table, "AInt"), 
              "Check \"AInt\" depth (3)... ");

  test_data(array, (cpl_array *)cpl_table_get_array(table, "AInt", 0), 
            "Get AInt array");
  test_ivalue(CPL_TYPE_INT, cpl_array_get_type(array),
              "Array AInt must be int... ");

/**** %%%
  list1 = uves_propertylist_new();
  uves_propertylist_append_bool(list1, "hierarch eso ins bool", 0);
  uves_propertylist_append_bool(list1, "hierarch eso ins bool", 0);
  uves_propertylist_set_comment(list1, "hierarch eso ins bool", "This is a comment");
  uves_propertylist_append_int(list1, "NAXIS", 111);
  uves_propertylist_set_comment(list1, "NAXIS", "This is a comment");
  uves_propertylist_append_long(list1, "long", 111111111);
  uves_propertylist_set_comment(list1, "long", "This is a comment");
  uves_propertylist_append_float(list1, "float", 4.4);
  uves_propertylist_set_comment(list1, "float", "This is a comment");
  uves_propertylist_append_double(list1, "double", 8.8);
  uves_propertylist_set_comment(list1, "double", "This is a comment");
  uves_propertylist_append_char(list1, "char", 'D');
  uves_propertylist_set_comment(list1, "char", "This is a comment");
  list2 = uves_propertylist_new();
  uves_propertylist_append_string(list2, "hierarch eso det string", "This is a test");
  uves_propertylist_set_comment(list2, "hierarch eso det string", "This is a comment");
  uves_propertylist_append_int(list2, "TFIELDS", 3000);
  uves_propertylist_set_comment(list2, "TFIELDS", "This is a comment");
  uves_propertylist_append_string(list2, "TUNIT2", "This is a test");
  uves_propertylist_set_comment(list2, "TUNIT2", "This is a comment");
  uves_propertylist_append_string(list2, "TFORM1", "This is a test");
  uves_propertylist_set_comment(list2, "TFORM1", "This is a comment");
  uves_propertylist_append_string(list2, "TTYPE3", "This is a test");
  uves_propertylist_set_comment(list2, "TTYPE3", "This is a comment");
  uves_propertylist_append_bool(list2, "hierarch eso ins bool", 0);
  uves_propertylist_set_comment(list2, "hierarch eso ins bool", "This is a comment");
  uves_propertylist_append_int(list2, "hierarch eso det int", 111);
  uves_propertylist_set_comment(list2, "hierarch eso det int", "This is a comment");
  uves_propertylist_append_long(list2, "long", 111111111);
  uves_propertylist_set_comment(list2, "long", "This is a comment");
  uves_propertylist_append_float(list2, "float", 4.4);
  uves_propertylist_set_comment(list2, "float", "This is a comment");
  uves_propertylist_append_double(list2, "double", 8.8);
  uves_propertylist_set_comment(list2, "double", "This is a comment");
  uves_propertylist_append_char(list2, "char", 'D');
  uves_propertylist_set_comment(list2, "char", "This is a comment");
****/

/**-
  cpl_table_save(table, list1, list2, "test_table.tfits", 0);
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
-**/

/****
  uves_propertylist_delete(list1);
  uves_propertylist_delete(list2);
****/

  test_ivalue(10, cpl_table_get_nrow(table), "Check table length (1)... ");
  test_ivalue(8, cpl_table_get_ncol(table), "Check table width... ");

  test_failure(CPL_ERROR_DATA_NOT_FOUND, 
               cpl_table_erase_column(table, "Diable"), 
               "Trying to delete a not existing column... ");

  test(cpl_table_erase_column(table, "DoubleDouble"), 
                                "Delete column \"DoubleDouble\"... ");

  test_ivalue(7, cpl_table_get_ncol(table), "Check again table width... ");

  test_ivalue(CPL_TYPE_INT, cpl_table_get_column_type(table, "Integer"),
                                "Column Integer must be int... ");
  test_ivalue(CPL_TYPE_DOUBLE, cpl_table_get_column_type(table, "Double"),
                                "Column Double must be double... ");
  test_ivalue(CPL_TYPE_STRING, cpl_table_get_column_type(table, "String"),
                                "Column String must be char*... ");
  test_ivalue(CPL_TYPE_FLOAT, cpl_table_get_column_type(table, "Float"),
                                "Column Float must be float... ");
  test_ivalue((CPL_TYPE_INT | CPL_TYPE_POINTER), 
              cpl_table_get_column_type(table, "AInt"),
              "Column AInt must be arrays of int... ");
  test_ivalue((CPL_TYPE_DOUBLE | CPL_TYPE_POINTER), 
              cpl_table_get_column_type(table, "ADouble"),
              "Column Double must be arrays of double... ");
  test_ivalue((CPL_TYPE_FLOAT | CPL_TYPE_POINTER), 
              cpl_table_get_column_type(table, "AFloat"),
              "Column Float must be arrays of float... ");

//  test_pvalue(iArray, cpl_table_get_data_int(table, "Integer"),
//                                "Check pointer to column Integer data... ");
//  test_pvalue(dArray, cpl_table_get_data_double(table, "Double"),
//                                "Check pointer to column Double data... ");
//  test_pvalue(sArray, cpl_table_get_data_string(table, "String"),
//                                "Check pointer to column String data... ");


  copia = cpl_table_new(5);

  test(cpl_table_copy_structure(copia, table),
       "Creating a new cpl_table modeled on an existing cpl_table... ");

  test_ivalue(5, cpl_table_get_nrow(copia), "Check table length (2)... ");
  test_ivalue(7, cpl_table_get_ncol(copia), "Check table width... ");

  test(cpl_table_compare_structure(table, copia), 
                                 "Tables must have the same structure... ");
  cpl_table_erase_column(copia, "Double");
  test_ivalue(1, cpl_table_compare_structure(table, copia), 
    "Deleting column Double - now tables must have different structure... ");
  test(cpl_table_new_column(copia, "Double", CPL_TYPE_DOUBLE),
                                 "Creating again the Double column... ");
  test(cpl_table_compare_structure(table, copia), 
                         "Tables must have the same structure again... ");

  test(cpl_table_fill_column_window_int(copia, "Integer", 0, 5, -1),
                                 "Fill column Integer of new table... ");
  test(cpl_table_fill_column_window_double(copia, "Double", 0, 5, -1.11),
                                 "Fill column Double of new table... ");
  test(cpl_table_fill_column_window_float(copia, "Float", 0, 5, -1.1),
                                 "Fill column Float of new table... ");
  test(cpl_table_fill_column_window_string(copia, "String", 0, 5, "extra"),
                                 "Fill column String of new table... ");

  array = cpl_array_new(2, CPL_TYPE_INT);
  for (j = 0; j < 2; j++)
    cpl_array_set_int(array, j, j);
  test(cpl_table_fill_column_window_array(copia, "AInt", 0, 5, array),
                                 "Fill column AInt of new table... ");
  cpl_array_delete(array);

  array = cpl_array_new(2, CPL_TYPE_FLOAT);
  for (j = 0; j < 2; j++) 
    cpl_array_set_float(array, j, j);
  test(cpl_table_fill_column_window_array(copia, "AFloat", 0, 5, array),
                                 "Fill column AFloat of new table... ");
  cpl_array_delete(array);

  array = cpl_array_new(2, CPL_TYPE_DOUBLE);
  for (j = 0; j < 2; j++) 
    cpl_array_set_double(array, j, j);
  test(cpl_table_fill_column_window_array(copia, "ADouble", 0, 5, array),
                                 "Fill column ADouble of new table... ");
  cpl_array_delete(array);

  test(cpl_table_insert(table, copia, 15), 
                                 "Appending new table to old table... ");
  test(cpl_table_insert(table, copia, 5), 
                                 "Inserting new table in old table... ");
  test(cpl_table_insert(table, copia, 0), 
                                 "Prepending new table to old table... ");

  cpl_table_delete(copia);

/**+ FIXME: RESTORE!!! */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/
  
  test_ivalue(25, cpl_table_get_nrow(table), "Check table length (3)... ");

  icheck[0] = -1;
  icheck[1] = -1;
  icheck[2] = -1;
  icheck[3] = -1;
  icheck[4] = -1;
  icheck[5] = 5;
  icheck[6] = 0;
  icheck[7] = 2;
  icheck[8] = 8;
  icheck[9] = 9;
  icheck[10] = -1;
  icheck[11] = -1;
  icheck[12] = -1;
  icheck[13] = -1;
  icheck[14] = -1;
  icheck[15] = 3;
  icheck[16] = 7;
  icheck[17] = 1;
  icheck[18] = 4;
  icheck[19] = 6;
  icheck[20] = -1;
  icheck[21] = -1;
  icheck[22] = -1;
  icheck[23] = -1;
  icheck[24] = -1;

  error = 0;

  for (i = 0; i < 25; i++) {
    if (cpl_table_get_int(table, "Integer", i, NULL) != icheck[i]) {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check Integer column... ");
    printf("Failure\n");
    
    return 1;
  }

  dcheck[0] = -1.1100;
  dcheck[1] = -1.1100;
  dcheck[2] = -1.1100;
  dcheck[3] = -1.1100;
  dcheck[4] = -1.1100;
  dcheck[5] = 5.1100;
  dcheck[6] = 0.1100;
  dcheck[7] = 2.1100;
  dcheck[8] = 8.1100;
  dcheck[9] = 9.1100;
  dcheck[10] = -1.1100;
  dcheck[11] = -1.1100;
  dcheck[12] = -1.1100;
  dcheck[13] = -1.1100;
  dcheck[14] = -1.1100;
  dcheck[15] = 3.1100;
  dcheck[16] = 7.1100;
  dcheck[17] = 1.1100;
  dcheck[18] = 4.1100;
  dcheck[19] = 6.1100;
  dcheck[20] = -1.1100;
  dcheck[21] = -1.1100;
  dcheck[22] = -1.1100;
  dcheck[23] = -1.1100;
  dcheck[24] = -1.1100;

  error = 0;

  for (i = 0; i < 25; i++) {
    if (fabs(cpl_table_get_double(table, "Double", i, NULL) - dcheck[i]) 
                                                                  > 0.00001) {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check Double column... ");
    printf("Failure\n");
    
    return 1;
  }

  scheck[0] = "extra";
  scheck[1] = "extra";
  scheck[2] = "extra";
  scheck[3] = "extra";
  scheck[4] = "extra";
  scheck[5] = "caaa";
  scheck[6] = "abcd";
  scheck[7] = "aaaa";
  scheck[8] = "daaa";
  scheck[9] = "acde";
  scheck[10] = "extra";
  scheck[11] = "extra";
  scheck[12] = "extra";
  scheck[13] = "extra";
  scheck[14] = "extra";
  scheck[15] = "baaa";
  scheck[16] = "aaaa";
  scheck[17] = "acde";
  scheck[18] = " sss";
  scheck[19] = "daaa";
  scheck[20] = "extra";
  scheck[21] = "extra";
  scheck[22] = "extra";
  scheck[23] = "extra";
  scheck[24] = "extra";

  error = 0;

  for (i = 0; i < 25; i++) {
    if (strcmp(cpl_table_get_string(table, "String", i), scheck[i])) {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check String column... ");
    printf("Failure\n");
    
    return 1;
  }

  fcheck[0] = -1.10;
  fcheck[1] = -1.10;
  fcheck[2] = -1.10;
  fcheck[3] = -1.10;
  fcheck[4] = -1.10;
  fcheck[5] = 5.10;
  fcheck[6] = 0.10;
  fcheck[7] = 2.10;
  fcheck[8] = 8.10;
  fcheck[9] = 9.10;
  fcheck[10] = -1.10;
  fcheck[11] = -1.10;
  fcheck[12] = -1.10;
  fcheck[13] = -1.10;
  fcheck[14] = -1.10;
  fcheck[15] = 3.10;
  fcheck[16] = 7.10;
  fcheck[17] = 1.10;
  fcheck[18] = 4.10;
  fcheck[19] = 6.10;
  fcheck[20] = -1.10;
  fcheck[21] = -1.10;
  fcheck[22] = -1.10;
  fcheck[23] = -1.10;
  fcheck[24] = -1.10;

  error = 0;

  for (i = 0; i < 25; i++) {
    if (fabs(cpl_table_get_float(table, "Float", i, NULL) - fcheck[i])
                                                                  > 0.00001) {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check Float column... ");
    printf("Failure\n");
    
    return 1;
  }

  test(cpl_table_set_invalid(table, "Integer", 0), 
                             "Set Integer 0 to NULL... ");
  test(cpl_table_set_invalid(table, "Integer", 5), 
                             "Set Integer 5 to NULL... ");
  test(cpl_table_set_invalid(table, "Integer", 24), 
                             "Set Integer 24 to NULL... ");

  test(cpl_table_set_invalid(table, "AInt", 0),
                             "Set AInt 0 to NULL... ");
  test(cpl_table_set_invalid(table, "AFloat", 5),
                             "Set AFloat 5 to NULL... ");
  test(cpl_table_set_invalid(table, "ADouble", 24),
                             "Set ADouble 24 to NULL... ");

/**+ FIXME: RESTORE!!! */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(3, cpl_table_count_invalid(table, "Integer"), 
              "Count Integer written NULLs... ");
  test_ivalue(1, cpl_table_count_invalid(table, "AInt"),
              "Count AInt written NULLs... ");
  test_ivalue(1, cpl_table_count_invalid(table, "AFloat"),
              "Count AFloat written NULLs... ");
  test_ivalue(1, cpl_table_count_invalid(table, "ADouble"),
              "Count ADouble written NULLs... ");

  error = 0;

  for (i = 0; i < 25; i++) {
    cpl_table_get_int(table, "Integer", i, &null);
    if (!null) {
      if (cpl_table_get_int(table, "Integer", i, &null) != icheck[i]) {
        error = 1;
        break;
      }
    }
    else if (i != 0 && i != 5 && i != 24) {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check Integer column... ");
    printf("Failure\n");
    
    return 1;
  }

  test(cpl_table_set_int(table, "Integer", 0, -1), 
                                              "Set Integer 0 to -1... ");
  test(cpl_table_set_int(table, "Integer", 5, 5), 
                                              "Set Integer 5 to 5... ");
  test(cpl_table_set_int(table, "Integer", 24, -1), 
                                              "Set Integer 24 to -1... ");

  array = cpl_array_new(2, CPL_TYPE_INT);
  for (j = 0; j < 2; j++)
    cpl_array_set_int(array, j, j);
  test(cpl_table_set_array(table, "AInt", 0, array),
                           "Set a valid array to AInt 0... ");
  cpl_array_delete(array);
  test_ivalue(0, cpl_table_count_invalid(table, "AInt"),
              "No invalid elements in AInt... ");

  array = cpl_array_new(2, CPL_TYPE_FLOAT);
  for (j = 0; j < 2; j++)
    cpl_array_set_float(array, j, j);
  test(cpl_table_set_array(table, "AFloat", 5, array),
                           "Set a valid array to AFloat 5... ");
  cpl_array_delete(array);
  test_ivalue(0, cpl_table_count_invalid(table, "AFloat"),
              "No invalid elements in AFloat... ");

  array = cpl_array_new(2, CPL_TYPE_DOUBLE);
  for (j = 0; j < 2; j++)
    cpl_array_set_double(array, j, j);
  test(cpl_table_set_array(table, "ADouble", 24, array),
                           "Set a valid array to ADouble 24... ");
  cpl_array_delete(array);
  test_ivalue(0, cpl_table_count_invalid(table, "ADouble"),
              "No invalid elements in ADouble... ");

/**+ FIXME: RESTORE!!! */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(0, cpl_table_count_invalid(table, "Integer"), 
                                              "Count NULLs... ");

  error = 0;

  for (i = 0; i < 25; i++) {
    cpl_table_get_int(table, "Integer", i, &null);
    if (!null) {
      if (cpl_table_get_int(table, "Integer", i, &null) != icheck[i]) {
        error = 1;
        break;
      }
    }
    else {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check Integer column... ");
    printf("Failure\n");
    
    return 1;
  }

  test(cpl_table_set_invalid(table, "Double", 0), "Set Double 0 to NULL... ");
  test(cpl_table_set_invalid(table, "Double", 5), "Set Double 5 to NULL... ");
  test(cpl_table_set_invalid(table, "Double", 24), "Set Double 24 to NULL... ");

/**+ FIXME: RESTORE!!! */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(3, cpl_table_count_invalid(table, "Double"), 
                                                  "Count written NULLs... ");

  error = 0;

  for (i = 0; i < 25; i++) {
    cpl_table_get_double(table, "Double", i, &null);
    if (!null) {
      if (cpl_table_get_double(table, "Double", i, &null) != dcheck[i]) {
        error = 1;
        break;
      }
    }
    else if (i != 0 && i != 5 && i != 24) {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check Double column... ");
    printf("Failure\n");
    
    return 1;
  }

  test(cpl_table_set_double(table, "Double", 0, -1.11), 
                                              "Set Double 0 to -1.11... ");
  test(cpl_table_set_double(table, "Double", 5, 5.11), 
                                              "Set Double 5 to 5.11... ");
  test(cpl_table_set_double(table, "Double", 24, -1.11), 
                                              "Set Double 24 to -1.11... ");

/**+ FIXME: RESTORE!!!  */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(0, cpl_table_count_invalid(table, "Double"), 
                                                  "Count NULLs... ");

  error = 0;

  for (i = 0; i < 25; i++) {
    cpl_table_get_double(table, "Double", i, &null);
    if (!null) {
      if (fabs(cpl_table_get_double(table, "Double", i, &null)-dcheck[i])
                                                              > 0.00001) {
        error = 1;
        break;
      }
    }
    else {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check Double column... ");
    printf("Failure\n");
    
    return 1;
  }


  test(cpl_table_set_invalid(table, "String", 0), "Set String 0 to NULL... ");
  test(cpl_table_set_invalid(table, "String", 5), "Set String 5 to NULL... ");
  test(cpl_table_set_invalid(table, "String", 24), "Set String 24 to NULL... ");

/**+ FIXME: RESTORE!!! %%% */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(3, cpl_table_count_invalid(table, "String"), 
                                                  "Count written NULLs... ");

  error = 0;

  for (i = 0; i < 25; i++) {
    if (cpl_table_get_string(table, "String", i)) {
      if (strcmp(cpl_table_get_string(table, "String", i), scheck[i])) {
        error = 1;
        break;
      }
    }
    else if (i != 0 && i != 5 && i != 24) {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check String column... ");
    printf("Failure\n");
    
    return 1;
  }

  test(cpl_table_set_string(table, "String", 0, "extra"),
                                              "Set String 0 to \"extra\"... ");
  test(cpl_table_set_string(table, "String", 5, "caaa"), 
                                              "Set String 5 to \"caaa\"... ");
  test(cpl_table_set_string(table, "String", 24, "extra"), 
                                              "Set String 24 to \"extra\"... ");

/**+ FIXME: RESTORE!!! %%% */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(0, cpl_table_count_invalid(table, "String"), 
                                              "Count NULLs... ");

  error = 0;

  for (i = 0; i < 25; i++) {
    if (cpl_table_get_string(table, "String", i)) {
      if (strcmp(cpl_table_get_string(table, "String", i), scheck[i])) {
        error = 1;
        break;
      }
    }
    else {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check String column... ");
    printf("Failure\n");
    
    return 1;
  }


  test(cpl_table_set_invalid(table, "Float", 0), "Set Float 0 to NULL... ");
  test(cpl_table_set_invalid(table, "Float", 5), "Set Float 5 to NULL... ");
  test(cpl_table_set_invalid(table, "Float", 24), "Set Float 24 to NULL... ");

/**+ FIXME: RESTORE!!! */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(3, cpl_table_count_invalid(table, "Float"), 
                                                  "Count written NULLs... ");

  error = 0;

  for (i = 0; i < 25; i++) {
    cpl_table_get_float(table, "Float", i, &null);
    if (!null) {
      if (cpl_table_get_float(table, "Float", i, &null) != fcheck[i]) {
        error = 1;
        break;
      }
    }
    else if (i != 0 && i != 5 && i != 24) {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check Float column... ");
    printf("Failure\n");
    
    return 1;
  }

  test(cpl_table_set_float(table, "Float", 0, -1.1), 
                                              "Set Float 0 to -1.1... ");
  test(cpl_table_set_float(table, "Float", 5, 5.1), 
                                              "Set Float 5 to 5.1... ");
  test(cpl_table_set_float(table, "Float", 24, -1.1), 
                                              "Set Float 24 to -1.1... ");

/**+ FIXME: RESTORE!!! */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(0, cpl_table_count_invalid(table, "Float"), 
                                              "Count NULLs... ");

  error = 0;

  for (i = 0; i < 25; i++) {
    cpl_table_get_float(table, "Float", i, &null);
    if (!null) {
      if (fabs(cpl_table_get_float(table, "Float", i, &null)-fcheck[i])
                                                              > 0.00001) {
        error = 1;
        break;
      }
    }
    else {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check Float column... ");
    printf("Failure\n");
    
    return 1;
  }

 /* %%% */

  test(cpl_table_set_column_invalid(table, "Integer", 0, 3), 
                                  "Set Integer 0-2 to NULL... ");
  test(cpl_table_set_column_invalid(table, "Integer", 5, 3), 
                                  "Set Integer 5-7 to NULL... ");
  test(cpl_table_set_column_invalid(table, "Integer", 20, 20), 
                                  "Set Integer 20 till end to NULL... ");

  test(cpl_table_set_column_invalid(table, "AInt", 0, 3),
                                  "Set AInt 0-2 to NULL... ");
  test(cpl_table_set_column_invalid(table, "AInt", 5, 3),
                                  "Set AInt 5-7 to NULL... ");
  test(cpl_table_set_column_invalid(table, "AInt", 20, 20),
                                  "Set AInt 20 till end to NULL... ");

/**+ FIXME: RESTORE!!! */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(11, cpl_table_count_invalid(table, "Integer"), 
              "Count Integer NULLs... ");

  test_ivalue(11, cpl_table_count_invalid(table, "AInt"), 
              "Count AInt NULLs... ");

  error = 0;

  for (i = 0; i < 25; i++) {
    cpl_table_get_int(table, "Integer", i, &null);
    if (!null) {
      if (cpl_table_get_int(table, "Integer", i, &null) != icheck[i]) {
        error = 1;
        break;
      }
    }
    else if ((i > 2 && i < 5) || (i > 7 && i < 20)) {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check Integer column... ");
    printf("Failure\n");
    
    return 1;
  }

  test(cpl_table_set_column_invalid(table, "Double", 0, 3),
                                  "Set Double 0-2 to NULL... ");
  test(cpl_table_set_column_invalid(table, "Double", 5, 3),
                                  "Set Double 5-7 to NULL... ");
  test(cpl_table_set_column_invalid(table, "Double", 20, 20),
                                  "Set Double 20 till end to NULL... ");

/**+ FIXME: RESTORE!!! */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(11, cpl_table_count_invalid(table, "Double"),
                                               "Count written NULLs... ");

  error = 0;

  for (i = 0; i < 25; i++) {
    cpl_table_get_double(table, "Double", i, &null);
    if (!null) {
      if (fabs(cpl_table_get_double(table, "Double", i, &null)-dcheck[i])
                                                       > 0.000001) {
        error = 1;
        break;
      }
    }
    else if ((i > 2 && i < 5) || (i > 7 && i < 20)) {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check Double column... ");
    printf("Failure\n");
    
    return 1;
  }


  test(cpl_table_set_column_invalid(table, "Float", 0, 3),
                                  "Set Float 0-2 to NULL... ");
  test(cpl_table_set_column_invalid(table, "Float", 5, 3),
                                  "Set Float 5-7 to NULL... ");
  test(cpl_table_set_column_invalid(table, "Float", 20, 20),
                                  "Set Float 20 till end to NULL... ");

/**+ FIXME: RESTORE!!!  */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(11, cpl_table_count_invalid(table, "Float"),
                                               "Count written NULLs... ");

  error = 0;

  for (i = 0; i < 25; i++) {
    cpl_table_get_float(table, "Float", i, &null);
    if (!null) {
      if (fabs(cpl_table_get_float(table, "Float", i, &null)-fcheck[i]) 
                                                           > 0.000001) {
        error = 1;
        break;
      }
    }
    else if ((i > 2 && i < 5) || (i > 7 && i < 20)) {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check Float column... ");
    printf("Failure\n");
    
    return 1;
  }


  test(cpl_table_set_column_invalid(table, "String", 0, 3),
                                  "Set String 0-2 to NULL... ");
  test(cpl_table_set_column_invalid(table, "String", 5, 3),
                                  "Set String 5-7 to NULL... ");
  test(cpl_table_set_column_invalid(table, "String", 20, 20),
                                  "Set String 20 till end to NULL... ");

/**+ FIXME: RESTORE!!!  */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(11, cpl_table_count_invalid(table, "String"),
                                               "Count written NULLs... ");

  error = 0;

  for (i = 0; i < 25; i++) {
    if (cpl_table_get_string(table, "String", i)) {
      if (strcmp(cpl_table_get_string(table, "String", i), scheck[i])) {
        error = 1;
        break;
      }
    }
    else if ((i > 2 && i < 5) || (i > 7 && i < 20)) {
      error = 1;
      break;
    }
  }

  if (error) {
    printf("Check String column... ");
    printf("Failure\n");
    
    return 1;
  }

  test(cpl_table_erase_window(table, 21, 4), "Delete last 4 table rows... ");

  test(cpl_table_erase_window(table, 7, 4), 
                               "Delete table rows from 7 to 10... ");

  test(cpl_table_erase_window(table, 3, 3), 
                               "Delete table rows from 3 to 5... ");

  test(cpl_table_erase_window(table, 0, 2), "Delete first two table rows... ");

  test_ivalue(12, cpl_table_get_nrow(table), "Check table length (4)... ");

  test_ivalue(3, cpl_table_count_invalid(table, "Integer"), 
                                       "Count Integer NULLs... ");

  test_ivalue(3, cpl_table_count_invalid(table, "Double"), 
                                       "Count Double NULLs... ");

  test_ivalue(3, cpl_table_count_invalid(table, "String"), 
                                       "Count String NULLs... ");

  test_ivalue(3, cpl_table_count_invalid(table, "Float"), 
                                       "Count Float NULLs... ");

  test_ivalue(3, cpl_table_count_invalid(table, "AInt"),
                                       "Count AInt NULLs... ");

  test_ivalue(0, cpl_table_count_invalid(table, "ADouble"),
                                       "Count ADouble NULLs... ");

  test_ivalue(0, cpl_table_count_invalid(table, "AFloat"),
                                       "Count AFloat NULLs... ");

  test(cpl_table_insert_window(table, 20, 5),
                                "Append 5 NULLs at table end... ");

  test(cpl_table_insert_window(table, 6, 4),
                                "Insert segment of 4 NULLs at row 6... ");

  test(cpl_table_insert_window(table, 1, 2),
                                "Insert segment of 2 NULLs at row 1... ");

  test_ivalue(23, cpl_table_get_nrow(table), "Check table length (5)... ");

  test_ivalue(14, cpl_table_count_invalid(table, "Integer"), 
                                       "Count Integer NULLs... ");

  test_ivalue(14, cpl_table_count_invalid(table, "Double"), 
                                       "Count Double NULLs... ");

  test_ivalue(14, cpl_table_count_invalid(table, "String"), 
                                       "Count String NULLs... ");

  test_ivalue(14, cpl_table_count_invalid(table, "Float"), 
                                       "Count Float NULLs... ");

  test(cpl_table_fill_column_window_int(table, "Integer", 0, 2, 999),
       "Write 999 in \"Integer\" column from 0 to 1... ");

  test(cpl_table_fill_column_window_int(table, "Integer", 3, 3, 999),
       "Write 999 in \"Integer\" column from 3 to 5... ");

  test(cpl_table_fill_column_window_int(table, "Integer", 7, 4, 999),
       "Write 999 in \"Integer\" column from 7 to 10... ");

  test(cpl_table_fill_column_window_int(table, "Integer", 20, 7, 999),
       "Write 999 in \"Integer\" column from 20 to end... ");

  test(cpl_table_fill_column_window_float(table, "Float", 0, 2, 999.99),
       "Write 999.99 in \"Float\" column from 0 to 1... ");

  test(cpl_table_fill_column_window_float(table, "Float", 3, 3, 999.99),
       "Write 999.99 in \"Float\" column from 3 to 5... ");

  test(cpl_table_fill_column_window_float(table, "Float", 7, 4, 999.99),
       "Write 999.99 in \"Float\" column from 7 to 10... ");

  test(cpl_table_fill_column_window_float(table, "Float", 20, 7, 999.99),
       "Write 999.99 in \"Float\" column from 20 to end... ");

  test(cpl_table_fill_column_window_double(table, "Double", 0, 2, 999.88),
       "Write 999.88 in \"Double\" column from 0 to 1... ");

  test(cpl_table_fill_column_window_double(table, "Double", 3, 3, 999.88),
       "Write 999.88 in \"Double\" column from 3 to 5... ");

  test(cpl_table_fill_column_window_double(table, "Double", 7, 4, 999.88),
       "Write 999.88 in \"Double\" column from 7 to 10... ");

  test(cpl_table_fill_column_window_double(table, "Double", 20, 7, 999.88),
       "Write 999.88 in \"Double\" column from 20 to end... ");

  test(cpl_table_fill_column_window_string(table, "String", 0, 2, "999"),
       "Write \"999\" in \"String\" column from 0 to 1... ");

  test(cpl_table_fill_column_window_string(table, "String", 3, 3, "999"),
       "Write \"999\" in \"String\" column from 3 to 5... ");

  test(cpl_table_fill_column_window_string(table, "String", 7, 4, "999"),
       "Write \"999\" in \"String\" column from 7 to 10... ");

  test(cpl_table_fill_column_window_string(table, "String", 20, 7, "999"),
       "Write \"999\" in \"String\" column from 20 to end... ");

/**+ FIXME: RESTORE!!!  */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(23, cpl_table_get_nrow(table), "Check table length (6)... ");

  test_ivalue(5, cpl_table_count_invalid(table, "Integer"), 
                                       "Count Integer NULLs... ");

  test_ivalue(5, cpl_table_count_invalid(table, "Float"), 
                                       "Count Float NULLs... ");

  test_ivalue(5, cpl_table_count_invalid(table, "Double"), 
                                       "Count Double NULLs... ");

  test_ivalue(5, cpl_table_count_invalid(table, "String"), 
                                       "Count String NULLs... ");

  test_ivalue(14, cpl_table_count_invalid(table, "AInt"),
                                       "Count AInt NULLs... ");

  test_ivalue(11, cpl_table_count_invalid(table, "AFloat"),
                                       "Count AFloat NULLs... ");

  test_ivalue(11, cpl_table_count_invalid(table, "ADouble"),
                                       "Count ADouble NULLs... ");

  test_ivalue(0, cpl_table_is_valid(table, "Integer", 2), 
                    "Check that third element of \"Integer\" is NULL... ");

  test_ivalue(1, cpl_table_is_valid(table, "Double", 0), 
                    "Check that first element of \"Double\" is not NULL... ");

  test_ivalue(1, cpl_table_is_valid(table, "String", 0), 
                    "Check that first element of \"String\" is not NULL... ");

  test_ivalue(0, cpl_table_is_valid(table, "String", 2), 
                    "Check that third element of \"String\" is NULL... ");

  test_ivalue(0, cpl_table_is_valid(table, "AInt", 17),
                    "Check that third element of \"AInt\" is NULL... ");

  test_ivalue(1, cpl_table_is_valid(table, "ADouble", 17),
                    "Check that first element of \"ADouble\" is not NULL... ");

  test_ivalue(1, cpl_table_is_valid(table, "AFloat", 17),
                    "Check that third element of \"AFloat\" is NULL... ");

  test_data(copia, cpl_table_duplicate(table), "Duplicate table... ");

  test(cpl_table_duplicate_column(table, "New Integer", table, "Integer"),
                        "Duplicate \"Integer\" column within same table... ");

  test(cpl_table_duplicate_column(table, "New Float", table, "Float"),
                        "Duplicate \"Float\" column within same table... ");

  test(cpl_table_duplicate_column(table, "New Double", table, "Double"),
                        "Duplicate \"Double\" column within same table... ");

  test(cpl_table_duplicate_column(table, "New String", table, "String"),
                        "Duplicate \"String\" column within same table... ");

  test(cpl_table_duplicate_column(table, "New AInt", table, "AInt"),
                        "Duplicate \"AInt\" column within same table... ");

  test(cpl_table_duplicate_column(table, "New AFloat", table, "AFloat"),
                        "Duplicate \"AFloat\" column within same table... ");

  test(cpl_table_duplicate_column(table, "New ADouble", table, "ADouble"),
                        "Duplicate \"ADouble\" column within same table... ");

  test_ivalue(5, cpl_table_count_invalid(table, "New Integer"), 
                                       "Count New Integer NULLs... ");

  test_ivalue(5, cpl_table_count_invalid(table, "New Float"), 
                                       "Count New Float NULLs... ");

  test_ivalue(5, cpl_table_count_invalid(table, "New Double"), 
                                       "Count New Double NULLs... ");

  test_ivalue(5, cpl_table_count_invalid(table, "New String"), 
                                       "Count New String NULLs... ");

  test_ivalue(14, cpl_table_count_invalid(table, "New AInt"),
                                       "Count New AInt NULLs... ");

  test_ivalue(11, cpl_table_count_invalid(table, "New AFloat"),
                                       "Count New AFloat NULLs... ");

  test_ivalue(11, cpl_table_count_invalid(table, "New ADouble"),
                                       "Count New ADouble NULLs... ");

  test(cpl_table_move_column(copia, "New Integer", table), 
           "Moving column \"New Integer\" to another table... ");

  test(cpl_table_move_column(copia, "New Float", table), 
           "Moving column \"New Float\" to another table... ");

  test(cpl_table_move_column(copia, "New Double", table), 
           "Moving column \"New Double\" to another table... ");

  test(cpl_table_move_column(copia, "New String", table), 
           "Moving column \"New String\" to another table... ");

  test_failure(CPL_ERROR_ILLEGAL_OUTPUT, 
               cpl_table_name_column(copia, "New String", "String"),
               "Try illegal column renaming... ");

  test(cpl_table_name_column(copia, "New Integer", "Old Integer"),
           "Try legal column renaming... ");

/**+ FIXME: RESTORE!!!  */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  cpl_table_fill_invalid_int(table, "New AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(!0, cpl_table_has_column(copia, "Old Integer"),
           "Check if column \"Old Integer\" exists... ");

  test_svalue("Integer", cpl_table_get_column_name(copia),
                                            "Check name column 1... ");

  test_svalue("Double", cpl_table_get_column_name(NULL),
                                            "Check name column 2... ");

  test_svalue("String", cpl_table_get_column_name(NULL),
                                            "Check name column 3... ");

  test_svalue("Float", cpl_table_get_column_name(NULL),
                                            "Check name column 4... ");

  test_svalue("AInt", cpl_table_get_column_name(NULL),
                                            "Check name column 5... ");

  test_svalue("AFloat", cpl_table_get_column_name(NULL),
                                            "Check name column 6... ");
  
  test_svalue("ADouble", cpl_table_get_column_name(NULL),
                                            "Check name column 7... ");
  
  test_svalue("Old Integer", cpl_table_get_column_name(NULL),
                                            "Check name column 8... ");

  test_svalue("New Float", cpl_table_get_column_name(NULL),
                                            "Check name column 9... ");

  test_svalue("New Double", cpl_table_get_column_name(NULL),
                                            "Check name column 10... ");

  test_svalue("New String", cpl_table_get_column_name(NULL),
                                            "Check name column 11... ");

  test_pvalue(NULL, (void *)cpl_table_get_column_name(NULL),
                                            "Check if no more colums... ");

  cpl_table_delete(copia);


  test(cpl_table_set_size(table, 30), "Expanding table to 30 rows... ");

/*
 * The following would do the same as cpl_table_set_size(table, 30), in
 * case cpl_table_set_size() would be crossed out...

  test(cpl_table_insert_window(table, 24, 7), "Expanding table to 30 rows... ");
*/

  test_ivalue(12, cpl_table_count_invalid(table, "Integer"),
                                       "Count \"Integer\" NULLs... ");

  test_ivalue(12, cpl_table_count_invalid(table, "String"),
                                       "Count \"String\" NULLs... ");

  test(cpl_table_set_size(table, 22), "Truncating table to 22 rows... ");

/*
 * The following would do the same as cpl_table_set_size(table, 30), in
 * case cpl_table_set_size() would be crossed out...

  test(cpl_table_erase_window(table, 22, 1000), 
                               "Truncating table to 22 rows... ");
*/

/**+ FIXME: RESTORE!!!  */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  cpl_table_fill_invalid_int(table, "New AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(5, cpl_table_count_invalid(table, "Integer"),
                                       "Count \"Integer\" NULLs (2)... ");

  test_ivalue(5, cpl_table_count_invalid(table, "String"),
                                       "Count \"String\" NULLs (2)... ");

  test_data(copia, cpl_table_extract(table, 0, 5), 
                       "Creating subtable from rows 0-5 of original... ");

  test_ivalue(1, cpl_table_count_invalid(copia, "Integer"),
                                       "Count \"Integer\" NULLs... ");

  test_ivalue(1, cpl_table_count_invalid(copia, "String"),
                                       "Count \"String\" NULLs... ");

  cpl_table_delete(copia);

  test_data(copia, cpl_table_extract(table, 8, 5), 
                       "Creating subtable from rows 8-5 of original... ");

  test_ivalue(1, cpl_table_count_invalid(copia, "Float"),
                                       "Count \"Float\" NULLs... ");

  test_ivalue(1, cpl_table_count_invalid(copia, "String"),
                                       "Count \"String\" NULLs... ");

  cpl_table_delete(copia);

  test_data(copia, cpl_table_extract(table, 15, 30), 
              "Creating subtable from rows 15 till end of original... ");

  test_ivalue(3, cpl_table_count_invalid(copia, "Double"),
                                       "Count \"Double\" NULLs... ");

  test_ivalue(3, cpl_table_count_invalid(copia, "String"),
                                       "Count \"String\" NULLs... ");

  cpl_table_delete(copia);

  test(cpl_table_cast_column(table, "Float", "FloatToInt", CPL_TYPE_INT),
                      "Casting float column to integer colum... ");

/**+ FIXME: RESTORE!!!  */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "FloatToInt", -2);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  cpl_table_fill_invalid_int(table, "New AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(999, cpl_table_get_int(table, "FloatToInt", 0, NULL),
                       "Check element  1 of casted column... ");
  test_ivalue(999, cpl_table_get_int(table, "FloatToInt", 1, NULL),
                       "Check element  2 of casted column... ");
  test_ivalue(0, cpl_table_is_valid(table, "FloatToInt", 2),
                       "Check element  3 of casted column... ");
  test_ivalue(999, cpl_table_get_int(table, "FloatToInt", 3, NULL),
                       "Check element  4 of casted column... ");
  test_ivalue(999, cpl_table_get_int(table, "FloatToInt", 4, NULL),
                       "Check element  5 of casted column... ");
  test_ivalue(999, cpl_table_get_int(table, "FloatToInt", 5, NULL),
                       "Check element  6 of casted column... ");
  test_ivalue(-1, cpl_table_get_int(table, "FloatToInt", 6, NULL),
                       "Check element  7 of casted column... ");
  test_ivalue(999, cpl_table_get_int(table, "FloatToInt", 7, NULL),
                       "Check element  8 of casted column... ");
  test_ivalue(999, cpl_table_get_int(table, "FloatToInt", 8, NULL),
                       "Check element  9 of casted column... ");
  test_ivalue(999, cpl_table_get_int(table, "FloatToInt", 9, NULL),
                       "Check element 10 of casted column... ");
  test_ivalue(999, cpl_table_get_int(table, "FloatToInt", 10, NULL),
                       "Check element 11 of casted column... ");
  test_ivalue(0, cpl_table_is_valid(table, "FloatToInt", 11),
                       "Check element 12 of casted column... ");
  test_ivalue(3, cpl_table_get_int(table, "FloatToInt", 12, NULL),
                       "Check element 13 of casted column... ");
  test_ivalue(7, cpl_table_get_int(table, "FloatToInt", 13, NULL),
                       "Check element 14 of casted column... ");
  test_ivalue(1, cpl_table_get_int(table, "FloatToInt", 14, NULL),
                       "Check element 15 of casted column... ");
  test_ivalue(4, cpl_table_get_int(table, "FloatToInt", 15, NULL),
                       "Check element 16 of casted column... ");
  test_ivalue(6, cpl_table_get_int(table, "FloatToInt", 16, NULL),
                       "Check element 17 of casted column... ");
  test_ivalue(0, cpl_table_is_valid(table, "FloatToInt", 17),
                       "Check element 18 of casted column... ");
  test_ivalue(0, cpl_table_is_valid(table, "FloatToInt", 18),
                       "Check element 19 of casted column... ");
  test_ivalue(0, cpl_table_is_valid(table, "FloatToInt", 19),
                       "Check element 20 of casted column... ");
  test_ivalue(999, cpl_table_get_int(table, "FloatToInt", 20, NULL),
                       "Check element 21 of casted column... ");
  test_ivalue(999, cpl_table_get_int(table, "FloatToInt", 21, NULL),
                       "Check element 22 of casted column... ");

  test(cpl_table_erase_column(table, "FloatToInt"),
                                      "Delete casted column... ");

  test(cpl_table_cast_column(table, "Integer", "IntToFloat", CPL_TYPE_FLOAT),
                      "Casting integer column to float colum... ");

/**- FIXME: RESTORE!!!  */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  cpl_table_fill_invalid_int(table, "New AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 0, NULL),
                     "Check element  1 of casted column (2)... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 1, NULL),
                     "Check element  2 of casted column (2)... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 2),
                     "Check element  3 of casted column (2)... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 3, NULL),
                     "Check element  4 of casted column (2)... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 4, NULL),
                     "Check element  5 of casted column (2)... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 5, NULL),
                     "Check element  6 of casted column (2)... ");
  test_fvalue(-1.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 6, NULL),
                     "Check element  7 of casted column (2)... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 7, NULL),
                     "Check element  8 of casted column (2)... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 8, NULL),
                     "Check element  9 of casted column (2)... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 9, NULL),
                     "Check element 10 of casted column (2)... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 10, NULL),
                     "Check element 11 of casted column (2)... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 11),
                     "Check element 12 of casted column (2)... ");
  test_fvalue(3.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 12, NULL),
                     "Check element 13 of casted column (2)... ");
  test_fvalue(7.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 13, NULL),
                     "Check element 14 of casted column (2)... ");
  test_fvalue(1.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 14, NULL),
                     "Check element 15 of casted column (2)... ");
  test_fvalue(4.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 15, NULL),
                     "Check element 16 of casted column (2)... ");
  test_fvalue(6.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 16, NULL),
                     "Check element 17 of casted column (2)... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 17),
                     "Check element 18 of casted column (2)... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 18),
                     "Check element 19 of casted column (2)... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 19),
                     "Check element 20 of casted column (2)... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 20, NULL),
                     "Check element 21 of casted column (2)... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 21, NULL),
                     "Check element 22 of casted column (2)... ");

  test(cpl_table_shift_column(table, "IntToFloat", 1), 
                              "Shift new column one position down... ");

  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 0),
                     "Check element  1 of shifted column... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 1, NULL),
                     "Check element  2 of shifted column... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 2, NULL),
                     "Check element  3 of shifted column... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 3),
                     "Check element  4 of shifted column... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 4, NULL),
                     "Check element  5 of shifted column... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 5, NULL),
                     "Check element  6 of shifted column... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 6, NULL),
                     "Check element  7 of shifted column... ");
  test_fvalue(-1.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 7, NULL),
                     "Check element  8 of shifted column... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 8, NULL),
                     "Check element  9 of shifted column... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 9, NULL),
                     "Check element 10 of shifted column... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 10, NULL),
                     "Check element 11 of shifted column... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 11, NULL),
                     "Check element 12 of shifted column... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 12),
                     "Check element 13 of shifted column... ");
  test_fvalue(3.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 13, NULL),
                     "Check element 14 of shifted column... ");
  test_fvalue(7.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 14, NULL),
                     "Check element 15 of shifted column... ");
  test_fvalue(1.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 15, NULL),
                     "Check element 16 of shifted column... ");
  test_fvalue(4.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 16, NULL),
                     "Check element 17 of shifted column... ");
  test_fvalue(6.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 17, NULL),
                     "Check element 18 of shifted column... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 18),
                     "Check element 19 of shifted column... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 19),
                     "Check element 20 of shifted column... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 20),
                     "Check element 21 of shifted column... ");
  test_fvalue(999.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 21, NULL),
                     "Check element 22 of shifted column... ");

  test(cpl_table_add_columns(table, "Integer", "IntToFloat"), 
                            "Sum \"IntToFloat\" to \"Integer\"... ");

/**- FIXME: RESTORE!!!  */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  cpl_table_fill_invalid_int(table, "New AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(0, cpl_table_is_valid(table, "Integer", 0),
                       "Check element  1 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(1998, cpl_table_get_int(table, "Integer", 1, NULL),
                       "Check element  2 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Integer", 2),
                       "Check element  3 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Integer", 3),
                       "Check element  4 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(1998, cpl_table_get_int(table, "Integer", 4, NULL),
                       "Check element  5 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(1998, cpl_table_get_int(table, "Integer", 5, NULL),
                       "Check element  6 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(998, cpl_table_get_int(table, "Integer", 6, NULL),
                       "Check element  7 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(998, cpl_table_get_int(table, "Integer", 7, NULL),
                       "Check element  8 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(1998, cpl_table_get_int(table, "Integer", 8, NULL),
                       "Check element  9 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(1998, cpl_table_get_int(table, "Integer", 9, NULL),
                       "Check element 10 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(1998, cpl_table_get_int(table, "Integer", 10, NULL),
                       "Check element 11 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Integer", 11),
                       "Check element 12 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Integer", 12),
                       "Check element 13 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(10, cpl_table_get_int(table, "Integer", 13, NULL),
                       "Check element 14 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(8, cpl_table_get_int(table, "Integer", 14, NULL),
                       "Check element 15 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(5, cpl_table_get_int(table, "Integer", 15, NULL),
                       "Check element 16 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(10, cpl_table_get_int(table, "Integer", 16, NULL),
                       "Check element 17 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Integer", 17),
                       "Check element 18 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Integer", 18),
                       "Check element 19 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Integer", 19),
                       "Check element 20 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Integer", 20),
                       "Check element 21 of \"Integer\" += \"IntToFloat\"... ");
  test_ivalue(1998, cpl_table_get_int(table, "Integer", 21, NULL),
                       "Check element 22 of \"Integer\" += \"IntToFloat\"... ");

  test(cpl_table_subtract_columns(table, "Integer", "IntToFloat"), 
                            "Subtract \"IntToFloat\" from \"Integer\"... ");

  test(cpl_table_subtract_columns(table, "IntToFloat", "Integer"), 
                            "Subtract \"Integer\" from \"IntToFloat\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 0),
                     "Check element  1 of \"IntToFloat\" -= \"Integer\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 1, NULL),
                     "Check element  2 of \"IntToFloat\" -= \"Integer\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 2),
                     "Check element  3 of \"IntToFloat\" -= \"Integer\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 3),
                     "Check element  4 of \"IntToFloat\" -= \"Integer\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 4, NULL),
                     "Check element  5 of \"IntToFloat\" -= \"Integer\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 5, NULL),
                     "Check element  6 of \"IntToFloat\" -= \"Integer\"... ");
  test_fvalue(1000.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 6, NULL),
                     "Check element  7 of \"IntToFloat\" -= \"Integer\"... ");
  test_fvalue(-1000.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 7, NULL),
                     "Check element  8 of \"IntToFloat\" -= \"Integer\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 8, NULL),
                     "Check element  9 of \"IntToFloat\" -= \"Integer\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 9, NULL),
                     "Check element 10 of \"IntToFloat\" -= \"Integer\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 10, NULL),
                     "Check element 11 of \"IntToFloat\" -= \"Integer\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 11),
                     "Check element 12 of \"IntToFloat\" -= \"Integer\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 12),
                     "Check element 13 of \"IntToFloat\" -= \"Integer\"... ");
  test_fvalue(-4.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 13, NULL),
                     "Check element 14 of \"IntToFloat\" -= \"Integer\"... ");
  test_fvalue(6.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 14, NULL),
                     "Check element 15 of \"IntToFloat\" -= \"Integer\"... ");
  test_fvalue(-3.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 15, NULL),
                     "Check element 16 of \"IntToFloat\" -= \"Integer\"... ");
  test_fvalue(-2.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 16, NULL),
                     "Check element 17 of \"IntToFloat\" -= \"Integer\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 17),
                     "Check element 18 of \"IntToFloat\" -= \"Integer\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 18),
                     "Check element 19 of \"IntToFloat\" -= \"Integer\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 19),
                     "Check element 20 of \"IntToFloat\" -= \"Integer\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 20),
                     "Check element 21 of \"IntToFloat\" -= \"Integer\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 21, NULL),
                     "Check element 22 of \"IntToFloat\" -= \"Integer\"... ");

  test(cpl_table_multiply_columns(table, "IntToFloat", "Double"), 
                     "Multiply double column with float column... ");

  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 0),
                     "Check element  1 of \"IntToFloat\" *= \"Double\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 1, NULL),
                     "Check element  2 of \"IntToFloat\" *= \"Double\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 2),
                     "Check element  3 of \"IntToFloat\" *= \"Double\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 3),
                     "Check element  4 of \"IntToFloat\" *= \"Double\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 4, NULL),
                     "Check element  5 of \"IntToFloat\" *= \"Double\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 5, NULL),
                     "Check element  6 of \"IntToFloat\" *= \"Double\"... ");
  test_fvalue(-1110.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 6, NULL),
                     "Check element  7 of \"IntToFloat\" *= \"Double\"... ");
  test_fvalue(-999880.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 7, NULL),
                     "Check element  8 of \"IntToFloat\" *= \"Double\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 8, NULL),
                     "Check element  9 of \"IntToFloat\" *= \"Double\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 9, NULL),
                     "Check element 10 of \"IntToFloat\" *= \"Double\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 10, NULL),
                     "Check element 11 of \"IntToFloat\" *= \"Double\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 11),
                     "Check element 12 of \"IntToFloat\" *= \"Double\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 12),
                     "Check element 13 of \"IntToFloat\" *= \"Double\"... ");
  test_fvalue(-28.44, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 13, NULL),
                     "Check element 14 of \"IntToFloat\" *= \"Double\"... ");
  test_fvalue(6.66, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 14, NULL),
                     "Check element 15 of \"IntToFloat\" *= \"Double\"... ");
  test_fvalue(-12.33, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 15, NULL),
                     "Check element 16 of \"IntToFloat\" *= \"Double\"... ");
  test_fvalue(-12.22, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 16, NULL),
                     "Check element 17 of \"IntToFloat\" *= \"Double\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 17),
                     "Check element 18 of \"IntToFloat\" *= \"Double\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 18),
                     "Check element 19 of \"IntToFloat\" *= \"Double\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 19),
                     "Check element 20 of \"IntToFloat\" *= \"Double\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "IntToFloat", 20),
                     "Check element 21 of \"IntToFloat\" *= \"Double\"... ");
  test_fvalue(0.0, 0.00001,
                     cpl_table_get_float(table, "IntToFloat", 21, NULL),
                     "Check element 22 of \"IntToFloat\" *= \"Double\"... ");

  test(cpl_table_divide_columns(table, "Float", "IntToFloat"), 
                     "Divide float column with float column... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 0),
                     "Check element  1 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 1),
                     "Check element  2 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 2),
                     "Check element  3 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 3),
                     "Check element  4 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 4),
                     "Check element  5 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 5),
                     "Check element  6 of \"Float\" /= \"IntToFloat\"... ");
  test_fvalue(0.000991, 0.0000001,
                     cpl_table_get_float(table, "Float", 6, NULL),
                     "Check element  7 of \"Float\" /= \"IntToFloat\"... ");
  test_fvalue(-0.0010001, 0.0000001,
                     cpl_table_get_float(table, "Float", 7, NULL),
                     "Check element  8 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 8),
                     "Check element  9 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 9),
                     "Check element 10 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 10),
                     "Check element 11 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 11),
                     "Check element 12 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 12),
                     "Check element 13 of \"Float\" /= \"IntToFloat\"... ");
  test_fvalue(-0.2496484, 0.0000001,
                     cpl_table_get_float(table, "Float", 13, NULL),
                     "Check element 14 of \"Float\" /= \"IntToFloat\"... ");
  test_fvalue(0.1651652, 0.0000001,
                     cpl_table_get_float(table, "Float", 14, NULL),
                     "Check element 15 of \"Float\" /= \"IntToFloat\"... ");
  test_fvalue(-0.3325223, 0.0000001,
                     cpl_table_get_float(table, "Float", 15, NULL),
                     "Check element 16 of \"Float\" /= \"IntToFloat\"... ");
  test_fvalue(-0.4991817, 0.0000001,
                     cpl_table_get_float(table, "Float", 16, NULL),
                     "Check element 17 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 17),
                     "Check element 18 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 18),
                     "Check element 19 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 19),
                     "Check element 20 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 20),
                     "Check element 21 of \"Float\" /= \"IntToFloat\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 21),
                     "Check element 22 of \"Float\" /= \"IntToFloat\"... ");

  test(cpl_table_add_scalar(table, "Float", 1), 
                     "Add integer constant to \"Float\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 0),
                     "Check element  1 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 1),
                     "Check element  2 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 2),
                     "Check element  3 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 3),
                     "Check element  4 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 4),
                     "Check element  5 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 5),
                     "Check element  6 of adding 1 to \"Float\"... ");
  test_fvalue(1.000991, 0.0000001,
                     cpl_table_get_float(table, "Float", 6, NULL),
                     "Check element  7 of adding 1 to \"Float\"... ");
  test_fvalue(1-0.0010001, 0.0000001,
                     cpl_table_get_float(table, "Float", 7, NULL),
                     "Check element  8 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 8),
                     "Check element  9 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 9),
                     "Check element 10 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 10),
                     "Check element 11 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 11),
                     "Check element 12 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 12),
                     "Check element 13 of adding 1 to \"Float\"... ");
  test_fvalue(1-0.2496484, 0.0000001,
                     cpl_table_get_float(table, "Float", 13, NULL),
                     "Check element 14 of adding 1 to \"Float\"... ");
  test_fvalue(1.1651652, 0.0000001,
                     cpl_table_get_float(table, "Float", 14, NULL),
                     "Check element 15 of adding 1 to \"Float\"... ");
  test_fvalue(1-0.3325223, 0.0000001,
                     cpl_table_get_float(table, "Float", 15, NULL),
                     "Check element 16 of adding 1 to \"Float\"... ");
  test_fvalue(1-0.4991817, 0.0000001,
                     cpl_table_get_float(table, "Float", 16, NULL),
                     "Check element 17 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 17),
                     "Check element 18 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 18),
                     "Check element 19 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 19),
                     "Check element 20 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 20),
                     "Check element 21 of adding 1 to \"Float\"... ");
  test_ivalue(0, cpl_table_is_valid(table, "Float", 21),
                     "Check element 22 of adding 1 to \"Float\"... ");

  test(cpl_table_set_column_invalid(table, "Float", 0, 
                     cpl_table_get_nrow(table)), 
                     "Set \"Float\" column to NULL... ");

  test_data(copia, cpl_table_duplicate(table), "Duplicate table... ");

  test(cpl_table_erase_invalid_rows(table), "Pruning table... ");

  test_ivalue(18, cpl_table_get_nrow(table), 
                       "Checking table length after pruning... ");

  test_ivalue(10, cpl_table_get_ncol(table), 
                       "Checking table width after pruning... ");

  test(cpl_table_erase_invalid(copia), "Cleaning table... ");

  test_ivalue(8, cpl_table_get_nrow(copia), 
                       "Checking table length after cleaning... ");

  test_ivalue(10, cpl_table_get_ncol(copia), 
                       "Checking table width after cleaning... ");

  cpl_table_delete(copia);

  test(cpl_table_name_column(table, "IntToFloat", "Float"),
           "Renaming \"IntToFloat\" to \"Float\"... ");

  test(cpl_table_set_column_invalid(table, "Integer", 7, 2), 
                              "Set NULLs in \"Integer\" column... ");

  test(cpl_table_set_invalid(table, "Float", 7), 
                              "Set NULL in \"Float\" column... ");

  test(cpl_table_set_invalid(table, "Float", 9), 
                              "Set another NULL in \"Float\" column... ");

  test(cpl_table_set_invalid(table, "Double", 7), 
                              "Set NULL in \"Double\" column... ");

  test(cpl_table_set_invalid(table, "String", 7), 
                              "Set NULL in \"String\" column... ");

  test(cpl_table_new_column(table, "Sequence", CPL_TYPE_INT),
                                "Creating the \"Sequence\" column... ");

  for (i = 0; i < 18; i++) {
    sprintf(message, "Writing to row %d of the \"Sequence\" column... ", i);
    test(cpl_table_set_int(table, "Sequence", i, i), message);
  }
/*
  cpl_table_dump_structure(table);
  cpl_table_dump(table, 0, cpl_table_get_nrow(table));
*/
  names[0] = "Integer";

  reflist = uves_propertylist_new();
  uves_propertylist_append_bool(reflist, names[0], 0);
/* %$% */
/*
cpl_table_dump_structure(table, NULL);
cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);
*/

  test(uves_table_sort(table, reflist), 
       "Sorting by increasing values of the \"Integer\" column... ");

  uves_propertylist_delete(reflist);

/**- FIXME: RESTORE!!!  */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  cpl_table_fill_invalid_int(table, "New AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(18, cpl_table_get_nrow(table),
                       "Checking table length after sorting... ");

  test_ivalue(11, cpl_table_get_ncol(table),
                       "Checking table width after sorting... ");

  test_ivalue(7, cpl_table_count_invalid(table, "Integer"),
                     "Count \"Integer\" NULLs after sorting... ");

  test_ivalue(7, cpl_table_count_invalid(table, "Float"),
                     "Count \"Float\" NULLs after sorting... ");

  test_ivalue(2, cpl_table_count_invalid(table, "Double"),
                     "Count \"Double\" NULLs after sorting... ");

  test_ivalue(2, cpl_table_count_invalid(table, "String"),
                     "Count \"String\" NULLs after sorting... ");

  for (i = 0; i < 7; i++) {
    sprintf(message, "Check element  %d of sorted \"Integer\"... ", i + 1);
    test_ivalue(0, cpl_table_is_valid(table, "Integer", i), message);
  }

  test_ivalue(-1, cpl_table_get_int(table, "Integer", 7, NULL),
                     "Check element  7 of sorted \"Integer\"... ");

  test_ivalue(1, cpl_table_get_int(table, "Integer", 8, NULL),
                     "Check element  8 of sorted \"Integer\"... ");

  test_ivalue(4, cpl_table_get_int(table, "Integer", 9, NULL),
                     "Check element  9 of sorted \"Integer\"... ");

  test_ivalue(6, cpl_table_get_int(table, "Integer", 10, NULL),
                     "Check element 10 of sorted \"Integer\"... ");

  test_ivalue(7, cpl_table_get_int(table, "Integer", 11, NULL),
                     "Check element 11 of sorted \"Integer\"... ");

  for (i = 12; i < 18; i++) {
    sprintf(message, "Check element  %d of sorted \"Integer\"... ", i + 1);
    test_ivalue(999, cpl_table_get_int(table, "Integer", i, NULL),
                       message);
  }

  test_fvalue(999.88, 0.00001,
                     cpl_table_get_double(table, "Double", 0, NULL),
                     "Check element  1 of sorted \"Double\"... ");

  test_fvalue(999.88, 0.00001,
                     cpl_table_get_double(table, "Double", 1, NULL),
                     "Check element  2 of sorted \"Double\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Double", 2), 
                     "Check element  3 of sorted \"Double\"... ");

  test_fvalue(999.88, 0.00001,
                     cpl_table_get_double(table, "Double", 3, NULL),
                     "Check element  4 of sorted \"Double\"... ");

  test_fvalue(3.11, 0.00001,
                     cpl_table_get_double(table, "Double", 4, NULL),
                     "Check element  5 of sorted \"Double\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Double", 5), 
                     "Check element  6 of sorted \"Double\"... ");

  test_fvalue(999.88, 0.00001,
                     cpl_table_get_double(table, "Double", 6, NULL),
                     "Check element  7 of sorted \"Double\"... ");

  test_fvalue(-1.11, 0.00001,
                     cpl_table_get_double(table, "Double", 7, NULL),
                     "Check element  8 of sorted \"Double\"... ");

  test_fvalue(1.11, 0.00001,
                    cpl_table_get_double(table, "Double", 8, NULL),
                    "Check element  9 of sorted \"Double\"... ");

  test_fvalue(4.11, 0.00001,
                    cpl_table_get_double(table, "Double", 9, NULL),
                    "Check element  10 of sorted \"Double\"... ");

  test_fvalue(6.11, 0.00001,
                    cpl_table_get_double(table, "Double", 10, NULL),
                    "Check element 11 of sorted \"Double\"... ");

  test_fvalue(7.11, 0.00001,
                    cpl_table_get_double(table, "Double", 11, NULL),
                    "Check element 12 of sorted \"Double\"... ");

  for (i = 12; i < 18; i++) {
    sprintf(message, "Check element  %d of sorted \"Double\"... ", i + 1);
    test_fvalue(999.88, 0.00001, 
                cpl_table_get_double(table, "Double", i, NULL), message);
  }

  test_svalue("999", cpl_table_get_string(table, "String", 0),
              "Check element  1 of sorted \"String\"... ");

  test_svalue("999", cpl_table_get_string(table, "String", 1),
              "Check element  2 of sorted \"String\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "String", 2),
              "Check element  3 of sorted \"String\"... ");

  test_svalue("999", cpl_table_get_string(table, "String", 3),
              "Check element  4 of sorted \"String\"... ");

  test_svalue("baaa", cpl_table_get_string(table, "String", 4),
              "Check element  5 of sorted \"String\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "String", 5),
              "Check element  6 of sorted \"String\"... ");

  test_svalue("999", cpl_table_get_string(table, "String", 6),
              "Check element  7 of sorted \"String\"... ");

  test_svalue("extra", cpl_table_get_string(table, "String", 7),
              "Check element  8 of sorted \"String\"... ");

  test_svalue("acde", cpl_table_get_string(table, "String", 8),
              "Check element  9 of sorted \"String\"... ");

  test_svalue(" sss", cpl_table_get_string(table, "String", 9),
              "Check element 10 of sorted \"String\"... ");

  test_svalue("daaa", cpl_table_get_string(table, "String", 10),
              "Check element 11 of sorted \"String\"... ");

  test_svalue("aaaa", cpl_table_get_string(table, "String", 11),
              "Check element 11 of sorted \"String\"... ");

  for (i = 12; i < 18; i++) {
    sprintf(message, "Check element  %d of sorted \"String\"... ", i + 1);
    test_svalue("999", cpl_table_get_string(table, "String", i), message);
  }


  test_ivalue(0, cpl_table_is_valid(table, "Float", 0),
              "Check element  1 of sorted \"Float\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 1),
              "Check element  2 of sorted \"Float\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 2),
              "Check element  3 of sorted \"Float\"... ");

  test_fvalue(0.0, 0.00001, cpl_table_get_float(table, "Float", 3, NULL),
              "Check element  4 of sorted \"Float\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 4),
              "Check element  5 of sorted \"Float\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 5),
              "Check element  6 of sorted \"Float\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 6),
              "Check element  7 of sorted \"Float\"... ");

  test_fvalue(-1110.0, 0.00001, 
              cpl_table_get_float(table, "Float", 7, NULL),
              "Check element  8 of sorted \"Float\"... ");

  test_fvalue(6.66, 0.00001, 
              cpl_table_get_float(table, "Float", 8, NULL),
              "Check element  9 of sorted \"Float\"... ");

  test_fvalue(-12.33, 0.00001, 
              cpl_table_get_float(table, "Float", 9, NULL),
              "Check element 10 of sorted \"Float\"... ");

  test_fvalue(-12.22, 0.00001, 
              cpl_table_get_float(table, "Float", 10, NULL),
              "Check element 11 of sorted \"Float\"... ");

  test_fvalue(-28.44, 0.00001, 
              cpl_table_get_float(table, "Float", 11, NULL),
              "Check element 12 of sorted \"Float\"... ");

  test_fvalue(0.0, 0.00001, 
              cpl_table_get_float(table, "Float", 12, NULL),
              "Check element 13 of sorted \"Float\"... ");

  test_fvalue(0.0, 0.00001, 
              cpl_table_get_float(table, "Float", 13, NULL),
              "Check element 14 of sorted \"Float\"... ");

  test_fvalue(0.0, 0.00001, 
              cpl_table_get_float(table, "Float", 14, NULL),
              "Check element 15 of sorted \"Float\"... ");

  test_fvalue(-999880.0, 0.00001, 
              cpl_table_get_float(table, "Float", 15, NULL),
              "Check element 16 of sorted \"Float\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 16),
              "Check element 17 of sorted \"Float\"... ");

  test_fvalue(0.0, 0.00001, 
              cpl_table_get_float(table, "Float", 17, NULL),
              "Check element 18 of sorted \"Float\"... ");

  names[0] = "Sequence";

  reflist = uves_propertylist_new();
  uves_propertylist_append_bool(reflist, names[0], 0);

  test(uves_table_sort(table, reflist), "Undo table sorting... ");

  uves_propertylist_delete(reflist);

  names[0] = "Integer";
  reverse[0] = 1;

  reflist = uves_propertylist_new();
  uves_propertylist_append_bool(reflist, names[0], 1);

  test(uves_table_sort(table, reflist), 
       "Sorting by decreasing values of the \"Integer\" column... ");

/* %$% */
/*
cpl_table_dump_structure(table, NULL);
cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);
*/

  uves_propertylist_delete(reflist);

/*
  cpl_table_dump_structure(table, NULL);
  cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);

  printf("Median of Integer: %d\n", cpl_table_median_int(table, "Integer"));
  printf("Median of Float: %f\n", cpl_table_median_float(table, "Float"));
  printf("Median of Double: %f\n", cpl_table_median_double(table, "Double"));
  printf("Median of Sequence: %d\n", cpl_table_median_int(table, "Sequence"));
*/

/*

cpl_table_dump_structure(table, NULL);
cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);

*/

  test_fvalue(999.000000, 0.001, cpl_table_get_column_median(table, "Integer"),
                   "Median of Integer...");
  test_fvalue(0.000000, 0.001, cpl_table_get_column_median(table, "Float"),
                   "Median of Float...");
  test_fvalue(999.880000, 0.001, cpl_table_get_column_median(table, "Double"),
                   "Median of Double...");
  test_fvalue(8.000000, 0.001, cpl_table_get_column_median(table, "Sequence"),
                   "Median of Sequence...");
  test_fvalue(546.454545, 0.001, cpl_table_get_column_mean(table, "Integer"),
                   "Mean of Integer...");
  test_fvalue(-91003.302727, 0.001, cpl_table_get_column_mean(table, "Float"),
                   "Mean of Float...");
  test_fvalue(626.202500, 0.001, cpl_table_get_column_mean(table, "Double"),
                   "Mean of Double...");
  test_fvalue(8.500000, 0.001, cpl_table_get_column_mean(table, "Sequence"),
                   "Mean of Sequence...");
  test_fvalue(519.939489, 0.001, cpl_table_get_column_stdev(table, "Integer"),
                   "Stdev of Integer...");
  test_fvalue(301440.480937, 0.001, cpl_table_get_column_stdev(table, "Float"),
                   "Stdev of Float...");
  test_fvalue(498.239830, 0.001, cpl_table_get_column_stdev(table, "Double"),
                   "Stdev of Double...");
  test_fvalue(5.338539, 0.001, cpl_table_get_column_stdev(table, "Sequence"),
                   "Stdev of Sequence...");

/*

  printf("median of Integer: %f\n", cpl_table_get_column_median(table, "Integer"));
  printf("median of Float: %f\n", cpl_table_get_column_median(table, "Float"));
  printf("median of Double: %f\n", cpl_table_get_column_median(table, "Double"));
  printf("median of Sequence: %f\n", cpl_table_get_column_median(table, "Sequence"));
  printf("mean of Integer: %f\n", cpl_table_get_column_mean(table, "Integer"));
  printf("mean of Float: %f\n", cpl_table_get_column_mean(table, "Float"));
  printf("mean of Double: %f\n", cpl_table_get_column_mean(table, "Double"));
  printf("mean of Sequence: %f\n", cpl_table_get_column_mean(table, "Sequence"));
  printf("Stdev of Integer: %f\n", cpl_table_get_column_stdev(table, "Integer"));
  printf("Stdev of Float: %f\n", cpl_table_get_column_stdev(table, "Float"));
  printf("Stdev of Double: %f\n", cpl_table_get_column_stdev(table, "Double"));
  printf("Stdev of Sequence: %f\n", cpl_table_get_column_stdev(table, "Sequence"));
*/

/**- FIXME: RESTORE!!!  */
  cpl_table_fill_invalid_int(table, "Integer", 320);
  cpl_table_fill_invalid_int(table, "AInt", 320);
  cpl_table_fill_invalid_int(table, "New AInt", 320);
  check_nomsg(cpl_table_save(table, NULL, NULL, "test_table.tfits", CPL_IO_DEFAULT));
  cpl_table_delete(table);
  table = cpl_table_load("test_table.tfits", 1, 1);
/**/

  test_ivalue(18, cpl_table_get_nrow(table),
                       "Checking table length after decreasing sorting... ");

  test_ivalue(11, cpl_table_get_ncol(table),
                       "Checking table width after decreasing sorting... ");

  test_ivalue(7, cpl_table_count_invalid(table, "Integer"),
                     "Count \"Integer\" NULLs after decreasing sorting... ");

  test_ivalue(7, cpl_table_count_invalid(table, "Float"),
                     "Count \"Float\" NULLs after decreasing sorting... ");

  test_ivalue(2, cpl_table_count_invalid(table, "Double"),
                     "Count \"Double\" NULLs after decreasing sorting... ");

  test_ivalue(2, cpl_table_count_invalid(table, "String"),
                     "Count \"String\" NULLs after decreasing sorting... ");

  for (i = 0; i < 7; i++) {
    sprintf(message, "Check element  %d of sorted \"Integer\"... ", i + 1);
    test_ivalue(0, cpl_table_is_valid(table, "Integer", i), message);
  }

  for (i = 7; i < 13; i++) {
    sprintf(message, "Check element  %d of sorted \"Integer\"... ", i + 1);
    test_ivalue(999, cpl_table_get_int(table, "Integer", i, NULL),
                       message);
  }

  test_ivalue(7, cpl_table_get_int(table, "Integer", 13, NULL),
                     "Check element 13 of sorted \"Integer\"... ");

  test_ivalue(6, cpl_table_get_int(table, "Integer", 14, NULL),
                     "Check element 14 of sorted \"Integer\"... ");

  test_ivalue(4, cpl_table_get_int(table, "Integer", 15, NULL),
                     "Check element 15 of sorted \"Integer\"... ");

  test_ivalue(1, cpl_table_get_int(table, "Integer", 16, NULL),
                     "Check element 16 of sorted \"Integer\"... ");

  test_ivalue(-1, cpl_table_get_int(table, "Integer", 17, NULL),
                     "Check element 17 of sorted \"Integer\"... ");


  test_fvalue(999.88, 0.00001,
                     cpl_table_get_double(table, "Double", 0, NULL),
                     "Check element  1 of sorted \"Double\"... ");

  test_fvalue(999.88, 0.00001,
                     cpl_table_get_double(table, "Double", 1, NULL),
                     "Check element  2 of sorted \"Double\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Double", 2),
                     "Check element  3 of sorted \"Double\"... ");

  test_fvalue(999.88, 0.00001,
                     cpl_table_get_double(table, "Double", 3, NULL),
                     "Check element  4 of sorted \"Double\"... ");

  test_fvalue(3.11, 0.00001,
                     cpl_table_get_double(table, "Double", 4, NULL),
                     "Check element  5 of sorted \"Double\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Double", 5),
                     "Check element  6 of sorted \"Double\"... ");

  test_fvalue(999.88, 0.00001,
                     cpl_table_get_double(table, "Double", 6, NULL),
                     "Check element  7 of sorted \"Double\"... ");

  for (i = 7; i < 13; i++) {
    sprintf(message, "Check element  %d of sorted \"Double\"... ", i + 1);
    test_fvalue(999.88, 0.00001,
                cpl_table_get_double(table, "Double", i, NULL), message);
  }

  test_fvalue(7.11, 0.00001,
                    cpl_table_get_double(table, "Double", 13, NULL),
                    "Check element 14 of sorted \"Double\"... ");

  test_fvalue(6.11, 0.00001,
                    cpl_table_get_double(table, "Double", 14, NULL),
                    "Check element 15 of sorted \"Double\"... ");

  test_fvalue(4.11, 0.00001,
                    cpl_table_get_double(table, "Double", 15, NULL),
                    "Check element 16 of sorted \"Double\"... ");

  test_fvalue(1.11, 0.00001,
                    cpl_table_get_double(table, "Double", 16, NULL),
                    "Check element 17 of sorted \"Double\"... ");

  test_fvalue(-1.11, 0.00001,
                     cpl_table_get_double(table, "Double", 17, NULL),
                     "Check element 18 of sorted \"Double\"... ");


  test_svalue("999", cpl_table_get_string(table, "String", 0),
              "Check element  1 of sorted \"String\"... ");

  test_svalue("999", cpl_table_get_string(table, "String", 1),
              "Check element  2 of sorted \"String\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "String", 2),
              "Check element  3 of sorted \"String\"... ");

  test_svalue("999", cpl_table_get_string(table, "String", 3),
              "Check element  4 of sorted \"String\"... ");

  test_svalue("baaa", cpl_table_get_string(table, "String", 4),
              "Check element  5 of sorted \"String\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "String", 5),
              "Check element  6 of sorted \"String\"... ");

  test_svalue("999", cpl_table_get_string(table, "String", 6),
              "Check element  7 of sorted \"String\"... ");

  for (i = 7; i < 13; i++) {
    sprintf(message, "Check element  %d of sorted \"String\"... ", i + 1);
    test_svalue("999", cpl_table_get_string(table, "String", i), message);
  }

  test_svalue("aaaa", cpl_table_get_string(table, "String", 13),
              "Check element 14 of sorted \"String\"... ");

  test_svalue("daaa", cpl_table_get_string(table, "String", 14),
              "Check element 15 of sorted \"String\"... ");

  test_svalue(" sss", cpl_table_get_string(table, "String", 15),
              "Check element 16 of sorted \"String\"... ");

  test_svalue("acde", cpl_table_get_string(table, "String", 16),
              "Check element 17 of sorted \"String\"... ");

  test_svalue("extra", cpl_table_get_string(table, "String", 17),
              "Check element 18 of sorted \"String\"... ");


  test_ivalue(0, cpl_table_is_valid(table, "Float", 0),
              "Check element  1 of sorted \"Float\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 1),
              "Check element  2 of sorted \"Float\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 2),
              "Check element  3 of sorted \"Float\"... ");

  test_fvalue(0.0, 0.00001, cpl_table_get_float(table, "Float", 3, NULL),
              "Check element  4 of sorted \"Float\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 4),
              "Check element  5 of sorted \"Float\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 5),
              "Check element  6 of sorted \"Float\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 6),
              "Check element  7 of sorted \"Float\"... ");

  test_fvalue(0.0, 0.00001,
              cpl_table_get_float(table, "Float", 7, NULL),
              "Check element  8 of sorted \"Float\"... ");

  test_fvalue(0.0, 0.00001,
              cpl_table_get_float(table, "Float", 8, NULL),
              "Check element  9 of sorted \"Float\"... ");

  test_fvalue(0.0, 0.00001,
              cpl_table_get_float(table, "Float", 9, NULL),
              "Check element 10 of sorted \"Float\"... ");

  test_fvalue(-999880.0, 0.00001,
              cpl_table_get_float(table, "Float", 10, NULL),
              "Check element 11 of sorted \"Float\"... ");

  test_ivalue(0, cpl_table_is_valid(table, "Float", 11),
              "Check element 12 of sorted \"Float\"... ");

  test_fvalue(0.0, 0.00001,
              cpl_table_get_float(table, "Float", 12, NULL),
              "Check element 13 of sorted \"Float\"... ");

  test_fvalue(-28.44, 0.00001,
              cpl_table_get_float(table, "Float", 13, NULL),
              "Check element 14 of sorted \"Float\"... ");

  test_fvalue(-12.22, 0.00001,
              cpl_table_get_float(table, "Float", 14, NULL),
              "Check element 15 of sorted \"Float\"... ");

  test_fvalue(-12.33, 0.00001,
              cpl_table_get_float(table, "Float", 15, NULL),
              "Check element 16 of sorted \"Float\"... ");

  test_fvalue(6.66, 0.00001,
              cpl_table_get_float(table, "Float", 16, NULL),
              "Check element 17 of sorted \"Float\"... ");

  test_fvalue(-1110.0, 0.00001,
              cpl_table_get_float(table, "Float", 17, NULL),
              "Check element 18 of sorted \"Float\"... ");

  cpl_table_delete(table);
  cpl_free(fArray);

  /*
   * Powers
   */

  nrows = 7;

  table = cpl_table_new(nrows);
  cpl_table_new_column(table, "Int", CPL_TYPE_INT);
  cpl_table_new_column(table, "Float", CPL_TYPE_FLOAT);
  cpl_table_new_column(table, "Double", CPL_TYPE_DOUBLE);

  for (i = 0; i < nrows; i++) {
      cpl_table_set_int(table, "Int", i, i);
      cpl_table_set_float(table, "Float", i, i);
      cpl_table_set_double(table, "Double", i, i);
  }

  cpl_table_exponential_column(table, "Int", 2);
  cpl_table_exponential_column(table, "Float", 2);
  cpl_table_exponential_column(table, "Double", 2);

  pp = 1;
  for (i = 0; i < nrows; i++) {
      test_ivalue(pp, cpl_table_get_int(table, 
                      "Int", i, NULL), "Check expo Int... ");
      test_fvalue((float)pp, 0.00001, cpl_table_get_float(table, 
                      "Float", i, NULL), "Check expo Float... ");
      test_fvalue((float)pp, 0.00001, cpl_table_get_double(table, 
                      "Double", i, NULL), "Check expo Double... ");
      pp *= 2;
  }

  cpl_table_logarithm_column(table, "Int", 2);
  cpl_table_logarithm_column(table, "Float", 2);
  cpl_table_logarithm_column(table, "Double", 2);

  for (i = 0; i < nrows; i++) {
      test_ivalue(i, cpl_table_get_int(table, 
                     "Int", i, NULL), "Check log Int... ");
      test_fvalue((float)i, 0.00001, cpl_table_get_float(table, 
                     "Float", i, NULL), "Check log Float... ");
      test_fvalue((float)i, 0.00001, cpl_table_get_double(table, 
                     "Double", i, NULL), "Check log Double... ");
  }

  cpl_table_power_column(table, "Int", 2);
  cpl_table_power_column(table, "Float", 2);
  cpl_table_power_column(table, "Double", 2);

  for (i = 0; i < nrows; i++) {
      test_ivalue(i*i, cpl_table_get_int(table,
                     "Int", i, NULL), "Check pow Int... ");
      test_fvalue((float)i*i, 0.00001, cpl_table_get_float(table,
                     "Float", i, NULL), "Check pow Float... ");
      test_fvalue((float)i*i, 0.00001, cpl_table_get_double(table,
                     "Double", i, NULL), "Check pow Double... ");
  }

  cpl_table_power_column(table, "Int", 0.5);
  cpl_table_power_column(table, "Float", 0.5); 
  cpl_table_power_column(table, "Double", 0.5); 

  for (i = 0; i < nrows; i++) {
      test_ivalue(i, cpl_table_get_int(table,
                     "Int", i, NULL), "Check sqrt Int... ");
      test_fvalue((float)i, 0.00001, cpl_table_get_float(table,
                     "Float", i, NULL), "Check sqrt Float... ");
      test_fvalue((float)i, 0.00001, cpl_table_get_double(table,
                     "Double", i, NULL), "Check sqrt Double... ");
  }

  cpl_table_delete(table);


  /*
   * Testing the selection functions
   */

  nrows = 7;

  table = cpl_table_new(nrows);
  cpl_table_new_column(table, "Int", CPL_TYPE_INT);
  cpl_table_new_column(table, "String", CPL_TYPE_STRING);

  unit = "abcd\0efgh\0ijkl\0mnop\0qrst\0uvwx\0yz";

  for (i = 0; i < nrows; i++) {
       cpl_table_set_int(table, "Int", i, i);
       cpl_table_set_string(table, "String", i, unit + i*5);
  }

  cpl_table_duplicate_column(table, "Int2", table, "Int");
  cpl_table_multiply_columns(table, "Int2", "Int2");
  cpl_table_cast_column(table, "Int", "Float", CPL_TYPE_FLOAT);

#ifdef VERBOSE

  printf("\nThis is the test table:\n\n");
  cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);

  printf("\nNow erase all selected:\n\n");

#endif

  copia = cpl_table_duplicate(table);
  test_ivalue(7, cpl_table_count_selected(copia), "Check all selected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(0, cpl_table_get_nrow(copia), 
              "Check length erase all selected... ");
  cpl_table_delete(copia);

#ifdef VERBOSE

  printf("\nThis is the test table:\n\n");
  cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);

  printf("\nNow delete all Int >= Int2:\n\n");

#endif

  copia = cpl_table_duplicate(table);
  cpl_table_and_selected(copia, "Int", CPL_NOT_LESS_THAN, "Int2");
  test_ivalue(2, cpl_table_count_selected(copia), 
              "Check Int >= Int2 selected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(5, cpl_table_get_nrow(copia), 
              "Check length erase all Int >= Int2... ");
  cpl_table_delete(copia);

#ifdef VERBOSE

  printf("\nThis is the test table:\n\n");
  cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);

  printf("\nNow delete all Int > 3:\n\n");

#endif

  copia = cpl_table_duplicate(table);
  cpl_table_and_selected_int(copia, "Int", CPL_GREATER_THAN, 3);
  test_ivalue(3, cpl_table_count_selected(copia), 
              "Check Int > 3 selected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(4, cpl_table_get_nrow(copia), 
              "Check length erase all Int > 3... ");
  cpl_table_delete(copia);

#ifdef VERBOSE

  printf("\nThis is the test table:\n\n");
  cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);

  printf("\nNow delete all Int2 > Float:\n\n");

#endif

  copia = cpl_table_duplicate(table);
  cpl_table_and_selected(copia, "Int2", CPL_GREATER_THAN, "Float");
  test_ivalue(5, cpl_table_count_selected(copia), 
              "Check Int2 > Float selected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(2, cpl_table_get_nrow(copia), 
              "Check length erase all Int2 > Float... ");
  cpl_table_delete(copia);

#ifdef VERBOSE

  printf("\nThis is the test table:\n\n");
  cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);

  printf("\nNow delete all String == \"^[a-l].*\":\n\n");

#endif

  copia = cpl_table_duplicate(table);
  cpl_table_and_selected_string(copia, "String", CPL_EQUAL_TO, "^[a-l].*");
  test_ivalue(3, cpl_table_count_selected(copia), 
              "Check String == \"^[a-l].*\" selected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(4, cpl_table_get_nrow(copia), 
              "Check length erase all String == \"^[a-l].*\"... ");
  cpl_table_delete(copia);

#ifdef VERBOSE

  printf("\nThis is the test table:\n\n");
  cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);

  printf("\nNow delete all String > \"carlo\":\n\n");

#endif

  copia = cpl_table_duplicate(table);
  cpl_table_and_selected_string(copia, "String", CPL_GREATER_THAN, "carlo");
  test_ivalue(6, cpl_table_count_selected(copia), 
              "Check String > \"carlo\" selected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(1, cpl_table_get_nrow(copia), 
              "Check length erase all String > \"carlo\"... ");
  cpl_table_delete(copia);

#ifdef VERBOSE

  printf("\nThis is the test table:\n\n");
  cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);

  printf("\nNow delete all String > \"tattoo\" and Int == 3:\n\n");

#endif

  copia = cpl_table_duplicate(table);
  cpl_table_and_selected_string(copia, "String", CPL_GREATER_THAN, "tattoo");
  cpl_table_or_selected_int(copia, "Int", CPL_EQUAL_TO, 3);
  test_ivalue(3, cpl_table_count_selected(copia), 
              "Check String > \"tattoo\" and Int == 3 selected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(4, cpl_table_get_nrow(copia),
              "Check length erase all String > \"tattoo\" and Int == 3... ");
  cpl_table_delete(copia);

#ifdef VERBOSE

  printf("\nNow keep all String > \"tattoo\" and Int == 3:\n\n");

#endif

  copia = cpl_table_duplicate(table);
  cpl_table_and_selected_string(copia, "String", CPL_GREATER_THAN, "tattoo");
  cpl_table_or_selected_int(copia, "Int", CPL_EQUAL_TO, 3);
  cpl_table_not_selected(copia);
  test_ivalue(4, cpl_table_count_selected(copia), 
              "Check String > \"tattoo\" and Int == 3 rejected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(3, cpl_table_get_nrow(copia),
              "Check length keep all String > \"tattoo\" and Int == 3... ");
  cpl_table_delete(copia);

#ifdef VERBOSE

  printf("\nThis is the test table:\n\n");
  cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);

  printf("\nNow delete rows 0, 2, and 6:\n\n");

#endif

  copia = cpl_table_duplicate(table);
  cpl_table_unselect_all(copia);
  cpl_table_select_row(copia, 0);
  cpl_table_select_row(copia, 2);
  cpl_table_select_row(copia, 6);
  test_ivalue(3, cpl_table_count_selected(copia), 
              "Check rows 0, 2, and 6 selected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(4, cpl_table_get_nrow(copia),
              "Check length erase rows 0, 2, and 6... ");
  cpl_table_delete(copia);

#ifdef VERBOSE

  printf("\nNow keep rows 0, 2, and 6:\n\n");

#endif

  copia = cpl_table_duplicate(table);
  cpl_table_unselect_row(copia, 0);
  cpl_table_unselect_row(copia, 2);
  cpl_table_unselect_row(copia, 6);
  test_ivalue(4, cpl_table_count_selected(copia), 
              "Check rows 0, 2, and 6 rejected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(3, cpl_table_get_nrow(copia),
              "Check length erase rows 0, 2, and 6... ");
  cpl_table_delete(copia);

#ifdef VERBOSE

  printf("\nThis is the test table:\n\n");
  cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);

  printf("\nNow delete first 3 rows:\n\n");

#endif

  copia = cpl_table_duplicate(table);
  cpl_table_and_selected_window(copia, 0, 3);
  test_ivalue(3, cpl_table_count_selected(copia), 
              "Check first 3 rows selected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(4, cpl_table_get_nrow(copia),
              "Check length erase first 3 rows... ");
  cpl_table_delete(copia);

#ifdef VERBOSE

  printf("\nNow delete last 2 rows:\n\n");

#endif

  copia = cpl_table_duplicate(table);
  cpl_table_and_selected_window(copia, 5, 2);
  test_ivalue(2, cpl_table_count_selected(copia), 
              "Check last 2 rows selected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(5, cpl_table_get_nrow(copia),
              "Check length erase last 2 rows... ");
  cpl_table_delete(copia);

#ifdef VERBOSE

  printf("\nNow delete rows from 2 to 3:\n\n");

#endif

  copia = cpl_table_duplicate(table);
  cpl_table_and_selected_window(copia, 2, 2);
  test_ivalue(2, cpl_table_count_selected(copia), 
              "Check middle 2 rows selected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(5, cpl_table_get_nrow(copia),
              "Check length erase rows from 2 to 3... ");
  cpl_table_delete(copia);

#ifdef VERBOSE

  printf("\nNow delete rows from 1 to 3 and row 6:\n\n");

#endif

  copia = cpl_table_duplicate(table);
  cpl_table_and_selected_window(copia, 1, 3);
  cpl_table_or_selected_window(copia, 6, 1);
  test_ivalue(4, cpl_table_count_selected(copia), 
              "Check rows 1 to 3 and row 6 rejected... ");
  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(3, cpl_table_get_nrow(copia),
              "Check length erase rows from 1 to 3 and row 6... ");
  cpl_table_delete(copia);

  /* Erase only invalid elements */
  copia = cpl_table_duplicate(table);
  for (i = 0; i < nrows; i++) {
      cpl_table_set_invalid(copia, "Int", i);
  }

  cpl_table_unselect_row(copia, nrows-1);

  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(1, cpl_table_get_nrow(copia),
              "Check length erase last row, only invalid values... ");
  cpl_table_delete(copia);

  /* Erase array column with valid/invalid values */
  copia = cpl_table_duplicate(table);

  cpl_table_cast_column(copia, "Int", "Double", CPL_TYPE_DOUBLE);

  test(cpl_table_new_column_array(copia, "ADouble", 
                                  CPL_TYPE_DOUBLE | CPL_TYPE_POINTER, 2),
                                  "Creating the ArrayDouble column... ");

  array = cpl_array_new(2, CPL_TYPE_DOUBLE);
  test(cpl_table_set_array(copia, "ADouble", 1, array),
       "Set a valid array to ADouble 1... ");
  test(cpl_table_set_array(copia, "ADouble", 2, array),
       "Set a valid array to ADouble 2... ");
  cpl_array_delete(array);

  cpl_table_unselect_row(copia, 0);
  cpl_table_unselect_row(copia, 2);
  cpl_table_set_invalid(copia, "Int", 6);
  cpl_table_set_invalid(copia, "Int2", 0);
  cpl_table_set_invalid(copia, "Int2", 1);
  cpl_table_set_invalid(copia, "Double", 0);
  cpl_table_set_invalid(copia, "Double", 1);

  cpl_table_erase_selected(copia);
#ifdef VERBOSE
  cpl_table_dump(copia, 0, cpl_table_get_nrow(copia), NULL);
#endif
  test_ivalue(2, cpl_table_get_nrow(copia),
              "Check length erase valid/invalid values... ");
  test_ivalue(0, cpl_table_is_valid(copia, "Int2", 0), 
                    "Check that first element of \"Int2\" is still NULL... ");
  test_ivalue(1, cpl_table_is_valid(copia, "Int2", 1), 
                    "Check that first element of \"Int2\" is now valid... ");

  cpl_table_unselect_row(copia, 0);
  cpl_table_unselect_row(copia, 1);
  cpl_table_erase_selected(copia);
  test_ivalue(2, cpl_table_count_selected(copia),
              "Check that rows are selected... ");

  cpl_table_delete(copia);

  cpl_table_delete(table);



  table = cpl_table_new(4);
  cpl_table_new_column(table, "S", CPL_TYPE_STRING);
  cpl_table_new_column(table, "D", CPL_TYPE_DOUBLE);

  cpl_table_set_double(table, "D", 0, 43.04);
  cpl_table_set_double(table, "D", 1, 43.04);
  cpl_table_set_double(table, "D", 2, 43.04);
  cpl_table_set_double(table, "D", 3, 43.04);
  cpl_table_set_invalid(table, "D", 3);

  cpl_table_set_string(table, "S", 0, "type");
  cpl_table_set_string(table, "S", 1, "type");
  cpl_table_set_string(table, "S", 2, "type");
  cpl_table_set_string(table, "S", 3, "type");
  cpl_table_set_invalid(table, "S", 1);

#ifdef VERBOSE
  cpl_table_dump(table, 0, 4, stdout);
#endif

  cpl_table_select_all(table);
  test_ivalue(4, cpl_table_count_selected(table), "A...");
  cpl_table_and_selected_invalid(table, "D");
  test_ivalue(1, cpl_table_count_selected(table), "B...");

  cpl_table_select_all(table);
  test_ivalue(4, cpl_table_count_selected(table), "C...");

//fails:  cpl_table_and_selected_invalid(table, "S");
  uves_table_and_selected_invalid(table, "S");

  test_ivalue(1, cpl_table_count_selected(table), "D...");

  cpl_table_delete(table);


  /*
   * Test case: dividing a double column by integer
   */

  nrows = 100;

  table = cpl_table_new(nrows);
  cpl_table_new_column(table, "Int", CPL_TYPE_INT);

  for (i = 0; i < nrows; i++)
       cpl_table_set_int(table, "Int", i, i + 1);

  cpl_table_cast_column(table, "Int", "Double", CPL_TYPE_DOUBLE);

  test(cpl_table_divide_columns(table, "Double", "Int"), 
                     "Divide double column with integer column... ");

  for (i = 0; i < nrows; i++) {
    sprintf(message, "Check element %d of result column... ", i);
    test_fvalue(1.0, 0.00001, cpl_table_get_double(table, "Double", i, NULL), 
                message);
  }

#ifdef VERBOSE
  cpl_table_dump(table, 0, cpl_table_get_nrow(table), NULL);
#endif

  cpl_table_delete(table);

/*
  table = cpl_table_load("/home/cizzo/qfits/qfits/test/asciitable.tfits", 1, 1);
  table = cpl_table_load("/home/cizzo/qfits/qfits/test/bintable.tfits", 1, 1);

  names[0] = "IDENT";
  names[1] = "Mag";
  reverse[0] = 0;
  reverse[1] = 1;
  uves_table_sort(table, names, 2, reverse);
 
  cpl_table_dump_structure(table);
  cpl_table_dump(table, 0, cpl_table_get_nrow(table));
*/
 cleanup:
  return cpl_error_get_code();

}



/*----------------------------------------------------------------------------*/
/**
  @brief   Test utility functions
**/
/*----------------------------------------------------------------------------*/

int main(void)
{
    cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_WARNING);

    cpl_test_eq(0, table_erase_selected());
    uves_find_property_test();
    uves_average_reject_test();
    uves_polynomial_fit_2d_test();
   
    //uves_filter_cosmic_test();

    return cpl_test_end(0);
}

/**@}*/
