"Fossies" - the Fresh Open Source Software Archive

Member "cfitsio-4.0.0/getcoluj.c" (20 May 2021, 148281 Bytes) of package /linux/misc/cfitsio-4.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "getcoluj.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 3440_vs_3450.

    1 /*  This file, getcoluj.c, contains routines that read data elements from  */
    2 /*  a FITS image or table, with unsigned long data type.                   */
    3 
    4 /*  The FITSIO software was written by William Pence at the High Energy    */
    5 /*  Astrophysic Science Archive Research Center (HEASARC) at the NASA      */
    6 /*  Goddard Space Flight Center.                                           */
    7 
    8 #include <math.h>
    9 #include <stdlib.h>
   10 #include <limits.h>
   11 #include <string.h>
   12 #include "fitsio2.h"
   13 
   14 /*--------------------------------------------------------------------------*/
   15 int ffgpvuj(fitsfile *fptr,   /* I - FITS file pointer                       */
   16             long  group,      /* I - group to read (1 = 1st group)           */
   17             LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
   18             LONGLONG  nelem,      /* I - number of values to read                */
   19    unsigned long  nulval,     /* I - value for undefined pixels              */
   20    unsigned long  *array,     /* O - array of values that are returned       */
   21             int  *anynul,     /* O - set to 1 if any values are null; else 0 */
   22             int  *status)     /* IO - error status                           */
   23 /*
   24   Read an array of values from the primary array. Data conversion
   25   and scaling will be performed if necessary (e.g, if the datatype of
   26   the FITS array is not the same as the array being read).
   27   Undefined elements will be set equal to NULVAL, unless NULVAL=0
   28   in which case no checking for undefined values will be performed.
   29   ANYNUL is returned with a value of .true. if any pixels are undefined.
   30 */
   31 {
   32     long row;
   33     char cdummy;
   34     int nullcheck = 1;
   35     unsigned long nullvalue;
   36 
   37     if (fits_is_compressed_image(fptr, status))
   38     {
   39         /* this is a compressed image in a binary table */
   40         nullvalue = nulval;  /* set local variable */
   41 
   42         fits_read_compressed_pixels(fptr, TULONG, firstelem, nelem,
   43             nullcheck, &nullvalue, array, NULL, anynul, status);
   44         return(*status);
   45     }
   46 
   47     /*
   48       the primary array is represented as a binary table:
   49       each group of the primary array is a row in the table,
   50       where the first column contains the group parameters
   51       and the second column contains the image itself.
   52     */
   53 
   54     row=maxvalue(1,group);
   55 
   56     ffgcluj(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
   57                array, &cdummy, anynul, status);
   58     return(*status);
   59 }
   60 /*--------------------------------------------------------------------------*/
   61 int ffgpfuj(fitsfile *fptr,   /* I - FITS file pointer                       */
   62             long  group,      /* I - group to read (1 = 1st group)           */
   63             LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
   64             LONGLONG  nelem,      /* I - number of values to read                */
   65    unsigned long  *array,     /* O - array of values that are returned       */
   66             char *nularray,   /* O - array of null pixel flags               */
   67             int  *anynul,     /* O - set to 1 if any values are null; else 0 */
   68             int  *status)     /* IO - error status                           */
   69 /*
   70   Read an array of values from the primary array. Data conversion
   71   and scaling will be performed if necessary (e.g, if the datatype of
   72   the FITS array is not the same as the array being read).
   73   Any undefined pixels in the returned array will be set = 0 and the 
   74   corresponding nularray value will be set = 1.
   75   ANYNUL is returned with a value of .true. if any pixels are undefined.
   76 */
   77 {
   78     long row;
   79     int nullcheck = 2;
   80 
   81     if (fits_is_compressed_image(fptr, status))
   82     {
   83         /* this is a compressed image in a binary table */
   84 
   85         fits_read_compressed_pixels(fptr, TULONG, firstelem, nelem,
   86             nullcheck, NULL, array, nularray, anynul, status);
   87         return(*status);
   88     }
   89 
   90     /*
   91       the primary array is represented as a binary table:
   92       each group of the primary array is a row in the table,
   93       where the first column contains the group parameters
   94       and the second column contains the image itself.
   95     */
   96 
   97     row=maxvalue(1,group);
   98 
   99     ffgcluj(fptr, 2, row, firstelem, nelem, 1, 2, 0L,
  100                array, nularray, anynul, status);
  101     return(*status);
  102 }
  103 /*--------------------------------------------------------------------------*/
  104 int ffg2duj(fitsfile *fptr,  /* I - FITS file pointer                       */
  105            long  group,     /* I - group to read (1 = 1st group)           */
  106   unsigned long  nulval,    /* set undefined pixels equal to this          */
  107            LONGLONG  ncols,     /* I - number of pixels in each row of array   */
  108            LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
  109            LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
  110   unsigned long  *array,    /* O - array to be filled and returned         */
  111            int  *anynul,    /* O - set to 1 if any values are null; else 0 */
  112            int  *status)    /* IO - error status                           */
  113 /*
  114   Read an entire 2-D array of values to the primary array. Data conversion
  115   and scaling will be performed if necessary (e.g, if the datatype of the
  116   FITS array is not the same as the array being read).  Any null
  117   values in the array will be set equal to the value of nulval, unless
  118   nulval = 0 in which case no null checking will be performed.
  119 */
  120 {
  121     /* call the 3D reading routine, with the 3rd dimension = 1 */
  122 
  123     ffg3duj(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
  124            anynul, status);
  125 
  126     return(*status);
  127 }
  128 /*--------------------------------------------------------------------------*/
  129 int ffg3duj(fitsfile *fptr,  /* I - FITS file pointer                       */
  130            long  group,     /* I - group to read (1 = 1st group)           */
  131   unsigned long  nulval,    /* set undefined pixels equal to this          */
  132            LONGLONG  ncols,     /* I - number of pixels in each row of array   */
  133            LONGLONG  nrows,     /* I - number of rows in each plane of array   */
  134            LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
  135            LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
  136            LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
  137   unsigned long  *array,    /* O - array to be filled and returned         */
  138            int  *anynul,    /* O - set to 1 if any values are null; else 0 */
  139            int  *status)    /* IO - error status                           */
  140 /*
  141   Read an entire 3-D array of values to the primary array. Data conversion
  142   and scaling will be performed if necessary (e.g, if the datatype of the
  143   FITS array is not the same as the array being read).  Any null
  144   values in the array will be set equal to the value of nulval, unless
  145   nulval = 0 in which case no null checking will be performed.
  146 */
  147 {
  148     long tablerow, ii, jj;
  149     char cdummy;
  150     int nullcheck = 1;
  151     long inc[] = {1,1,1};
  152     LONGLONG fpixel[] = {1,1,1}, nfits, narray;
  153     LONGLONG lpixel[3];
  154     unsigned long nullvalue;
  155 
  156     if (fits_is_compressed_image(fptr, status))
  157     {
  158         /* this is a compressed image in a binary table */
  159 
  160         lpixel[0] = ncols;
  161         lpixel[1] = nrows;
  162         lpixel[2] = naxis3;
  163         nullvalue = nulval;  /* set local variable */
  164 
  165         fits_read_compressed_img(fptr, TULONG, fpixel, lpixel, inc,
  166             nullcheck, &nullvalue, array, NULL, anynul, status);
  167         return(*status);
  168     }
  169 
  170     /*
  171       the primary array is represented as a binary table:
  172       each group of the primary array is a row in the table,
  173       where the first column contains the group parameters
  174       and the second column contains the image itself.
  175     */
  176     tablerow=maxvalue(1,group);
  177 
  178     if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
  179     {
  180        /* all the image pixels are contiguous, so read all at once */
  181        ffgcluj(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
  182                array, &cdummy, anynul, status);
  183        return(*status);
  184     }
  185 
  186     if (ncols < naxis1 || nrows < naxis2)
  187        return(*status = BAD_DIMEN);
  188 
  189     nfits = 1;   /* next pixel in FITS image to read */
  190     narray = 0;  /* next pixel in output array to be filled */
  191 
  192     /* loop over naxis3 planes in the data cube */
  193     for (jj = 0; jj < naxis3; jj++)
  194     {
  195       /* loop over the naxis2 rows in the FITS image, */
  196       /* reading naxis1 pixels to each row            */
  197 
  198       for (ii = 0; ii < naxis2; ii++)
  199       {
  200        if (ffgcluj(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
  201           &array[narray], &cdummy, anynul, status) > 0)
  202           return(*status);
  203 
  204        nfits += naxis1;
  205        narray += ncols;
  206       }
  207       narray += (nrows - naxis2) * ncols;
  208     }
  209 
  210     return(*status);
  211 }
  212 /*--------------------------------------------------------------------------*/
  213 int ffgsvuj(fitsfile *fptr, /* I - FITS file pointer                         */
  214            int  colnum,    /* I - number of the column to read (1 = 1st)    */
  215            int naxis,      /* I - number of dimensions in the FITS array    */
  216            long  *naxes,   /* I - size of each dimension                    */
  217            long  *blc,     /* I - 'bottom left corner' of the subsection    */
  218            long  *trc,     /* I - 'top right corner' of the subsection      */
  219            long  *inc,     /* I - increment to be applied in each dimension */
  220   unsigned long nulval,    /* I - value to set undefined pixels             */
  221   unsigned long *array,    /* O - array to be filled and returned           */
  222            int  *anynul,   /* O - set to 1 if any values are null; else 0   */
  223            int  *status)   /* IO - error status                             */
  224 /*
  225   Read a subsection of data values from an image or a table column.
  226   This routine is set up to handle a maximum of nine dimensions.
  227 */
  228 {
  229     long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
  230     long str[9],stp[9],incr[9];
  231     long nelem, nultyp, ninc, numcol;
  232     LONGLONG felem, dsize[10], blcll[9], trcll[9];
  233     int hdutype, anyf;
  234     char ldummy, msg[FLEN_ERRMSG];
  235     int nullcheck = 1;
  236     unsigned long nullvalue;
  237 
  238     if (naxis < 1 || naxis > 9)
  239     {
  240         snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvuj is out of range", naxis);
  241         ffpmsg(msg);
  242         return(*status = BAD_DIMEN);
  243     }
  244 
  245     if (fits_is_compressed_image(fptr, status))
  246     {
  247         /* this is a compressed image in a binary table */
  248 
  249         for (ii=0; ii < naxis; ii++) {
  250         blcll[ii] = blc[ii];
  251         trcll[ii] = trc[ii];
  252     }
  253 
  254         nullvalue = nulval;  /* set local variable */
  255 
  256         fits_read_compressed_img(fptr, TULONG, blcll, trcll, inc,
  257             nullcheck, &nullvalue, array, NULL, anynul, status);
  258         return(*status);
  259     }
  260 
  261 /*
  262     if this is a primary array, then the input COLNUM parameter should
  263     be interpreted as the row number, and we will alway read the image
  264     data from column 2 (any group parameters are in column 1).
  265 */
  266     if (ffghdt(fptr, &hdutype, status) > 0)
  267         return(*status);
  268 
  269     if (hdutype == IMAGE_HDU)
  270     {
  271         /* this is a primary array, or image extension */
  272         if (colnum == 0)
  273         {
  274             rstr = 1;
  275             rstp = 1;
  276         }
  277         else
  278         {
  279             rstr = colnum;
  280             rstp = colnum;
  281         }
  282         rinc = 1;
  283         numcol = 2;
  284     }
  285     else
  286     {
  287         /* this is a table, so the row info is in the (naxis+1) elements */
  288         rstr = blc[naxis];
  289         rstp = trc[naxis];
  290         rinc = inc[naxis];
  291         numcol = colnum;
  292     }
  293 
  294     nultyp = 1;
  295     if (anynul)
  296         *anynul = FALSE;
  297 
  298     i0 = 0;
  299     for (ii = 0; ii < 9; ii++)
  300     {
  301         str[ii] = 1;
  302         stp[ii] = 1;
  303         incr[ii] = 1;
  304         dsize[ii] = 1;
  305     }
  306 
  307     for (ii = 0; ii < naxis; ii++)
  308     {
  309       if (trc[ii] < blc[ii])
  310       {
  311         snprintf(msg, FLEN_ERRMSG,"ffgsvuj: illegal range specified for axis %ld", ii + 1);
  312         ffpmsg(msg);
  313         return(*status = BAD_PIX_NUM);
  314       }
  315 
  316       str[ii] = blc[ii];
  317       stp[ii] = trc[ii];
  318       incr[ii] = inc[ii];
  319       dsize[ii + 1] = dsize[ii] * naxes[ii];
  320     }
  321 
  322     if (naxis == 1 && naxes[0] == 1)
  323     {
  324       /* This is not a vector column, so read all the rows at once */
  325       nelem = (rstp - rstr) / rinc + 1;
  326       ninc = rinc;
  327       rstp = rstr;
  328     }
  329     else
  330     {
  331       /* have to read each row individually, in all dimensions */
  332       nelem = (stp[0] - str[0]) / inc[0] + 1;
  333       ninc = incr[0];
  334     }
  335 
  336     for (row = rstr; row <= rstp; row += rinc)
  337     {
  338      for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
  339      {
  340       for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
  341       {
  342        for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
  343        {
  344         for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
  345         {
  346          for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
  347          {
  348           for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
  349           {
  350            for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
  351            {
  352             for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
  353             {
  354               felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
  355                              (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
  356                              (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
  357                              (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
  358 
  359               if ( ffgcluj(fptr, numcol, row, felem, nelem, ninc, nultyp,
  360                    nulval, &array[i0], &ldummy, &anyf, status) > 0)
  361                    return(*status);
  362 
  363               if (anyf && anynul)
  364                   *anynul = TRUE;
  365 
  366               i0 += nelem;
  367             }
  368            }
  369           }
  370          }
  371         }
  372        }
  373       }
  374      }
  375     }
  376     return(*status);
  377 }
  378 /*--------------------------------------------------------------------------*/
  379 int ffgsfuj(fitsfile *fptr, /* I - FITS file pointer                         */
  380            int  colnum,    /* I - number of the column to read (1 = 1st)    */
  381            int naxis,      /* I - number of dimensions in the FITS array    */
  382            long  *naxes,   /* I - size of each dimension                    */
  383            long  *blc,     /* I - 'bottom left corner' of the subsection    */
  384            long  *trc,     /* I - 'top right corner' of the subsection      */
  385            long  *inc,     /* I - increment to be applied in each dimension */
  386   unsigned long *array,    /* O - array to be filled and returned           */
  387            char *flagval,  /* O - set to 1 if corresponding value is null   */
  388            int  *anynul,   /* O - set to 1 if any values are null; else 0   */
  389            int  *status)   /* IO - error status                             */
  390 /*
  391   Read a subsection of data values from an image or a table column.
  392   This routine is set up to handle a maximum of nine dimensions.
  393 */
  394 {
  395     long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
  396     long str[9],stp[9],incr[9],dsize[10];
  397     LONGLONG blcll[9], trcll[9];
  398     long felem, nelem, nultyp, ninc, numcol;
  399     unsigned long nulval = 0;
  400     int hdutype, anyf;
  401     char msg[FLEN_ERRMSG];
  402     int nullcheck = 2;
  403 
  404     if (naxis < 1 || naxis > 9)
  405     {
  406         snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
  407         ffpmsg(msg);
  408         return(*status = BAD_DIMEN);
  409     }
  410 
  411     if (fits_is_compressed_image(fptr, status))
  412     {
  413         /* this is a compressed image in a binary table */
  414 
  415         for (ii=0; ii < naxis; ii++) {
  416         blcll[ii] = blc[ii];
  417         trcll[ii] = trc[ii];
  418     }
  419 
  420         fits_read_compressed_img(fptr, TULONG, blcll, trcll, inc,
  421             nullcheck, NULL, array, flagval, anynul, status);
  422         return(*status);
  423     }
  424 
  425 /*
  426     if this is a primary array, then the input COLNUM parameter should
  427     be interpreted as the row number, and we will alway read the image
  428     data from column 2 (any group parameters are in column 1).
  429 */
  430     if (ffghdt(fptr, &hdutype, status) > 0)
  431         return(*status);
  432 
  433     if (hdutype == IMAGE_HDU)
  434     {
  435         /* this is a primary array, or image extension */
  436         if (colnum == 0)
  437         {
  438             rstr = 1;
  439             rstp = 1;
  440         }
  441         else
  442         {
  443             rstr = colnum;
  444             rstp = colnum;
  445         }
  446         rinc = 1;
  447         numcol = 2;
  448     }
  449     else
  450     {
  451         /* this is a table, so the row info is in the (naxis+1) elements */
  452         rstr = blc[naxis];
  453         rstp = trc[naxis];
  454         rinc = inc[naxis];
  455         numcol = colnum;
  456     }
  457 
  458     nultyp = 2;
  459     if (anynul)
  460         *anynul = FALSE;
  461 
  462     i0 = 0;
  463     for (ii = 0; ii < 9; ii++)
  464     {
  465         str[ii] = 1;
  466         stp[ii] = 1;
  467         incr[ii] = 1;
  468         dsize[ii] = 1;
  469     }
  470 
  471     for (ii = 0; ii < naxis; ii++)
  472     {
  473       if (trc[ii] < blc[ii])
  474       {
  475         snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1);
  476         ffpmsg(msg);
  477         return(*status = BAD_PIX_NUM);
  478       }
  479 
  480       str[ii] = blc[ii];
  481       stp[ii] = trc[ii];
  482       incr[ii] = inc[ii];
  483       dsize[ii + 1] = dsize[ii] * naxes[ii];
  484     }
  485 
  486     if (naxis == 1 && naxes[0] == 1)
  487     {
  488       /* This is not a vector column, so read all the rows at once */
  489       nelem = (rstp - rstr) / rinc + 1;
  490       ninc = rinc;
  491       rstp = rstr;
  492     }
  493     else
  494     {
  495       /* have to read each row individually, in all dimensions */
  496       nelem = (stp[0] - str[0]) / inc[0] + 1;
  497       ninc = incr[0];
  498     }
  499 
  500     for (row = rstr; row <= rstp; row += rinc)
  501     {
  502      for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
  503      {
  504       for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
  505       {
  506        for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
  507        {
  508         for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
  509         {
  510          for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
  511          {
  512           for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
  513           {
  514            for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
  515            {
  516             for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
  517             {
  518               felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
  519                              (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
  520                              (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
  521                              (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
  522 
  523               if ( ffgcluj(fptr, numcol, row, felem, nelem, ninc, nultyp,
  524                    nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
  525                    return(*status);
  526 
  527               if (anyf && anynul)
  528                   *anynul = TRUE;
  529 
  530               i0 += nelem;
  531             }
  532            }
  533           }
  534          }
  535         }
  536        }
  537       }
  538      }
  539     }
  540     return(*status);
  541 }
  542 /*--------------------------------------------------------------------------*/
  543 int ffggpuj(fitsfile *fptr,   /* I - FITS file pointer                       */
  544             long  group,      /* I - group to read (1 = 1st group)           */
  545             long  firstelem,  /* I - first vector element to read (1 = 1st)  */
  546             long  nelem,      /* I - number of values to read                */
  547    unsigned long  *array,     /* O - array of values that are returned       */
  548             int  *status)     /* IO - error status                           */
  549 /*
  550   Read an array of group parameters from the primary array. Data conversion
  551   and scaling will be performed if necessary (e.g, if the datatype of
  552   the FITS array is not the same as the array being read).
  553 */
  554 {
  555     long row;
  556     int idummy;
  557     char cdummy;
  558     /*
  559       the primary array is represented as a binary table:
  560       each group of the primary array is a row in the table,
  561       where the first column contains the group parameters
  562       and the second column contains the image itself.
  563     */
  564 
  565     row=maxvalue(1,group);
  566 
  567     ffgcluj(fptr, 1, row, firstelem, nelem, 1, 1, 0L,
  568                array, &cdummy, &idummy, status);
  569     return(*status);
  570 }
  571 /*--------------------------------------------------------------------------*/
  572 int ffgcvuj(fitsfile *fptr,   /* I - FITS file pointer                       */
  573            int  colnum,      /* I - number of column to read (1 = 1st col)  */
  574            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
  575            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
  576            LONGLONG  nelem,      /* I - number of values to read                */
  577   unsigned long  nulval,     /* I - value for null pixels                   */
  578   unsigned long *array,      /* O - array of values that are read           */
  579            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
  580            int  *status)     /* IO - error status                           */
  581 /*
  582   Read an array of values from a column in the current FITS HDU. Automatic
  583   datatype conversion will be performed if the datatype of the column does not
  584   match the datatype of the array parameter. The output values will be scaled 
  585   by the FITS TSCALn and TZEROn values if these values have been defined.
  586   Any undefined pixels will be set equal to the value of 'nulval' unless
  587   nulval = 0 in which case no checks for undefined pixels will be made.
  588 */
  589 {
  590     char cdummy;
  591 
  592     ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
  593            array, &cdummy, anynul, status);
  594     return(*status);
  595 }
  596 /*--------------------------------------------------------------------------*/
  597 int ffgcfuj(fitsfile *fptr,   /* I - FITS file pointer                       */
  598            int  colnum,      /* I - number of column to read (1 = 1st col)  */
  599            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
  600            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
  601            LONGLONG  nelem,      /* I - number of values to read                */
  602   unsigned long  *array,     /* O - array of values that are read           */
  603            char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
  604            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
  605            int  *status)     /* IO - error status                           */
  606 /*
  607   Read an array of values from a column in the current FITS HDU. Automatic
  608   datatype conversion will be performed if the datatype of the column does not
  609   match the datatype of the array parameter. The output values will be scaled 
  610   by the FITS TSCALn and TZEROn values if these values have been defined.
  611   Nularray will be set = 1 if the corresponding array pixel is undefined, 
  612   otherwise nularray will = 0.
  613 */
  614 {
  615     unsigned long dummy = 0;
  616 
  617     ffgcluj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
  618            array, nularray, anynul, status);
  619     return(*status);
  620 }
  621 /*--------------------------------------------------------------------------*/
  622 int ffgcluj(fitsfile *fptr,   /* I - FITS file pointer                       */
  623             int  colnum,      /* I - number of column to read (1 = 1st col)  */
  624             LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
  625             LONGLONG  firstelem, /* I - first vector element to read (1 = 1st)  */
  626             LONGLONG  nelem,      /* I - number of values to read                */
  627             long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
  628             int   nultyp,     /* I - null value handling code:               */
  629                               /*     1: set undefined pixels = nulval        */
  630                               /*     2: set nularray=1 for undefined pixels  */
  631    unsigned long  nulval,     /* I - value for null pixels if nultyp = 1     */
  632    unsigned long  *array,     /* O - array of values that are read           */
  633             char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
  634             int  *anynul,     /* O - set to 1 if any values are null; else 0 */
  635             int  *status)     /* IO - error status                           */
  636 /*
  637   Read an array of values from a column in the current FITS HDU.
  638   The column number may refer to a real column in an ASCII or binary table, 
  639   or it may refer be a virtual column in a 1 or more grouped FITS primary
  640   array or image extension.  FITSIO treats a primary array as a binary table
  641   with 2 vector columns: the first column contains the group parameters (often
  642   with length = 0) and the second column contains the array of image pixels.
  643   Each row of the table represents a group in the case of multigroup FITS
  644   images.
  645 
  646   The output array of values will be converted from the datatype of the column 
  647   and will be scaled by the FITS TSCALn and TZEROn values if necessary.
  648 */
  649 {
  650     double scale, zero, power = 1., dtemp;
  651     int tcode, maxelem2, hdutype, xcode, decimals;
  652     long twidth, incre;
  653     long ii, xwidth, ntodo;
  654     int nulcheck;
  655     LONGLONG repeat, startpos, elemnum, readptr, tnull;
  656     LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
  657     char tform[20];
  658     char message[FLEN_ERRMSG];
  659     char snull[20];   /*  the FITS null value if reading from ASCII table  */
  660 
  661     double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
  662     void *buffer;
  663 
  664     if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
  665         return(*status);
  666 
  667     buffer = cbuff;
  668 
  669     if (anynul)
  670         *anynul = 0;
  671 
  672     if (nultyp == 2)
  673         memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
  674 
  675     /*---------------------------------------------------*/
  676     /*  Check input and get parameters about the column: */
  677     /*---------------------------------------------------*/
  678     if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
  679          tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
  680          &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
  681          return(*status);
  682     maxelem = maxelem2;
  683 
  684     incre *= elemincre;   /* multiply incre to just get every nth pixel */
  685 
  686     if (tcode == TSTRING)    /* setup for ASCII tables */
  687     {
  688       /* get the number of implied decimal places if no explicit decmal point */
  689       ffasfm(tform, &xcode, &xwidth, &decimals, status); 
  690       for(ii = 0; ii < decimals; ii++)
  691         power *= 10.;
  692     }
  693     /*------------------------------------------------------------------*/
  694     /*  Decide whether to check for null values in the input FITS file: */
  695     /*------------------------------------------------------------------*/
  696     nulcheck = nultyp; /* by default check for null values in the FITS file */
  697 
  698     if (nultyp == 1 && nulval == 0)
  699        nulcheck = 0;    /* calling routine does not want to check for nulls */
  700 
  701     else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
  702             tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
  703             nulcheck = 0;            /* then do not check for null values. */
  704 
  705     else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
  706             nulcheck = 0;            /* Impossible null value */
  707 
  708     else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
  709             nulcheck = 0;            /* Impossible null value */
  710 
  711     else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
  712          nulcheck = 0;
  713 
  714     /*----------------------------------------------------------------------*/
  715     /*  If FITS column and output data array have same datatype, then we do */
  716     /*  not need to use a temporary buffer to store intermediate datatype.  */
  717     /*----------------------------------------------------------------------*/
  718     if ((tcode == TLONG) && (LONGSIZE == 32))  /* Special Case:                        */
  719     {                             /* no type convertion required, so read */
  720                                   /* data directly into output buffer.    */
  721 
  722         if (nelem < (LONGLONG)INT32_MAX/4) {
  723             maxelem = nelem;
  724         } else {
  725             maxelem = INT32_MAX/4;
  726         }
  727     }
  728 
  729     /*---------------------------------------------------------------------*/
  730     /*  Now read the pixels from the FITS column. If the column does not   */
  731     /*  have the same datatype as the output array, then we have to read   */
  732     /*  the raw values into a temporary buffer (of limited size).  In      */
  733     /*  the case of a vector colum read only 1 vector of values at a time  */
  734     /*  then skip to the next row if more values need to be read.          */
  735     /*  After reading the raw values, then call the fffXXYY routine to (1) */
  736     /*  test for undefined values, (2) convert the datatype if necessary,  */
  737     /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
  738     /*  scaling parameters.                                                */
  739     /*---------------------------------------------------------------------*/
  740     remain = nelem;           /* remaining number of values to read */
  741     next = 0;                 /* next element in array to be read   */
  742     rownum = 0;               /* row number, relative to firstrow   */
  743 
  744     while (remain)
  745     {
  746         /* limit the number of pixels to read at one time to the number that
  747            will fit in the buffer or to the number of pixels that remain in
  748            the current vector, which ever is smaller.
  749         */
  750         ntodo = (long) minvalue(remain, maxelem);      
  751         ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
  752 
  753         readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
  754 
  755         switch (tcode) 
  756         {
  757             case (TLONG):
  758           if (LONGSIZE == 32) {
  759                 ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next],
  760                        status);
  761                 fffi4u4((INT32BIT *) &array[next], ntodo, scale, zero,
  762                          nulcheck, (INT32BIT) tnull, nulval, &nularray[next],
  763                          anynul, &array[next], status);
  764           } else { /* case where sizeof(long) = 8 */
  765                 ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
  766                        status);
  767                 fffi4u4((INT32BIT *) buffer, ntodo, scale, zero,
  768                          nulcheck, (INT32BIT) tnull, nulval, &nularray[next],
  769                          anynul, &array[next], status);
  770           }
  771 
  772 
  773                 break;
  774             case (TLONGLONG):
  775 
  776                 ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
  777                 fffi8u4( (LONGLONG *) buffer, ntodo, scale, zero, 
  778                            nulcheck, tnull, nulval, &nularray[next], 
  779                             anynul, &array[next], status);
  780                 break;
  781             case (TBYTE):
  782                 ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
  783                        status);
  784                 fffi1u4((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
  785                      (unsigned char) tnull, nulval, &nularray[next], anynul, 
  786                      &array[next], status);
  787                 break;
  788             case (TSHORT):
  789                 ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
  790                 fffi2u4((short  *) buffer, ntodo, scale, zero, nulcheck, 
  791                       (short) tnull, nulval, &nularray[next], anynul, 
  792                       &array[next], status);
  793                 break;
  794             case (TFLOAT):
  795                 ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
  796                 fffr4u4((float  *) buffer, ntodo, scale, zero, nulcheck, 
  797                        nulval, &nularray[next], anynul, 
  798                        &array[next], status);
  799                 break;
  800             case (TDOUBLE):
  801                 ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
  802                 fffr8u4((double *) buffer, ntodo, scale, zero, nulcheck, 
  803                           nulval, &nularray[next], anynul, 
  804                           &array[next], status);
  805                 break;
  806             case (TSTRING):
  807                 ffmbyt(fptr, readptr, REPORT_EOF, status);
  808        
  809                 if (incre == twidth)    /* contiguous bytes */
  810                      ffgbyt(fptr, ntodo * twidth, buffer, status);
  811                 else
  812                      ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
  813                                status);
  814 
  815                 fffstru4((char *) buffer, ntodo, scale, zero, twidth, power,
  816                      nulcheck, snull, nulval, &nularray[next], anynul,
  817                      &array[next], status);
  818                 break;
  819 
  820             default:  /*  error trap for invalid column format */
  821                 snprintf(message,FLEN_ERRMSG, 
  822                    "Cannot read numbers from column %d which has format %s",
  823                     colnum, tform);
  824                 ffpmsg(message);
  825                 if (hdutype == ASCII_TBL)
  826                     return(*status = BAD_ATABLE_FORMAT);
  827                 else
  828                     return(*status = BAD_BTABLE_FORMAT);
  829 
  830         } /* End of switch block */
  831 
  832         /*-------------------------*/
  833         /*  Check for fatal error  */
  834         /*-------------------------*/
  835         if (*status > 0)  /* test for error during previous read operation */
  836         {
  837       dtemp = (double) next;
  838           if (hdutype > 0)
  839             snprintf(message,FLEN_ERRMSG,
  840             "Error reading elements %.0f thru %.0f from column %d (ffgcluj).",
  841               dtemp+1., dtemp+ntodo, colnum);
  842           else
  843             snprintf(message,FLEN_ERRMSG,
  844             "Error reading elements %.0f thru %.0f from image (ffgcluj).",
  845               dtemp+1., dtemp+ntodo);
  846 
  847           ffpmsg(message);
  848           return(*status);
  849         }
  850 
  851         /*--------------------------------------------*/
  852         /*  increment the counters for the next loop  */
  853         /*--------------------------------------------*/
  854         remain -= ntodo;
  855         if (remain)
  856         {
  857             next += ntodo;
  858             elemnum = elemnum + (ntodo * elemincre);
  859 
  860             if (elemnum >= repeat)  /* completed a row; start on later row */
  861             {
  862                 rowincre = elemnum / repeat;
  863                 rownum += rowincre;
  864                 elemnum = elemnum - (rowincre * repeat);
  865             }
  866         }
  867     }  /*  End of main while Loop  */
  868 
  869 
  870     /*--------------------------------*/
  871     /*  check for numerical overflow  */
  872     /*--------------------------------*/
  873     if (*status == OVERFLOW_ERR)
  874     {
  875         ffpmsg(
  876         "Numerical overflow during type conversion while reading FITS data.");
  877         *status = NUM_OVERFLOW;
  878     }
  879 
  880     return(*status);
  881 }
  882 /*--------------------------------------------------------------------------*/
  883 int fffi1u4(unsigned char *input, /* I - array of values to be converted     */
  884             long ntodo,           /* I - number of elements in the array     */
  885             double scale,         /* I - FITS TSCALn or BSCALE value         */
  886             double zero,          /* I - FITS TZEROn or BZERO  value         */
  887             int nullcheck,        /* I - null checking code; 0 = don't check */
  888                                   /*     1:set null pixels = nullval         */
  889                                   /*     2: if null pixel, set nullarray = 1 */
  890             unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
  891    unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
  892             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
  893             int  *anynull,        /* O - set to 1 if any pixels are null     */
  894    unsigned long *output,         /* O - array of converted pixels           */
  895             int *status)          /* IO - error status                       */
  896 /*
  897   Copy input to output following reading of the input from a FITS file.
  898   Check for null values and do datatype conversion and scaling if required.
  899   The nullcheck code value determines how any null values in the input array
  900   are treated.  A null value is an input pixel that is equal to tnull.  If 
  901   nullcheck = 0, then no checking for nulls is performed and any null values
  902   will be transformed just like any other pixel.  If nullcheck = 1, then the
  903   output pixel will be set = nullval if the corresponding input pixel is null.
  904   If nullcheck = 2, then if the pixel is null then the corresponding value of
  905   nullarray will be set to 1; the value of nullarray for non-null pixels 
  906   will = 0.  The anynull parameter will be set = 1 if any of the returned
  907   pixels are null, otherwise anynull will be returned with a value = 0;
  908 */
  909 {
  910     long ii;
  911     double dvalue;
  912 
  913     if (nullcheck == 0)     /* no null checking required */
  914     {
  915         if (scale == 1. && zero == 0.)      /* no scaling */
  916         {       
  917             for (ii = 0; ii < ntodo; ii++)
  918                 output[ii] = (unsigned long) input[ii];  /* copy input */
  919         }
  920         else             /* must scale the data */
  921         {
  922             for (ii = 0; ii < ntodo; ii++)
  923             {
  924                 dvalue = input[ii] * scale + zero;
  925 
  926                 if (dvalue < DULONG_MIN)
  927                 {
  928                     *status = OVERFLOW_ERR;
  929                     output[ii] = 0;
  930                 }
  931                 else if (dvalue > DULONG_MAX)
  932                 {
  933                     *status = OVERFLOW_ERR;
  934                     output[ii] = ULONG_MAX;
  935                 }
  936                 else
  937                     output[ii] = (unsigned long) dvalue;
  938             }
  939         }
  940     }
  941     else        /* must check for null values */
  942     {
  943         if (scale == 1. && zero == 0.)  /* no scaling */
  944         {       
  945             for (ii = 0; ii < ntodo; ii++)
  946             {
  947                 if (input[ii] == tnull)
  948                 {
  949                     *anynull = 1;
  950                     if (nullcheck == 1)
  951                         output[ii] = nullval;
  952                     else
  953                         nullarray[ii] = 1;
  954                 }
  955                 else
  956                     output[ii] = (unsigned long) input[ii];
  957             }
  958         }
  959         else                  /* must scale the data */
  960         {
  961             for (ii = 0; ii < ntodo; ii++)
  962             {
  963                 if (input[ii] == tnull)
  964                 {
  965                     *anynull = 1;
  966                     if (nullcheck == 1)
  967                         output[ii] = nullval;
  968                     else
  969                         nullarray[ii] = 1;
  970                 }
  971                 else
  972                 {
  973                     dvalue = input[ii] * scale + zero;
  974 
  975                     if (dvalue < DULONG_MIN)
  976                     {
  977                         *status = OVERFLOW_ERR;
  978                         output[ii] = 0;
  979                     }
  980                     else if (dvalue > DULONG_MAX)
  981                     {
  982                         *status = OVERFLOW_ERR;
  983                         output[ii] = ULONG_MAX;
  984                     }
  985                     else
  986                         output[ii] = (unsigned long) dvalue;
  987                 }
  988             }
  989         }
  990     }
  991     return(*status);
  992 }
  993 /*--------------------------------------------------------------------------*/
  994 int fffi2u4(short *input,         /* I - array of values to be converted     */
  995             long ntodo,           /* I - number of elements in the array     */
  996             double scale,         /* I - FITS TSCALn or BSCALE value         */
  997             double zero,          /* I - FITS TZEROn or BZERO  value         */
  998             int nullcheck,        /* I - null checking code; 0 = don't check */
  999                                   /*     1:set null pixels = nullval         */
 1000                                   /*     2: if null pixel, set nullarray = 1 */
 1001             short tnull,          /* I - value of FITS TNULLn keyword if any */
 1002    unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
 1003             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 1004             int  *anynull,        /* O - set to 1 if any pixels are null     */
 1005    unsigned long *output,         /* O - array of converted pixels           */
 1006             int *status)          /* IO - error status                       */
 1007 /*
 1008   Copy input to output following reading of the input from a FITS file.
 1009   Check for null values and do datatype conversion and scaling if required.
 1010   The nullcheck code value determines how any null values in the input array
 1011   are treated.  A null value is an input pixel that is equal to tnull.  If 
 1012   nullcheck = 0, then no checking for nulls is performed and any null values
 1013   will be transformed just like any other pixel.  If nullcheck = 1, then the
 1014   output pixel will be set = nullval if the corresponding input pixel is null.
 1015   If nullcheck = 2, then if the pixel is null then the corresponding value of
 1016   nullarray will be set to 1; the value of nullarray for non-null pixels 
 1017   will = 0.  The anynull parameter will be set = 1 if any of the returned
 1018   pixels are null, otherwise anynull will be returned with a value = 0;
 1019 */
 1020 {
 1021     long ii;
 1022     double dvalue;
 1023 
 1024     if (nullcheck == 0)     /* no null checking required */
 1025     {
 1026         if (scale == 1. && zero == 0.)      /* no scaling */
 1027         {       
 1028             for (ii = 0; ii < ntodo; ii++)
 1029             {
 1030                 if (input[ii] < 0)
 1031                 {
 1032                     *status = OVERFLOW_ERR;
 1033                     output[ii] = 0;
 1034                 }
 1035                 else
 1036                     output[ii] = (unsigned long) input[ii];
 1037             }
 1038         }
 1039         else             /* must scale the data */
 1040         {
 1041             for (ii = 0; ii < ntodo; ii++)
 1042             {
 1043                 dvalue = input[ii] * scale + zero;
 1044 
 1045                 if (dvalue < DULONG_MIN)
 1046                 {
 1047                     *status = OVERFLOW_ERR;
 1048                     output[ii] = 0;
 1049                 }
 1050                 else if (dvalue > DULONG_MAX)
 1051                 {
 1052                     *status = OVERFLOW_ERR;
 1053                     output[ii] = ULONG_MAX;
 1054                 }
 1055                 else
 1056                     output[ii] = (unsigned long) dvalue;
 1057             }
 1058         }
 1059     }
 1060     else        /* must check for null values */
 1061     {
 1062         if (scale == 1. && zero == 0.)  /* no scaling */
 1063         {       
 1064             for (ii = 0; ii < ntodo; ii++)
 1065             {
 1066                 if (input[ii] == tnull)
 1067                 {
 1068                     *anynull = 1;
 1069                     if (nullcheck == 1)
 1070                         output[ii] = nullval;
 1071                     else
 1072                         nullarray[ii] = 1;
 1073                 }
 1074                 else
 1075                 {
 1076                     if (input[ii] < 0)
 1077                     {
 1078                         *status = OVERFLOW_ERR;
 1079                         output[ii] = 0;
 1080                     }
 1081                     else
 1082                         output[ii] = (unsigned long) input[ii];
 1083                 }
 1084             }
 1085         }
 1086         else                  /* must scale the data */
 1087         {
 1088             for (ii = 0; ii < ntodo; ii++)
 1089             {
 1090                 if (input[ii] == tnull)
 1091                 {
 1092                     *anynull = 1;
 1093                     if (nullcheck == 1)
 1094                         output[ii] = nullval;
 1095                     else
 1096                         nullarray[ii] = 1;
 1097                 }
 1098                 else
 1099                 {
 1100                     dvalue = input[ii] * scale + zero;
 1101 
 1102                     if (dvalue < DULONG_MIN)
 1103                     {
 1104                         *status = OVERFLOW_ERR;
 1105                         output[ii] = 0;
 1106                     }
 1107                     else if (dvalue > DULONG_MAX)
 1108                     {
 1109                         *status = OVERFLOW_ERR;
 1110                         output[ii] = ULONG_MAX;
 1111                     }
 1112                     else
 1113                         output[ii] = (unsigned long) dvalue;
 1114                 }
 1115             }
 1116         }
 1117     }
 1118     return(*status);
 1119 }
 1120 /*--------------------------------------------------------------------------*/
 1121 int fffi4u4(INT32BIT *input,      /* I - array of values to be converted     */
 1122             long ntodo,           /* I - number of elements in the array     */
 1123             double scale,         /* I - FITS TSCALn or BSCALE value         */
 1124             double zero,          /* I - FITS TZEROn or BZERO  value         */
 1125             int nullcheck,        /* I - null checking code; 0 = don't check */
 1126                                   /*     1:set null pixels = nullval         */
 1127                                   /*     2: if null pixel, set nullarray = 1 */
 1128             INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
 1129    unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
 1130             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 1131             int  *anynull,        /* O - set to 1 if any pixels are null     */
 1132    unsigned long *output,         /* O - array of converted pixels           */
 1133             int *status)          /* IO - error status                       */
 1134 /*
 1135   Copy input to output following reading of the input from a FITS file.
 1136   Check for null values and do datatype conversion and scaling if required.
 1137   The nullcheck code value determines how any null values in the input array
 1138   are treated.  A null value is an input pixel that is equal to tnull.  If 
 1139   nullcheck = 0, then no checking for nulls is performed and any null values
 1140   will be transformed just like any other pixel.  If nullcheck = 1, then the
 1141   output pixel will be set = nullval if the corresponding input pixel is null.
 1142   If nullcheck = 2, then if the pixel is null then the corresponding value of
 1143   nullarray will be set to 1; the value of nullarray for non-null pixels 
 1144   will = 0.  The anynull parameter will be set = 1 if any of the returned
 1145   pixels are null, otherwise anynull will be returned with a value = 0;
 1146 */
 1147 {
 1148     long ii;
 1149     double dvalue;
 1150 
 1151     if (nullcheck == 0)     /* no null checking required */
 1152     {
 1153         if (scale == 1. && zero == 2147483648.)
 1154         {       
 1155            /* Instead of adding 2147483648, it is more efficient */
 1156            /* to just flip the sign bit with the XOR operator */
 1157 
 1158             for (ii = 0; ii < ntodo; ii++) {
 1159                output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
 1160         }
 1161         }
 1162         else if (scale == 1. && zero == 0.)      /* no scaling */
 1163         {       
 1164             for (ii = 0; ii < ntodo; ii++)
 1165             {
 1166                 if (input[ii] < 0)
 1167                 {
 1168                     *status = OVERFLOW_ERR;
 1169                     output[ii] = 0;
 1170                 }
 1171                 else
 1172                     output[ii] = (unsigned long) input[ii]; /* copy input */
 1173             }
 1174         }
 1175         else             /* must scale the data */
 1176         {
 1177             for (ii = 0; ii < ntodo; ii++)
 1178             {
 1179                 dvalue = input[ii] * scale + zero;
 1180 
 1181                 if (dvalue < DULONG_MIN)
 1182                 {
 1183                     *status = OVERFLOW_ERR;
 1184                     output[ii] = 0;
 1185                 }
 1186                 else if (dvalue > DULONG_MAX)
 1187                 {
 1188                     *status = OVERFLOW_ERR;
 1189                     output[ii] = ULONG_MAX;
 1190                 }
 1191                 else
 1192                     output[ii] = (unsigned long) dvalue;
 1193             }
 1194         }
 1195     }
 1196     else        /* must check for null values */
 1197     {
 1198         if (scale == 1. && zero == 2147483648.) 
 1199         {       
 1200             for (ii = 0; ii < ntodo; ii++)
 1201             {
 1202                 if (input[ii] == tnull)
 1203                 {
 1204                     *anynull = 1;
 1205                     if (nullcheck == 1)
 1206                         output[ii] = nullval;
 1207                     else
 1208                         nullarray[ii] = 1;
 1209                 }
 1210                 else
 1211                    output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
 1212             }
 1213         }
 1214         else if (scale == 1. && zero == 0.)      /* no scaling */
 1215         {       
 1216             for (ii = 0; ii < ntodo; ii++)
 1217             {
 1218                 if (input[ii] == tnull)
 1219                 {
 1220                     *anynull = 1;
 1221                     if (nullcheck == 1)
 1222                         output[ii] = nullval;
 1223                     else
 1224                         nullarray[ii] = 1;
 1225                 }
 1226                 else if (input[ii] < 0)
 1227                 {
 1228                     *status = OVERFLOW_ERR;
 1229                     output[ii] = 0;
 1230                 }
 1231                 else
 1232                     output[ii] = (unsigned long) input[ii]; /* copy input */
 1233             }
 1234         }
 1235         else                  /* must scale the data */
 1236         {
 1237             for (ii = 0; ii < ntodo; ii++)
 1238             {
 1239                 if (input[ii] == tnull)
 1240                 {
 1241                     *anynull = 1;
 1242                     if (nullcheck == 1)
 1243                         output[ii] = nullval;
 1244                     else
 1245                         nullarray[ii] = 1;
 1246                 }
 1247                 else
 1248                 {
 1249                     dvalue = input[ii] * scale + zero;
 1250 
 1251                     if (dvalue < DULONG_MIN)
 1252                     {
 1253                         *status = OVERFLOW_ERR;
 1254                         output[ii] = 0;
 1255                     }
 1256                     else if (dvalue > DULONG_MAX)
 1257                     {
 1258                         *status = OVERFLOW_ERR;
 1259                         output[ii] = ULONG_MAX;
 1260                     }
 1261                     else
 1262                         output[ii] = (unsigned long) dvalue;
 1263                 }
 1264             }
 1265         }
 1266     }
 1267     return(*status);
 1268 }
 1269 /*--------------------------------------------------------------------------*/
 1270 int fffi8u4(LONGLONG *input,      /* I - array of values to be converted     */
 1271             long ntodo,           /* I - number of elements in the array     */
 1272             double scale,         /* I - FITS TSCALn or BSCALE value         */
 1273             double zero,          /* I - FITS TZEROn or BZERO  value         */
 1274             int nullcheck,        /* I - null checking code; 0 = don't check */
 1275                                   /*     1:set null pixels = nullval         */
 1276                                   /*     2: if null pixel, set nullarray = 1 */
 1277             LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
 1278    unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
 1279             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 1280             int  *anynull,        /* O - set to 1 if any pixels are null     */
 1281    unsigned long *output,         /* O - array of converted pixels           */
 1282             int *status)          /* IO - error status                       */
 1283 /*
 1284   Copy input to output following reading of the input from a FITS file.
 1285   Check for null values and do datatype conversion and scaling if required.
 1286   The nullcheck code value determines how any null values in the input array
 1287   are treated.  A null value is an input pixel that is equal to tnull.  If 
 1288   nullcheck = 0, then no checking for nulls is performed and any null values
 1289   will be transformed just like any other pixel.  If nullcheck = 1, then the
 1290   output pixel will be set = nullval if the corresponding input pixel is null.
 1291   If nullcheck = 2, then if the pixel is null then the corresponding value of
 1292   nullarray will be set to 1; the value of nullarray for non-null pixels 
 1293   will = 0.  The anynull parameter will be set = 1 if any of the returned
 1294   pixels are null, otherwise anynull will be returned with a value = 0;
 1295 */
 1296 {
 1297     long ii;
 1298     double dvalue;
 1299     ULONGLONG ulltemp;
 1300 
 1301     if (nullcheck == 0)     /* no null checking required */
 1302     {
 1303         if (scale == 1. && zero ==  9223372036854775808.)
 1304         {       
 1305             /* The column we read contains unsigned long long values. */
 1306             /* Instead of adding 9223372036854775808, it is more efficient */
 1307             /* and more precise to just flip the sign bit with the XOR operator */
 1308 
 1309             for (ii = 0; ii < ntodo; ii++) {
 1310  
 1311                 ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
 1312 
 1313                 if (ulltemp > ULONG_MAX)
 1314                 {
 1315                     *status = OVERFLOW_ERR;
 1316                     output[ii] = ULONG_MAX;
 1317                 }
 1318                 else
 1319                     output[ii] = (unsigned long) ulltemp;
 1320             }
 1321         }
 1322         else if (scale == 1. && zero == 0.)      /* no scaling */
 1323         {       
 1324             for (ii = 0; ii < ntodo; ii++)
 1325             {
 1326                 if (input[ii] < 0)
 1327                 {
 1328                     *status = OVERFLOW_ERR;
 1329                     output[ii] = 0;
 1330                 }
 1331                 else if (input[ii] > ULONG_MAX)
 1332                 {
 1333                     *status = OVERFLOW_ERR;
 1334                     output[ii] = ULONG_MAX;
 1335                 }
 1336                 else
 1337                     output[ii] = (unsigned long) input[ii];
 1338             }
 1339         }
 1340         else             /* must scale the data */
 1341         {
 1342             for (ii = 0; ii < ntodo; ii++)
 1343             {
 1344                 dvalue = input[ii] * scale + zero;
 1345 
 1346                 if (dvalue < DULONG_MIN)
 1347                 {
 1348                     *status = OVERFLOW_ERR;
 1349                     output[ii] = 0;
 1350                 }
 1351                 else if (dvalue > DULONG_MAX)
 1352                 {
 1353                     *status = OVERFLOW_ERR;
 1354                     output[ii] = ULONG_MAX;
 1355                 }
 1356                 else
 1357                     output[ii] = (unsigned long) dvalue;
 1358             }
 1359         }
 1360     }
 1361     else        /* must check for null values */
 1362     {
 1363         if (scale == 1. && zero ==  9223372036854775808.)
 1364         {       
 1365             /* The column we read contains unsigned long long values. */
 1366             /* Instead of adding 9223372036854775808, it is more efficient */
 1367             /* and more precise to just flip the sign bit with the XOR operator */
 1368 
 1369             for (ii = 0; ii < ntodo; ii++) {
 1370  
 1371                 if (input[ii] == tnull)
 1372                 {
 1373                     *anynull = 1;
 1374                     if (nullcheck == 1)
 1375                         output[ii] = nullval;
 1376                     else
 1377                         nullarray[ii] = 1;
 1378                 }
 1379                 else
 1380                 {
 1381                     ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
 1382 
 1383                     if (ulltemp > ULONG_MAX)
 1384                     {
 1385                         *status = OVERFLOW_ERR;
 1386                         output[ii] = ULONG_MAX;
 1387                     }
 1388                     else
 1389             {
 1390                         output[ii] = (unsigned long) ulltemp;
 1391             }
 1392                 }
 1393             }
 1394         }
 1395         else if (scale == 1. && zero == 0.)  /* no scaling */
 1396         {       
 1397             for (ii = 0; ii < ntodo; ii++)
 1398             {
 1399                 if (input[ii] == tnull)
 1400                 {
 1401                     *anynull = 1;
 1402                     if (nullcheck == 1)
 1403                         output[ii] = nullval;
 1404                     else
 1405                         nullarray[ii] = 1;
 1406                 }
 1407                 else
 1408                 {
 1409                     if (input[ii] < 0)
 1410                     {
 1411                         *status = OVERFLOW_ERR;
 1412                         output[ii] = 0;
 1413                     }
 1414                     else if (input[ii] > ULONG_MAX)
 1415                     {
 1416                         *status = OVERFLOW_ERR;
 1417                         output[ii] = ULONG_MAX;
 1418                     }
 1419                     else
 1420                         output[ii] = (unsigned long) input[ii];
 1421                 }
 1422             }
 1423         }
 1424         else                  /* must scale the data */
 1425         {
 1426             for (ii = 0; ii < ntodo; ii++)
 1427             {
 1428                 if (input[ii] == tnull)
 1429                 {
 1430                     *anynull = 1;
 1431                     if (nullcheck == 1)
 1432                         output[ii] = nullval;
 1433                     else
 1434                         nullarray[ii] = 1;
 1435                 }
 1436                 else
 1437                 {
 1438                     dvalue = input[ii] * scale + zero;
 1439 
 1440                     if (dvalue < DULONG_MIN)
 1441                     {
 1442                         *status = OVERFLOW_ERR;
 1443                         output[ii] = 0;
 1444                     }
 1445                     else if (dvalue > DULONG_MAX)
 1446                     {
 1447                         *status = OVERFLOW_ERR;
 1448                         output[ii] = ULONG_MAX;
 1449                     }
 1450                     else
 1451                         output[ii] = (unsigned long) dvalue;
 1452                 }
 1453             }
 1454         }
 1455     }
 1456     return(*status);
 1457 }
 1458 /*--------------------------------------------------------------------------*/
 1459 int fffr4u4(float *input,         /* I - array of values to be converted     */
 1460             long ntodo,           /* I - number of elements in the array     */
 1461             double scale,         /* I - FITS TSCALn or BSCALE value         */
 1462             double zero,          /* I - FITS TZEROn or BZERO  value         */
 1463             int nullcheck,        /* I - null checking code; 0 = don't check */
 1464                                   /*     1:set null pixels = nullval         */
 1465                                   /*     2: if null pixel, set nullarray = 1 */
 1466    unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
 1467             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 1468             int  *anynull,        /* O - set to 1 if any pixels are null     */
 1469    unsigned long *output,         /* O - array of converted pixels           */
 1470             int *status)          /* IO - error status                       */
 1471 /*
 1472   Copy input to output following reading of the input from a FITS file.
 1473   Check for null values and do datatype conversion and scaling if required.
 1474   The nullcheck code value determines how any null values in the input array
 1475   are treated.  A null value is an input pixel that is equal to NaN.  If 
 1476   nullcheck = 0, then no checking for nulls is performed and any null values
 1477   will be transformed just like any other pixel.  If nullcheck = 1, then the
 1478   output pixel will be set = nullval if the corresponding input pixel is null.
 1479   If nullcheck = 2, then if the pixel is null then the corresponding value of
 1480   nullarray will be set to 1; the value of nullarray for non-null pixels 
 1481   will = 0.  The anynull parameter will be set = 1 if any of the returned
 1482   pixels are null, otherwise anynull will be returned with a value = 0;
 1483 */
 1484 {
 1485     long ii;
 1486     double dvalue;
 1487     short *sptr, iret;
 1488 
 1489     if (nullcheck == 0)     /* no null checking required */
 1490     {
 1491         if (scale == 1. && zero == 0.)      /* no scaling */
 1492         {       
 1493             for (ii = 0; ii < ntodo; ii++)
 1494             {
 1495                 if (input[ii] < DULONG_MIN)
 1496                 {
 1497                     *status = OVERFLOW_ERR;
 1498                     output[ii] = 0;
 1499                 }
 1500                 else if (input[ii] > DULONG_MAX)
 1501                 {
 1502                     *status = OVERFLOW_ERR;
 1503                     output[ii] = ULONG_MAX;
 1504                 }
 1505                 else
 1506                     output[ii] = (unsigned long) input[ii];
 1507             }
 1508         }
 1509         else             /* must scale the data */
 1510         {
 1511             for (ii = 0; ii < ntodo; ii++)
 1512             {
 1513                 dvalue = input[ii] * scale + zero;
 1514 
 1515                 if (dvalue < DULONG_MIN)
 1516                 {
 1517                     *status = OVERFLOW_ERR;
 1518                     output[ii] = 0;
 1519                 }
 1520                 else if (dvalue > DULONG_MAX)
 1521                 {
 1522                     *status = OVERFLOW_ERR;
 1523                     output[ii] = ULONG_MAX;
 1524                 }
 1525                 else
 1526                     output[ii] = (unsigned long) dvalue;
 1527             }
 1528         }
 1529     }
 1530     else        /* must check for null values */
 1531     {
 1532         sptr = (short *) input;
 1533 
 1534 #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
 1535         sptr++;       /* point to MSBs */
 1536 #endif
 1537 
 1538         if (scale == 1. && zero == 0.)  /* no scaling */
 1539         {       
 1540             for (ii = 0; ii < ntodo; ii++, sptr += 2)
 1541             {
 1542               if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
 1543               {
 1544                   if (iret == 1)  /* is it a NaN? */
 1545                   {
 1546                     *anynull = 1;
 1547                     if (nullcheck == 1)
 1548                         output[ii] = nullval;
 1549                     else
 1550                         nullarray[ii] = 1;
 1551                   }
 1552                   else            /* it's an underflow */
 1553                      output[ii] = 0;
 1554               }
 1555               else
 1556                 {
 1557                     if (input[ii] < DULONG_MIN)
 1558                     {
 1559                         *status = OVERFLOW_ERR;
 1560                         output[ii] = 0;
 1561                     }
 1562                     else if (input[ii] > DULONG_MAX)
 1563                     {
 1564                         *status = OVERFLOW_ERR;
 1565                         output[ii] = ULONG_MAX;
 1566                     }
 1567                     else
 1568                         output[ii] = (unsigned long) input[ii];
 1569                 }
 1570             }
 1571         }
 1572         else                  /* must scale the data */
 1573         {
 1574             for (ii = 0; ii < ntodo; ii++, sptr += 2)
 1575             {
 1576               if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
 1577               {
 1578                   if (iret == 1)  /* is it a NaN? */
 1579                   {  
 1580                     *anynull = 1;
 1581                     if (nullcheck == 1)
 1582                         output[ii] = nullval;
 1583                     else
 1584                         nullarray[ii] = 1;
 1585                   }
 1586                   else            /* it's an underflow */
 1587                   { 
 1588                     if (zero < DULONG_MIN)
 1589                     {
 1590                         *status = OVERFLOW_ERR;
 1591                         output[ii] = 0;
 1592                     }
 1593                     else if (zero > DULONG_MAX)
 1594                     {
 1595                         *status = OVERFLOW_ERR;
 1596                         output[ii] = ULONG_MAX;
 1597                     }
 1598                     else
 1599                       output[ii] = (unsigned long) zero;
 1600                   }
 1601               }
 1602               else
 1603                 {
 1604                     dvalue = input[ii] * scale + zero;
 1605 
 1606                     if (dvalue < DULONG_MIN)
 1607                     {
 1608                         *status = OVERFLOW_ERR;
 1609                         output[ii] = 0;
 1610                     }
 1611                     else if (dvalue > DULONG_MAX)
 1612                     {
 1613                         *status = OVERFLOW_ERR;
 1614                         output[ii] = ULONG_MAX;
 1615                     }
 1616                     else
 1617                         output[ii] = (unsigned long) dvalue;
 1618                 }
 1619             }
 1620         }
 1621     }
 1622     return(*status);
 1623 }
 1624 /*--------------------------------------------------------------------------*/
 1625 int fffr8u4(double *input,        /* I - array of values to be converted     */
 1626             long ntodo,           /* I - number of elements in the array     */
 1627             double scale,         /* I - FITS TSCALn or BSCALE value         */
 1628             double zero,          /* I - FITS TZEROn or BZERO  value         */
 1629             int nullcheck,        /* I - null checking code; 0 = don't check */
 1630                                   /*     1:set null pixels = nullval         */
 1631                                   /*     2: if null pixel, set nullarray = 1 */
 1632    unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
 1633             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 1634             int  *anynull,        /* O - set to 1 if any pixels are null     */
 1635    unsigned long *output,         /* O - array of converted pixels           */
 1636             int *status)          /* IO - error status                       */
 1637 /*
 1638   Copy input to output following reading of the input from a FITS file.
 1639   Check for null values and do datatype conversion and scaling if required.
 1640   The nullcheck code value determines how any null values in the input array
 1641   are treated.  A null value is an input pixel that is equal to NaN.  If 
 1642   nullcheck = 0, then no checking for nulls is performed and any null values
 1643   will be transformed just like any other pixel.  If nullcheck = 1, then the
 1644   output pixel will be set = nullval if the corresponding input pixel is null.
 1645   If nullcheck = 2, then if the pixel is null then the corresponding value of
 1646   nullarray will be set to 1; the value of nullarray for non-null pixels 
 1647   will = 0.  The anynull parameter will be set = 1 if any of the returned
 1648   pixels are null, otherwise anynull will be returned with a value = 0;
 1649 */
 1650 {
 1651     long ii;
 1652     double dvalue;
 1653     short *sptr, iret;
 1654 
 1655     if (nullcheck == 0)     /* no null checking required */
 1656     {
 1657         if (scale == 1. && zero == 0.)      /* no scaling */
 1658         {       
 1659             for (ii = 0; ii < ntodo; ii++)
 1660             {
 1661                 if (input[ii] < DULONG_MIN)
 1662                 {
 1663                     *status = OVERFLOW_ERR;
 1664                     output[ii] = 0;
 1665                 }
 1666                 else if (input[ii] > DULONG_MAX)
 1667                 {
 1668                     *status = OVERFLOW_ERR;
 1669                     output[ii] = ULONG_MAX;
 1670                 }
 1671                 else
 1672                     output[ii] = (unsigned long) input[ii];
 1673             }
 1674         }
 1675         else             /* must scale the data */
 1676         {
 1677             for (ii = 0; ii < ntodo; ii++)
 1678             {
 1679                 dvalue = input[ii] * scale + zero;
 1680 
 1681                 if (dvalue < DULONG_MIN)
 1682                 {
 1683                     *status = OVERFLOW_ERR;
 1684                     output[ii] = 0;
 1685                 }
 1686                 else if (dvalue > DULONG_MAX)
 1687                 {
 1688                     *status = OVERFLOW_ERR;
 1689                     output[ii] = ULONG_MAX;
 1690                 }
 1691                 else
 1692                     output[ii] = (unsigned long) dvalue;
 1693             }
 1694         }
 1695     }
 1696     else        /* must check for null values */
 1697     {
 1698         sptr = (short *) input;
 1699 
 1700 #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
 1701         sptr += 3;       /* point to MSBs */
 1702 #endif
 1703         if (scale == 1. && zero == 0.)  /* no scaling */
 1704         {       
 1705             for (ii = 0; ii < ntodo; ii++, sptr += 4)
 1706             {
 1707               if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
 1708               {
 1709                   if (iret == 1)  /* is it a NaN? */
 1710                   {
 1711                     *anynull = 1;
 1712                     if (nullcheck == 1)
 1713                         output[ii] = nullval;
 1714                     else
 1715                         nullarray[ii] = 1;
 1716                   }
 1717                   else            /* it's an underflow */
 1718                      output[ii] = 0;
 1719               }
 1720               else
 1721                 {
 1722                     if (input[ii] < DULONG_MIN)
 1723                     {
 1724                         *status = OVERFLOW_ERR;
 1725                         output[ii] = 0;
 1726                     }
 1727                     else if (input[ii] > DULONG_MAX)
 1728                     {
 1729                         *status = OVERFLOW_ERR;
 1730                         output[ii] = ULONG_MAX;
 1731                     }
 1732                     else
 1733                         output[ii] = (unsigned long) input[ii];
 1734                 }
 1735             }
 1736         }
 1737         else                  /* must scale the data */
 1738         {
 1739             for (ii = 0; ii < ntodo; ii++, sptr += 4)
 1740             {
 1741               if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
 1742               {
 1743                   if (iret == 1)  /* is it a NaN? */
 1744                   {  
 1745                     *anynull = 1;
 1746                     if (nullcheck == 1)
 1747                         output[ii] = nullval;
 1748                     else
 1749                         nullarray[ii] = 1;
 1750                   }
 1751                   else            /* it's an underflow */
 1752                   { 
 1753                     if (zero < DULONG_MIN)
 1754                     {
 1755                         *status = OVERFLOW_ERR;
 1756                         output[ii] = 0;
 1757                     }
 1758                     else if (zero > DULONG_MAX)
 1759                     {
 1760                         *status = OVERFLOW_ERR;
 1761                         output[ii] = ULONG_MAX;
 1762                     }
 1763                     else
 1764                       output[ii] = (unsigned long) zero;
 1765                   }
 1766               }
 1767               else
 1768                 {
 1769                     dvalue = input[ii] * scale + zero;
 1770 
 1771                     if (dvalue < DULONG_MIN)
 1772                     {
 1773                         *status = OVERFLOW_ERR;
 1774                         output[ii] = 0;
 1775                     }
 1776                     else if (dvalue > DULONG_MAX)
 1777                     {
 1778                         *status = OVERFLOW_ERR;
 1779                         output[ii] = ULONG_MAX;
 1780                     }
 1781                     else
 1782                         output[ii] = (unsigned long) dvalue;
 1783                 }
 1784             }
 1785         }
 1786     }
 1787     return(*status);
 1788 }
 1789 /*--------------------------------------------------------------------------*/
 1790 int fffstru4(char *input,         /* I - array of values to be converted     */
 1791             long ntodo,           /* I - number of elements in the array     */
 1792             double scale,         /* I - FITS TSCALn or BSCALE value         */
 1793             double zero,          /* I - FITS TZEROn or BZERO  value         */
 1794             long twidth,          /* I - width of each substring of chars    */
 1795             double implipower,    /* I - power of 10 of implied decimal      */
 1796             int nullcheck,        /* I - null checking code; 0 = don't check */
 1797                                   /*     1:set null pixels = nullval         */
 1798                                   /*     2: if null pixel, set nullarray = 1 */
 1799             char  *snull,         /* I - value of FITS null string, if any   */
 1800    unsigned long nullval,         /* I - set null pixels, if nullcheck = 1   */
 1801             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 1802             int  *anynull,        /* O - set to 1 if any pixels are null     */
 1803    unsigned long *output,         /* O - array of converted pixels           */
 1804             int *status)          /* IO - error status                       */
 1805 /*
 1806   Copy input to output following reading of the input from a FITS file. Check
 1807   for null values and do scaling if required. The nullcheck code value
 1808   determines how any null values in the input array are treated. A null
 1809   value is an input pixel that is equal to snull.  If nullcheck= 0, then
 1810   no special checking for nulls is performed.  If nullcheck = 1, then the
 1811   output pixel will be set = nullval if the corresponding input pixel is null.
 1812   If nullcheck = 2, then if the pixel is null then the corresponding value of
 1813   nullarray will be set to 1; the value of nullarray for non-null pixels 
 1814   will = 0.  The anynull parameter will be set = 1 if any of the returned
 1815   pixels are null, otherwise anynull will be returned with a value = 0;
 1816 */
 1817 {
 1818     int nullen;
 1819     long ii;
 1820     double dvalue;
 1821     char *cstring, message[FLEN_ERRMSG];
 1822     char *cptr, *tpos;
 1823     char tempstore, chrzero = '0';
 1824     double val, power;
 1825     int exponent, sign, esign, decpt;
 1826 
 1827     nullen = strlen(snull);
 1828     cptr = input;  /* pointer to start of input string */
 1829     for (ii = 0; ii < ntodo; ii++)
 1830     {
 1831       cstring = cptr;
 1832       /* temporarily insert a null terminator at end of the string */
 1833       tpos = cptr + twidth;
 1834       tempstore = *tpos;
 1835       *tpos = 0;
 1836 
 1837       /* check if null value is defined, and if the    */
 1838       /* column string is identical to the null string */
 1839       if (snull[0] != ASCII_NULL_UNDEFINED && 
 1840          !strncmp(snull, cptr, nullen) )
 1841       {
 1842         if (nullcheck)  
 1843         {
 1844           *anynull = 1;    
 1845           if (nullcheck == 1)
 1846             output[ii] = nullval;
 1847           else
 1848             nullarray[ii] = 1;
 1849         }
 1850         cptr += twidth;
 1851       }
 1852       else
 1853       {
 1854         /* value is not the null value, so decode it */
 1855         /* remove any embedded blank characters from the string */
 1856 
 1857         decpt = 0;
 1858         sign = 1;
 1859         val  = 0.;
 1860         power = 1.;
 1861         exponent = 0;
 1862         esign = 1;
 1863 
 1864         while (*cptr == ' ')               /* skip leading blanks */
 1865            cptr++;
 1866 
 1867         if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
 1868         {
 1869           if (*cptr == '-')
 1870              sign = -1;
 1871 
 1872           cptr++;
 1873 
 1874           while (*cptr == ' ')         /* skip blanks between sign and value */
 1875             cptr++;
 1876         }
 1877 
 1878         while (*cptr >= '0' && *cptr <= '9')
 1879         {
 1880           val = val * 10. + *cptr - chrzero;  /* accumulate the value */
 1881           cptr++;
 1882 
 1883           while (*cptr == ' ')         /* skip embedded blanks in the value */
 1884             cptr++;
 1885         }
 1886 
 1887         if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
 1888         {
 1889           decpt = 1;       /* set flag to show there was a decimal point */
 1890           cptr++;
 1891           while (*cptr == ' ')         /* skip any blanks */
 1892             cptr++;
 1893 
 1894           while (*cptr >= '0' && *cptr <= '9')
 1895           {
 1896             val = val * 10. + *cptr - chrzero;  /* accumulate the value */
 1897             power = power * 10.;
 1898             cptr++;
 1899 
 1900             while (*cptr == ' ')         /* skip embedded blanks in the value */
 1901               cptr++;
 1902           }
 1903         }
 1904 
 1905         if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
 1906         {
 1907           cptr++;
 1908           while (*cptr == ' ')         /* skip blanks */
 1909               cptr++;
 1910   
 1911           if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
 1912           {
 1913             if (*cptr == '-')
 1914                esign = -1;
 1915 
 1916             cptr++;
 1917 
 1918             while (*cptr == ' ')        /* skip blanks between sign and exp */
 1919               cptr++;
 1920           }
 1921 
 1922           while (*cptr >= '0' && *cptr <= '9')
 1923           {
 1924             exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
 1925             cptr++;
 1926 
 1927             while (*cptr == ' ')         /* skip embedded blanks */
 1928               cptr++;
 1929           }
 1930         }
 1931 
 1932         if (*cptr  != 0)  /* should end up at the null terminator */
 1933         {
 1934           snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
 1935           ffpmsg(message);
 1936           snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
 1937           ffpmsg(message);
 1938           /* restore the char that was overwritten by the null */
 1939           *tpos = tempstore;
 1940           return(*status = BAD_C2D);
 1941         }
 1942 
 1943         if (!decpt)  /* if no explicit decimal, use implied */
 1944            power = implipower;
 1945 
 1946         dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
 1947 
 1948         dvalue = dvalue * scale + zero;   /* apply the scaling */
 1949 
 1950         if (dvalue < DULONG_MIN)
 1951         {
 1952             *status = OVERFLOW_ERR;
 1953             output[ii] = 0;
 1954         }
 1955         else if (dvalue > DULONG_MAX)
 1956         {
 1957             *status = OVERFLOW_ERR;
 1958             output[ii] = ULONG_MAX;
 1959         }
 1960         else
 1961             output[ii] = (unsigned long) dvalue;
 1962       }
 1963       /* restore the char that was overwritten by the null */
 1964       *tpos = tempstore;
 1965     }
 1966     return(*status);
 1967 }
 1968 
 1969 /* ======================================================================== */
 1970 /*      the following routines support the 'long long' data type            */
 1971 /* ======================================================================== */
 1972 
 1973 /*--------------------------------------------------------------------------*/
 1974 int ffgpvujj(fitsfile *fptr,   /* I - FITS file pointer                       */
 1975             long  group,      /* I - group to read (1 = 1st group)           */
 1976             LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
 1977             LONGLONG  nelem,      /* I - number of values to read                */
 1978             ULONGLONG  nulval, /* I - value for undefined pixels              */
 1979             ULONGLONG  *array, /* O - array of values that are returned       */
 1980             int  *anynul,     /* O - set to 1 if any values are null; else 0 */
 1981             int  *status)     /* IO - error status                           */
 1982 /*
 1983   Read an array of values from the primary array. Data conversion
 1984   and scaling will be performed if necessary (e.g, if the datatype of
 1985   the FITS array is not the same as the array being read).
 1986   Undefined elements will be set equal to NULVAL, unless NULVAL=0
 1987   in which case no checking for undefined values will be performed.
 1988   ANYNUL is returned with a value of .true. if any pixels are undefined.
 1989 */
 1990 {
 1991     long row;
 1992     char cdummy;
 1993     int nullcheck = 1;
 1994     ULONGLONG nullvalue;
 1995 
 1996     if (fits_is_compressed_image(fptr, status))
 1997     {
 1998         /* this is a compressed image in a binary table */
 1999          nullvalue = nulval;  /* set local variable */
 2000 
 2001         fits_read_compressed_pixels(fptr, TULONGLONG, firstelem, nelem,
 2002             nullcheck, &nullvalue, array, NULL, anynul, status);
 2003         return(*status);
 2004     }
 2005 
 2006     /*
 2007       the primary array is represented as a binary table:
 2008       each group of the primary array is a row in the table,
 2009       where the first column contains the group parameters
 2010       and the second column contains the image itself.
 2011     */
 2012 
 2013     row=maxvalue(1,group);
 2014 
 2015     ffgclujj(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
 2016                array, &cdummy, anynul, status);
 2017     return(*status);
 2018 }
 2019 /*--------------------------------------------------------------------------*/
 2020 int ffgpfujj(fitsfile *fptr,   /* I - FITS file pointer                       */
 2021             long  group,      /* I - group to read (1 = 1st group)           */
 2022             LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
 2023             LONGLONG  nelem,      /* I - number of values to read                */
 2024             ULONGLONG  *array, /* O - array of values that are returned       */
 2025             char *nularray,   /* O - array of null pixel flags               */
 2026             int  *anynul,     /* O - set to 1 if any values are null; else 0 */
 2027             int  *status)     /* IO - error status                           */
 2028 /*
 2029   Read an array of values from the primary array. Data conversion
 2030   and scaling will be performed if necessary (e.g, if the datatype of
 2031   the FITS array is not the same as the array being read).
 2032   Any undefined pixels in the returned array will be set = 0 and the 
 2033   corresponding nularray value will be set = 1.
 2034   ANYNUL is returned with a value of .true. if any pixels are undefined.
 2035 */
 2036 {
 2037     long row;
 2038     int nullcheck = 2;
 2039     ULONGLONG dummy = 0;
 2040 
 2041     if (fits_is_compressed_image(fptr, status))
 2042     {
 2043         /* this is a compressed image in a binary table */
 2044 
 2045         fits_read_compressed_pixels(fptr, TULONGLONG, firstelem, nelem,
 2046             nullcheck, NULL, array, nularray, anynul, status);
 2047         return(*status);
 2048     }
 2049 
 2050     /*
 2051       the primary array is represented as a binary table:
 2052       each group of the primary array is a row in the table,
 2053       where the first column contains the group parameters
 2054       and the second column contains the image itself.
 2055     */
 2056 
 2057     row=maxvalue(1,group);
 2058 
 2059     ffgclujj(fptr, 2, row, firstelem, nelem, 1, 2, dummy,
 2060                array, nularray, anynul, status);
 2061     return(*status);
 2062 }
 2063 /*--------------------------------------------------------------------------*/
 2064 int ffg2dujj(fitsfile *fptr, /* I - FITS file pointer                       */
 2065            long  group,     /* I - group to read (1 = 1st group)           */
 2066            ULONGLONG nulval ,/* set undefined pixels equal to this          */
 2067            LONGLONG  ncols,     /* I - number of pixels in each row of array   */
 2068            LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
 2069            LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
 2070            ULONGLONG  *array,/* O - array to be filled and returned         */
 2071            int  *anynul,    /* O - set to 1 if any values are null; else 0 */
 2072            int  *status)    /* IO - error status                           */
 2073 /*
 2074   Read an entire 2-D array of values to the primary array. Data conversion
 2075   and scaling will be performed if necessary (e.g, if the datatype of the
 2076   FITS array is not the same as the array being read).  Any null
 2077   values in the array will be set equal to the value of nulval, unless
 2078   nulval = 0 in which case no null checking will be performed.
 2079 */
 2080 {
 2081     /* call the 3D reading routine, with the 3rd dimension = 1 */
 2082 
 2083     ffg3dujj(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array, 
 2084            anynul, status);
 2085 
 2086     return(*status);
 2087 }
 2088 /*--------------------------------------------------------------------------*/
 2089 int ffg3dujj(fitsfile *fptr, /* I - FITS file pointer                       */
 2090            long  group,     /* I - group to read (1 = 1st group)           */
 2091            ULONGLONG nulval, /* set undefined pixels equal to this          */
 2092            LONGLONG  ncols,     /* I - number of pixels in each row of array   */
 2093            LONGLONG  nrows,     /* I - number of rows in each plane of array   */
 2094            LONGLONG  naxis1,    /* I - FITS image NAXIS1 value                 */
 2095            LONGLONG  naxis2,    /* I - FITS image NAXIS2 value                 */
 2096            LONGLONG  naxis3,    /* I - FITS image NAXIS3 value                 */
 2097            ULONGLONG  *array,/* O - array to be filled and returned         */
 2098            int  *anynul,    /* O - set to 1 if any values are null; else 0 */
 2099            int  *status)    /* IO - error status                           */
 2100 /*
 2101   Read an entire 3-D array of values to the primary array. Data conversion
 2102   and scaling will be performed if necessary (e.g, if the datatype of the
 2103   FITS array is not the same as the array being read).  Any null
 2104   values in the array will be set equal to the value of nulval, unless
 2105   nulval = 0 in which case no null checking will be performed.
 2106 */
 2107 {
 2108     long tablerow, ii, jj;
 2109     char cdummy;
 2110     int nullcheck = 1;
 2111     long inc[] = {1,1,1};
 2112     LONGLONG fpixel[] = {1,1,1}, nfits, narray;
 2113     LONGLONG lpixel[3];
 2114     ULONGLONG nullvalue;
 2115 
 2116     if (fits_is_compressed_image(fptr, status))
 2117     {
 2118         /* this is a compressed image in a binary table */
 2119 
 2120         lpixel[0] = ncols;
 2121         lpixel[1] = nrows;
 2122         lpixel[2] = naxis3;
 2123         nullvalue = nulval;  /* set local variable */
 2124 
 2125         fits_read_compressed_img(fptr, TULONGLONG, fpixel, lpixel, inc,
 2126             nullcheck, &nullvalue, array, NULL, anynul, status);
 2127         return(*status);
 2128     }
 2129 
 2130     /*
 2131       the primary array is represented as a binary table:
 2132       each group of the primary array is a row in the table,
 2133       where the first column contains the group parameters
 2134       and the second column contains the image itself.
 2135     */
 2136     tablerow=maxvalue(1,group);
 2137 
 2138     if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
 2139     {
 2140        /* all the image pixels are contiguous, so read all at once */
 2141        ffgclujj(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
 2142                array, &cdummy, anynul, status);
 2143        return(*status);
 2144     }
 2145 
 2146     if (ncols < naxis1 || nrows < naxis2)
 2147        return(*status = BAD_DIMEN);
 2148 
 2149     nfits = 1;   /* next pixel in FITS image to read */
 2150     narray = 0;  /* next pixel in output array to be filled */
 2151 
 2152     /* loop over naxis3 planes in the data cube */
 2153     for (jj = 0; jj < naxis3; jj++)
 2154     {
 2155       /* loop over the naxis2 rows in the FITS image, */
 2156       /* reading naxis1 pixels to each row            */
 2157 
 2158       for (ii = 0; ii < naxis2; ii++)
 2159       {
 2160        if (ffgclujj(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
 2161           &array[narray], &cdummy, anynul, status) > 0)
 2162           return(*status);
 2163 
 2164        nfits += naxis1;
 2165        narray += ncols;
 2166       }
 2167       narray += (nrows - naxis2) * ncols;
 2168     }
 2169 
 2170     return(*status);
 2171 }
 2172 /*--------------------------------------------------------------------------*/
 2173 int ffgsvujj(fitsfile *fptr, /* I - FITS file pointer                         */
 2174            int  colnum,    /* I - number of the column to read (1 = 1st)    */
 2175            int naxis,      /* I - number of dimensions in the FITS array    */
 2176            long  *naxes,   /* I - size of each dimension                    */
 2177            long  *blc,     /* I - 'bottom left corner' of the subsection    */
 2178            long  *trc,     /* I - 'top right corner' of the subsection      */
 2179            long  *inc,     /* I - increment to be applied in each dimension */
 2180            ULONGLONG nulval,/* I - value to set undefined pixels             */
 2181            ULONGLONG *array,/* O - array to be filled and returned           */
 2182            int  *anynul,   /* O - set to 1 if any values are null; else 0   */
 2183            int  *status)   /* IO - error status                             */
 2184 /*
 2185   Read a subsection of data values from an image or a table column.
 2186   This routine is set up to handle a maximum of nine dimensions.
 2187 */
 2188 {
 2189     long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
 2190     long str[9],stp[9],incr[9],dir[9];
 2191     long nelem, nultyp, ninc, numcol;
 2192     LONGLONG felem, dsize[10], blcll[9], trcll[9];
 2193     int hdutype, anyf;
 2194     char ldummy, msg[FLEN_ERRMSG];
 2195     int nullcheck = 1;
 2196     ULONGLONG nullvalue;
 2197 
 2198     if (naxis < 1 || naxis > 9)
 2199     {
 2200         snprintf(msg, FLEN_ERRMSG, "NAXIS = %d in call to ffgsvj is out of range", naxis);
 2201         ffpmsg(msg);
 2202         return(*status = BAD_DIMEN);
 2203     }
 2204 
 2205     if (fits_is_compressed_image(fptr, status))
 2206     {
 2207         /* this is a compressed image in a binary table */
 2208 
 2209         for (ii=0; ii < naxis; ii++) {
 2210         blcll[ii] = blc[ii];
 2211         trcll[ii] = trc[ii];
 2212     }
 2213 
 2214         nullvalue = nulval;  /* set local variable */
 2215 
 2216         fits_read_compressed_img(fptr, TULONGLONG, blcll, trcll, inc,
 2217             nullcheck, &nullvalue, array, NULL, anynul, status);
 2218         return(*status);
 2219     }
 2220 
 2221 /*
 2222     if this is a primary array, then the input COLNUM parameter should
 2223     be interpreted as the row number, and we will alway read the image
 2224     data from column 2 (any group parameters are in column 1).
 2225 */
 2226     if (ffghdt(fptr, &hdutype, status) > 0)
 2227         return(*status);
 2228 
 2229     if (hdutype == IMAGE_HDU)
 2230     {
 2231         /* this is a primary array, or image extension */
 2232         if (colnum == 0)
 2233         {
 2234             rstr = 1;
 2235             rstp = 1;
 2236         }
 2237         else
 2238         {
 2239             rstr = colnum;
 2240             rstp = colnum;
 2241         }
 2242         rinc = 1;
 2243         numcol = 2;
 2244     }
 2245     else
 2246     {
 2247         /* this is a table, so the row info is in the (naxis+1) elements */
 2248         rstr = blc[naxis];
 2249         rstp = trc[naxis];
 2250         rinc = inc[naxis];
 2251         numcol = colnum;
 2252     }
 2253 
 2254     nultyp = 1;
 2255     if (anynul)
 2256         *anynul = FALSE;
 2257 
 2258     i0 = 0;
 2259     for (ii = 0; ii < 9; ii++)
 2260     {
 2261         str[ii] = 1;
 2262         stp[ii] = 1;
 2263         incr[ii] = 1;
 2264         dsize[ii] = 1;
 2265         dir[ii] = 1;
 2266     }
 2267 
 2268     for (ii = 0; ii < naxis; ii++)
 2269     {
 2270       if (trc[ii] < blc[ii])
 2271       {
 2272         if (hdutype == IMAGE_HDU)
 2273         {
 2274            dir[ii] = -1;
 2275         }
 2276         else
 2277         {
 2278           snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1);
 2279           ffpmsg(msg);
 2280           return(*status = BAD_PIX_NUM);
 2281         }
 2282       }
 2283 
 2284       str[ii] = blc[ii];
 2285       stp[ii] = trc[ii];
 2286       incr[ii] = inc[ii];
 2287       dsize[ii + 1] = dsize[ii] * naxes[ii];
 2288       dsize[ii] = dsize[ii] * dir[ii];
 2289     }
 2290     dsize[naxis] = dsize[naxis] * dir[naxis];
 2291 
 2292     if (naxis == 1 && naxes[0] == 1)
 2293     {
 2294       /* This is not a vector column, so read all the rows at once */
 2295       nelem = (rstp - rstr) / rinc + 1;
 2296       ninc = rinc;
 2297       rstp = rstr;
 2298     }
 2299     else
 2300     {
 2301       /* have to read each row individually, in all dimensions */
 2302       nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
 2303       ninc = incr[0] * dir[0];
 2304     }
 2305 
 2306     for (row = rstr; row <= rstp; row += rinc)
 2307     {
 2308      for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
 2309      {
 2310       for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
 2311       {
 2312        for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
 2313        {
 2314         for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
 2315         {
 2316          for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
 2317          {
 2318           for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
 2319           {
 2320            for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
 2321            {
 2322             for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
 2323             {
 2324 
 2325               felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] + 
 2326                              (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
 2327                              (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
 2328                              (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];
 2329 
 2330               if ( ffgclujj(fptr, numcol, row, felem, nelem, ninc, nultyp,
 2331                    nulval, &array[i0], &ldummy, &anyf, status) > 0)
 2332                    return(*status);
 2333 
 2334               if (anyf && anynul)
 2335                   *anynul = TRUE;
 2336 
 2337               i0 += nelem;
 2338             }
 2339            }
 2340           }
 2341          }
 2342         }
 2343        }
 2344       }
 2345      }
 2346     }
 2347     return(*status);
 2348 }
 2349 /*--------------------------------------------------------------------------*/
 2350 int ffgsfujj(fitsfile *fptr, /* I - FITS file pointer                         */
 2351            int  colnum,    /* I - number of the column to read (1 = 1st)    */
 2352            int naxis,      /* I - number of dimensions in the FITS array    */
 2353            long  *naxes,   /* I - size of each dimension                    */
 2354            long  *blc,     /* I - 'bottom left corner' of the subsection    */
 2355            long  *trc,     /* I - 'top right corner' of the subsection      */
 2356            long  *inc,     /* I - increment to be applied in each dimension */
 2357            ULONGLONG *array,/* O - array to be filled and returned           */
 2358            char *flagval,  /* O - set to 1 if corresponding value is null   */
 2359            int  *anynul,   /* O - set to 1 if any values are null; else 0   */
 2360            int  *status)   /* IO - error status                             */
 2361 /*
 2362   Read a subsection of data values from an image or a table column.
 2363   This routine is set up to handle a maximum of nine dimensions.
 2364 */
 2365 {
 2366     long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
 2367     long str[9],stp[9],incr[9],dsize[10];
 2368     LONGLONG blcll[9], trcll[9];
 2369     long felem, nelem, nultyp, ninc, numcol;
 2370     ULONGLONG nulval = 0;
 2371     int hdutype, anyf;
 2372     char msg[FLEN_ERRMSG];
 2373     int nullcheck = 2;
 2374 
 2375     if (naxis < 1 || naxis > 9)
 2376     {
 2377         snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
 2378         ffpmsg(msg);
 2379         return(*status = BAD_DIMEN);
 2380     }
 2381 
 2382     if (fits_is_compressed_image(fptr, status))
 2383     {
 2384         /* this is a compressed image in a binary table */
 2385 
 2386         for (ii=0; ii < naxis; ii++) {
 2387         blcll[ii] = blc[ii];
 2388         trcll[ii] = trc[ii];
 2389     }
 2390 
 2391          fits_read_compressed_img(fptr, TULONGLONG, blcll, trcll, inc,
 2392             nullcheck, NULL, array, flagval, anynul, status);
 2393         return(*status);
 2394     }
 2395 
 2396 /*
 2397     if this is a primary array, then the input COLNUM parameter should
 2398     be interpreted as the row number, and we will alway read the image
 2399     data from column 2 (any group parameters are in column 1).
 2400 */
 2401     if (ffghdt(fptr, &hdutype, status) > 0)
 2402         return(*status);
 2403 
 2404     if (hdutype == IMAGE_HDU)
 2405     {
 2406         /* this is a primary array, or image extension */
 2407         if (colnum == 0)
 2408         {
 2409             rstr = 1;
 2410             rstp = 1;
 2411         }
 2412         else
 2413         {
 2414             rstr = colnum;
 2415             rstp = colnum;
 2416         }
 2417         rinc = 1;
 2418         numcol = 2;
 2419     }
 2420     else
 2421     {
 2422         /* this is a table, so the row info is in the (naxis+1) elements */
 2423         rstr = blc[naxis];
 2424         rstp = trc[naxis];
 2425         rinc = inc[naxis];
 2426         numcol = colnum;
 2427     }
 2428 
 2429     nultyp = 2;
 2430     if (anynul)
 2431         *anynul = FALSE;
 2432 
 2433     i0 = 0;
 2434     for (ii = 0; ii < 9; ii++)
 2435     {
 2436         str[ii] = 1;
 2437         stp[ii] = 1;
 2438         incr[ii] = 1;
 2439         dsize[ii] = 1;
 2440     }
 2441 
 2442     for (ii = 0; ii < naxis; ii++)
 2443     {
 2444       if (trc[ii] < blc[ii])
 2445       {
 2446         snprintf(msg, FLEN_ERRMSG,"ffgsvujj: illegal range specified for axis %ld", ii + 1);
 2447         ffpmsg(msg);
 2448         return(*status = BAD_PIX_NUM);
 2449       }
 2450 
 2451       str[ii] = blc[ii];
 2452       stp[ii] = trc[ii];
 2453       incr[ii] = inc[ii];
 2454       dsize[ii + 1] = dsize[ii] * naxes[ii];
 2455     }
 2456 
 2457     if (naxis == 1 && naxes[0] == 1)
 2458     {
 2459       /* This is not a vector column, so read all the rows at once */
 2460       nelem = (rstp - rstr) / rinc + 1;
 2461       ninc = rinc;
 2462       rstp = rstr;
 2463     }
 2464     else
 2465     {
 2466       /* have to read each row individually, in all dimensions */
 2467       nelem = (stp[0] - str[0]) / inc[0] + 1;
 2468       ninc = incr[0];
 2469     }
 2470 
 2471     for (row = rstr; row <= rstp; row += rinc)
 2472     {
 2473      for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
 2474      {
 2475       for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
 2476       {
 2477        for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
 2478        {
 2479         for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
 2480         {
 2481          for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
 2482          {
 2483           for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
 2484           {
 2485            for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
 2486            {
 2487             for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
 2488             {
 2489               felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] + 
 2490                              (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
 2491                              (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
 2492                              (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
 2493 
 2494               if ( ffgclujj(fptr, numcol, row, felem, nelem, ninc, nultyp,
 2495                    nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
 2496                    return(*status);
 2497 
 2498               if (anyf && anynul)
 2499                   *anynul = TRUE;
 2500 
 2501               i0 += nelem;
 2502             }
 2503            }
 2504           }
 2505          }
 2506         }
 2507        }
 2508       }
 2509      }
 2510     }
 2511     return(*status);
 2512 }
 2513 /*--------------------------------------------------------------------------*/
 2514 int ffggpujj(fitsfile *fptr,   /* I - FITS file pointer                       */
 2515             long  group,      /* I - group to read (1 = 1st group)           */
 2516             long  firstelem,  /* I - first vector element to read (1 = 1st)  */
 2517             long  nelem,      /* I - number of values to read                */
 2518             ULONGLONG  *array, /* O - array of values that are returned       */
 2519             int  *status)     /* IO - error status                           */
 2520 /*
 2521   Read an array of group parameters from the primary array. Data conversion
 2522   and scaling will be performed if necessary (e.g, if the datatype of
 2523   the FITS array is not the same as the array being read).
 2524 */
 2525 {
 2526     long row;
 2527     int idummy;
 2528     char cdummy;
 2529     ULONGLONG dummy = 0;
 2530 
 2531     /*
 2532       the primary array is represented as a binary table:
 2533       each group of the primary array is a row in the table,
 2534       where the first column contains the group parameters
 2535       and the second column contains the image itself.
 2536     */
 2537 
 2538     row=maxvalue(1,group);
 2539 
 2540     ffgclujj(fptr, 1, row, firstelem, nelem, 1, 1, dummy,
 2541                array, &cdummy, &idummy, status);
 2542     return(*status);
 2543 }
 2544 /*--------------------------------------------------------------------------*/
 2545 int ffgcvujj(fitsfile *fptr,  /* I - FITS file pointer                       */
 2546            int  colnum,      /* I - number of column to read (1 = 1st col)  */
 2547            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
 2548            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
 2549            LONGLONG  nelem,      /* I - number of values to read                */
 2550            ULONGLONG  nulval, /* I - value for null pixels                   */
 2551            ULONGLONG *array,  /* O - array of values that are read           */
 2552            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
 2553            int  *status)     /* IO - error status                           */
 2554 /*
 2555   Read an array of values from a column in the current FITS HDU. Automatic
 2556   datatype conversion will be performed if the datatype of the column does not
 2557   match the datatype of the array parameter. The output values will be scaled 
 2558   by the FITS TSCALn and TZEROn values if these values have been defined.
 2559   Any undefined pixels will be set equal to the value of 'nulval' unless
 2560   nulval = 0 in which case no checks for undefined pixels will be made.
 2561 */
 2562 {
 2563     char cdummy;
 2564 
 2565     ffgclujj(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
 2566            array, &cdummy, anynul, status);
 2567     return(*status);
 2568 }
 2569 /*--------------------------------------------------------------------------*/
 2570 int ffgcfujj(fitsfile *fptr,  /* I - FITS file pointer                       */
 2571            int  colnum,      /* I - number of column to read (1 = 1st col)  */
 2572            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
 2573            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
 2574            LONGLONG  nelem,      /* I - number of values to read                */
 2575            ULONGLONG  *array, /* O - array of values that are read           */
 2576            char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
 2577            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
 2578            int  *status)     /* IO - error status                           */
 2579 /*
 2580   Read an array of values from a column in the current FITS HDU. Automatic
 2581   datatype conversion will be performed if the datatype of the column does not
 2582   match the datatype of the array parameter. The output values will be scaled 
 2583   by the FITS TSCALn and TZEROn values if these values have been defined.
 2584   Nularray will be set = 1 if the corresponding array pixel is undefined, 
 2585   otherwise nularray will = 0.
 2586 */
 2587 {
 2588     ULONGLONG dummy = 0;
 2589 
 2590     ffgclujj(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
 2591            array, nularray, anynul, status);
 2592     return(*status);
 2593 }
 2594 /*--------------------------------------------------------------------------*/
 2595 int ffgclujj( fitsfile *fptr,   /* I - FITS file pointer                       */
 2596             int  colnum,      /* I - number of column to read (1 = 1st col)  */
 2597             LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
 2598             LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
 2599             LONGLONG  nelem,      /* I - number of values to read                */
 2600             long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
 2601             int   nultyp,     /* I - null value handling code:               */
 2602                               /*     1: set undefined pixels = nulval        */
 2603                               /*     2: set nularray=1 for undefined pixels  */
 2604             ULONGLONG  nulval, /* I - value for null pixels if nultyp = 1     */
 2605             ULONGLONG  *array, /* O - array of values that are read           */
 2606             char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
 2607             int  *anynul,     /* O - set to 1 if any values are null; else 0 */
 2608             int  *status)     /* IO - error status                           */
 2609 /*
 2610   Read an array of values from a column in the current FITS HDU.
 2611   The column number may refer to a real column in an ASCII or binary table, 
 2612   or it may refer be a virtual column in a 1 or more grouped FITS primary
 2613   array or image extension.  FITSIO treats a primary array as a binary table
 2614   with 2 vector columns: the first column contains the group parameters (often
 2615   with length = 0) and the second column contains the array of image pixels.
 2616   Each row of the table represents a group in the case of multigroup FITS
 2617   images.
 2618 
 2619   The output array of values will be converted from the datatype of the column 
 2620   and will be scaled by the FITS TSCALn and TZEROn values if necessary.
 2621 */
 2622 {
 2623     double scale, zero, power = 1., dtemp;
 2624     int tcode, maxelem2, hdutype, xcode, decimals;
 2625     long twidth, incre;
 2626     long ii, xwidth, ntodo;
 2627     int convert, nulcheck, readcheck = 0;
 2628     LONGLONG repeat, startpos, elemnum, readptr, tnull;
 2629     LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
 2630     char tform[20];
 2631     char message[81];
 2632     char snull[20];   /*  the FITS null value if reading from ASCII table  */
 2633 
 2634     double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
 2635     void *buffer;
 2636 
 2637     if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
 2638         return(*status);
 2639 
 2640     buffer = cbuff;
 2641 
 2642     if (anynul)
 2643         *anynul = 0;
 2644 
 2645     if (nultyp == 2)
 2646         memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
 2647 
 2648     /*---------------------------------------------------*/
 2649     /*  Check input and get parameters about the column: */
 2650     /*---------------------------------------------------*/
 2651     if (elemincre < 0)
 2652         readcheck = -1;  /* don't do range checking in this case */
 2653 
 2654     if (ffgcprll(fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
 2655          tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
 2656          &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
 2657          return(*status);
 2658     maxelem = maxelem2;
 2659 
 2660     incre *= elemincre;   /* multiply incre to just get every nth pixel */
 2661 
 2662     if (tcode == TSTRING)    /* setup for ASCII tables */
 2663     {
 2664       /* get the number of implied decimal places if no explicit decmal point */
 2665       ffasfm(tform, &xcode, &xwidth, &decimals, status); 
 2666       for(ii = 0; ii < decimals; ii++)
 2667         power *= 10.;
 2668     }
 2669     /*------------------------------------------------------------------*/
 2670     /*  Decide whether to check for null values in the input FITS file: */
 2671     /*------------------------------------------------------------------*/
 2672     nulcheck = nultyp; /* by default check for null values in the FITS file */
 2673 
 2674     if (nultyp == 1 && nulval == 0)
 2675        nulcheck = 0;    /* calling routine does not want to check for nulls */
 2676 
 2677     else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
 2678             tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
 2679             nulcheck = 0;            /* then do not check for null values. */
 2680 
 2681     else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
 2682             nulcheck = 0;            /* Impossible null value */
 2683 
 2684     else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
 2685             nulcheck = 0;            /* Impossible null value */
 2686 
 2687     else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
 2688          nulcheck = 0;
 2689 
 2690     convert = 1;
 2691 
 2692     /*---------------------------------------------------------------------*/
 2693     /*  Now read the pixels from the FITS column. If the column does not   */
 2694     /*  have the same datatype as the output array, then we have to read   */
 2695     /*  the raw values into a temporary buffer (of limited size).  In      */
 2696     /*  the case of a vector colum read only 1 vector of values at a time  */
 2697     /*  then skip to the next row if more values need to be read.          */
 2698     /*  After reading the raw values, then call the fffXXYY routine to (1) */
 2699     /*  test for undefined values, (2) convert the datatype if necessary,  */
 2700     /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
 2701     /*  scaling parameters.                                                */
 2702     /*---------------------------------------------------------------------*/
 2703     remain = nelem;           /* remaining number of values to read */
 2704     next = 0;                 /* next element in array to be read   */
 2705     rownum = 0;               /* row number, relative to firstrow   */
 2706 
 2707     while (remain)
 2708     {
 2709         /* limit the number of pixels to read at one time to the number that
 2710            will fit in the buffer or to the number of pixels that remain in
 2711            the current vector, which ever is smaller.
 2712         */
 2713         ntodo = (long) minvalue(remain, maxelem);
 2714         if (elemincre >= 0)
 2715         {
 2716           ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
 2717         }
 2718         else
 2719         {
 2720           ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
 2721         }
 2722 
 2723         readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
 2724 
 2725         switch (tcode) 
 2726         {
 2727             case (TLONGLONG):
 2728                 ffgi8b(fptr, readptr, ntodo, incre, (long *) &array[next],
 2729                        status);
 2730                 fffi8u8((LONGLONG *) &array[next], ntodo, scale, zero, 
 2731                            nulcheck, tnull, nulval, &nularray[next], 
 2732                            anynul, &array[next], status);
 2733                 break;
 2734             case (TLONG):
 2735                 ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
 2736                        status);
 2737                 fffi4u8((INT32BIT *) buffer, ntodo, scale, zero, 
 2738                         nulcheck, (INT32BIT) tnull, nulval, &nularray[next], 
 2739                         anynul, &array[next], status);
 2740                 break;
 2741             case (TBYTE):
 2742                 ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
 2743                        status);
 2744                 fffi1u8((unsigned char *) buffer, ntodo, scale, zero, nulcheck, 
 2745                      (unsigned char) tnull, nulval, &nularray[next], anynul, 
 2746                      &array[next], status);
 2747                 break;
 2748             case (TSHORT):
 2749                 ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
 2750                 fffi2u8((short  *) buffer, ntodo, scale, zero, nulcheck, 
 2751                       (short) tnull, nulval, &nularray[next], anynul, 
 2752                       &array[next], status);
 2753                 break;
 2754             case (TFLOAT):
 2755                 ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
 2756                 fffr4u8((float  *) buffer, ntodo, scale, zero, nulcheck, 
 2757                        nulval, &nularray[next], anynul, 
 2758                        &array[next], status);
 2759                 break;
 2760             case (TDOUBLE):
 2761                 ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
 2762                 fffr8u8((double *) buffer, ntodo, scale, zero, nulcheck, 
 2763                           nulval, &nularray[next], anynul, 
 2764                           &array[next], status);
 2765                 break;
 2766             case (TSTRING):
 2767                 ffmbyt(fptr, readptr, REPORT_EOF, status);
 2768        
 2769                 if (incre == twidth)    /* contiguous bytes */
 2770                      ffgbyt(fptr, ntodo * twidth, buffer, status);
 2771                 else
 2772                      ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
 2773                                status);
 2774 
 2775                 fffstru8((char *) buffer, ntodo, scale, zero, twidth, power,
 2776                      nulcheck, snull, nulval, &nularray[next], anynul,
 2777                      &array[next], status);
 2778                 break;
 2779 
 2780             default:  /*  error trap for invalid column format */
 2781                 snprintf(message, 81, 
 2782                    "Cannot read numbers from column %d which has format %s",
 2783                     colnum, tform);
 2784                 ffpmsg(message);
 2785                 if (hdutype == ASCII_TBL)
 2786                     return(*status = BAD_ATABLE_FORMAT);
 2787                 else
 2788                     return(*status = BAD_BTABLE_FORMAT);
 2789 
 2790         } /* End of switch block */
 2791 
 2792         /*-------------------------*/
 2793         /*  Check for fatal error  */
 2794         /*-------------------------*/
 2795         if (*status > 0)  /* test for error during previous read operation */
 2796         {
 2797       dtemp = (double) next;
 2798           if (hdutype > 0)
 2799             snprintf(message, 81,
 2800             "Error reading elements %.0f thru %.0f from column %d (ffgclj).",
 2801               dtemp+1., dtemp+ntodo, colnum);
 2802           else
 2803             snprintf(message, 81,
 2804             "Error reading elements %.0f thru %.0f from image (ffgclj).",
 2805               dtemp+1., dtemp+ntodo);
 2806 
 2807           ffpmsg(message);
 2808           return(*status);
 2809         }
 2810 
 2811         /*--------------------------------------------*/
 2812         /*  increment the counters for the next loop  */
 2813         /*--------------------------------------------*/
 2814         remain -= ntodo;
 2815         if (remain)
 2816         {
 2817             next += ntodo;
 2818             elemnum = elemnum + (ntodo * elemincre);
 2819 
 2820             if (elemnum >= repeat)  /* completed a row; start on later row */
 2821             {
 2822                 rowincre = elemnum / repeat;
 2823                 rownum += rowincre;
 2824                 elemnum = elemnum - (rowincre * repeat);
 2825             }
 2826             else if (elemnum < 0)  /* completed a row; start on a previous row */
 2827             {
 2828                 rowincre = (-elemnum - 1) / repeat + 1;
 2829                 rownum -= rowincre;
 2830                 elemnum = (rowincre * repeat) + elemnum;
 2831             }
 2832         }
 2833     }  /*  End of main while Loop  */
 2834 
 2835 
 2836     /*--------------------------------*/
 2837     /*  check for numerical overflow  */
 2838     /*--------------------------------*/
 2839     if (*status == OVERFLOW_ERR)
 2840     {
 2841         ffpmsg(
 2842         "Numerical overflow during type conversion while reading FITS data.");
 2843         *status = NUM_OVERFLOW;
 2844     }
 2845 
 2846     return(*status);
 2847 }
 2848 /*--------------------------------------------------------------------------*/
 2849 int fffi1u8(unsigned char *input, /* I - array of values to be converted     */
 2850             long ntodo,           /* I - number of elements in the array     */
 2851             double scale,         /* I - FITS TSCALn or BSCALE value         */
 2852             double zero,          /* I - FITS TZEROn or BZERO  value         */
 2853             int nullcheck,        /* I - null checking code; 0 = don't check */
 2854                                   /*     1:set null pixels = nullval         */
 2855                                   /*     2: if null pixel, set nullarray = 1 */
 2856             unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
 2857             ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
 2858             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 2859             int  *anynull,        /* O - set to 1 if any pixels are null     */
 2860             ULONGLONG *output,     /* O - array of converted pixels           */
 2861             int *status)          /* IO - error status                       */
 2862 /*
 2863   Copy input to output following reading of the input from a FITS file.
 2864   Check for null values and do datatype conversion and scaling if required.
 2865   The nullcheck code value determines how any null values in the input array
 2866   are treated.  A null value is an input pixel that is equal to tnull.  If 
 2867   nullcheck = 0, then no checking for nulls is performed and any null values
 2868   will be transformed just like any other pixel.  If nullcheck = 1, then the
 2869   output pixel will be set = nullval if the corresponding input pixel is null.
 2870   If nullcheck = 2, then if the pixel is null then the corresponding value of
 2871   nullarray will be set to 1; the value of nullarray for non-null pixels 
 2872   will = 0.  The anynull parameter will be set = 1 if any of the returned
 2873   pixels are null, otherwise anynull will be returned with a value = 0;
 2874 */
 2875 {
 2876     long ii;
 2877     double dvalue;
 2878 
 2879     if (nullcheck == 0)     /* no null checking required */
 2880     {
 2881         if (scale == 1. && zero == 0.)      /* no scaling */
 2882         {       
 2883             for (ii = 0; ii < ntodo; ii++)
 2884         {
 2885             if (input[ii] < 0) 
 2886         {
 2887                    *status = OVERFLOW_ERR;
 2888                     output[ii] = 0;
 2889                 }
 2890         else
 2891         {
 2892                     output[ii] = (ULONGLONG) input[ii];  /* copy input to output */
 2893         }
 2894         }
 2895         }
 2896         else             /* must scale the data */
 2897         {
 2898             for (ii = 0; ii < ntodo; ii++)
 2899             {
 2900                 dvalue = input[ii] * scale + zero;
 2901 
 2902                 if (dvalue < 0)
 2903                 {
 2904                     *status = OVERFLOW_ERR;
 2905                     output[ii] = 0;
 2906                 }
 2907                 else if (dvalue > DULONGLONG_MAX)
 2908                 {
 2909                     *status = OVERFLOW_ERR;
 2910                     output[ii] = UINT64_MAX;
 2911                 }
 2912                 else
 2913                     output[ii] = (ULONGLONG) dvalue;
 2914             }
 2915         }
 2916     }
 2917     else        /* must check for null values */
 2918     {
 2919         if (scale == 1. && zero == 0.)  /* no scaling */
 2920         {       
 2921             for (ii = 0; ii < ntodo; ii++)
 2922             {
 2923                 if (input[ii] == tnull)
 2924                 {
 2925                     *anynull = 1;
 2926                     if (nullcheck == 1)
 2927                         output[ii] = nullval;
 2928                     else
 2929                         nullarray[ii] = 1;
 2930                 }
 2931                 else if (input[ii] < 0) 
 2932         {
 2933                    *status = OVERFLOW_ERR;
 2934                     output[ii] = 0;
 2935                 }
 2936         else
 2937                     output[ii] = (ULONGLONG) input[ii];
 2938             }
 2939         }
 2940         else                  /* must scale the data */
 2941         {
 2942             for (ii = 0; ii < ntodo; ii++)
 2943             {
 2944                 if (input[ii] == tnull)
 2945                 {
 2946                     *anynull = 1;
 2947                     if (nullcheck == 1)
 2948                         output[ii] = nullval;
 2949                     else
 2950                         nullarray[ii] = 1;
 2951                 }
 2952                 else
 2953                 {
 2954                     dvalue = input[ii] * scale + zero;
 2955 
 2956                     if (dvalue < 0)
 2957                     {
 2958                         *status = OVERFLOW_ERR;
 2959                         output[ii] = 0;
 2960                     }
 2961                     else if (dvalue > DULONGLONG_MAX)
 2962                     {
 2963                         *status = OVERFLOW_ERR;
 2964                         output[ii] = UINT64_MAX;
 2965                     }
 2966                     else
 2967                         output[ii] = (ULONGLONG) dvalue;
 2968                 }
 2969             }
 2970         }
 2971     }
 2972     return(*status);
 2973 }
 2974 /*--------------------------------------------------------------------------*/
 2975 int fffi2u8(short *input,         /* I - array of values to be converted     */
 2976             long ntodo,           /* I - number of elements in the array     */
 2977             double scale,         /* I - FITS TSCALn or BSCALE value         */
 2978             double zero,          /* I - FITS TZEROn or BZERO  value         */
 2979             int nullcheck,        /* I - null checking code; 0 = don't check */
 2980                                   /*     1:set null pixels = nullval         */
 2981                                   /*     2: if null pixel, set nullarray = 1 */
 2982             short tnull,          /* I - value of FITS TNULLn keyword if any */
 2983             ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
 2984             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 2985             int  *anynull,        /* O - set to 1 if any pixels are null     */
 2986             ULONGLONG *output,     /* O - array of converted pixels           */
 2987             int *status)          /* IO - error status                       */
 2988 /*
 2989   Copy input to output following reading of the input from a FITS file.
 2990   Check for null values and do datatype conversion and scaling if required.
 2991   The nullcheck code value determines how any null values in the input array
 2992   are treated.  A null value is an input pixel that is equal to tnull.  If 
 2993   nullcheck = 0, then no checking for nulls is performed and any null values
 2994   will be transformed just like any other pixel.  If nullcheck = 1, then the
 2995   output pixel will be set = nullval if the corresponding input pixel is null.
 2996   If nullcheck = 2, then if the pixel is null then the corresponding value of
 2997   nullarray will be set to 1; the value of nullarray for non-null pixels 
 2998   will = 0.  The anynull parameter will be set = 1 if any of the returned
 2999   pixels are null, otherwise anynull will be returned with a value = 0;
 3000 */
 3001 {
 3002     long ii;
 3003     double dvalue;
 3004 
 3005     if (nullcheck == 0)     /* no null checking required */
 3006     {
 3007         if (scale == 1. && zero == 0.)      /* no scaling */
 3008         {       
 3009             for (ii = 0; ii < ntodo; ii++)
 3010         {
 3011             if (input[ii] < 0) 
 3012         {
 3013                    *status = OVERFLOW_ERR;
 3014                     output[ii] = 0;
 3015                 }
 3016         else
 3017         {
 3018                     output[ii] = (ULONGLONG) input[ii];   /* copy input to output */
 3019                 }
 3020         }
 3021         }
 3022         else             /* must scale the data */
 3023         {
 3024             for (ii = 0; ii < ntodo; ii++)
 3025             {
 3026                 dvalue = input[ii] * scale + zero;
 3027 
 3028                 if (dvalue < DLONGLONG_MIN)
 3029                 {
 3030                     *status = OVERFLOW_ERR;
 3031                     output[ii] = LONGLONG_MIN;
 3032                 }
 3033                 else if (dvalue > DLONGLONG_MAX)
 3034                 {
 3035                     *status = OVERFLOW_ERR;
 3036                     output[ii] = LONGLONG_MAX;
 3037                 }
 3038                 else
 3039                     output[ii] = (LONGLONG) dvalue;
 3040             }
 3041         }
 3042     }
 3043     else        /* must check for null values */
 3044     {
 3045         if (scale == 1. && zero == 0.)  /* no scaling */
 3046         {       
 3047             for (ii = 0; ii < ntodo; ii++)
 3048             {
 3049                 if (input[ii] == tnull)
 3050                 {
 3051                     *anynull = 1;
 3052                     if (nullcheck == 1)
 3053                         output[ii] = nullval;
 3054                     else
 3055                         nullarray[ii] = 1;
 3056                 }
 3057                 else
 3058                     output[ii] = (LONGLONG) input[ii];
 3059             }
 3060         }
 3061         else                  /* must scale the data */
 3062         {
 3063             for (ii = 0; ii < ntodo; ii++)
 3064             {
 3065                 if (input[ii] == tnull)
 3066                 {
 3067                     *anynull = 1;
 3068                     if (nullcheck == 1)
 3069                         output[ii] = nullval;
 3070                     else
 3071                         nullarray[ii] = 1;
 3072                 }
 3073                 else
 3074                 {
 3075                     dvalue = input[ii] * scale + zero;
 3076 
 3077                     if (dvalue < DLONGLONG_MIN)
 3078                     {
 3079                         *status = OVERFLOW_ERR;
 3080                         output[ii] = LONGLONG_MIN;
 3081                     }
 3082                     else if (dvalue > DLONGLONG_MAX)
 3083                     {
 3084                         *status = OVERFLOW_ERR;
 3085                         output[ii] = LONGLONG_MAX;
 3086                     }
 3087                     else
 3088                         output[ii] = (LONGLONG) dvalue;
 3089                 }
 3090             }
 3091         }
 3092     }
 3093     return(*status);
 3094 }
 3095 /*--------------------------------------------------------------------------*/
 3096 int fffi4u8(INT32BIT *input,      /* I - array of values to be converted     */
 3097             long ntodo,           /* I - number of elements in the array     */
 3098             double scale,         /* I - FITS TSCALn or BSCALE value         */
 3099             double zero,          /* I - FITS TZEROn or BZERO  value         */
 3100             int nullcheck,        /* I - null checking code; 0 = don't check */
 3101                                   /*     1:set null pixels = nullval         */
 3102                                   /*     2: if null pixel, set nullarray = 1 */
 3103             INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
 3104             ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
 3105             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 3106             int  *anynull,        /* O - set to 1 if any pixels are null     */
 3107             ULONGLONG *output,     /* O - array of converted pixels           */
 3108             int *status)          /* IO - error status                       */
 3109 /*
 3110   Copy input to output following reading of the input from a FITS file.
 3111   Check for null values and do datatype conversion and scaling if required.
 3112   The nullcheck code value determines how any null values in the input array
 3113   are treated.  A null value is an input pixel that is equal to tnull.  If 
 3114   nullcheck = 0, then no checking for nulls is performed and any null values
 3115   will be transformed just like any other pixel.  If nullcheck = 1, then the
 3116   output pixel will be set = nullval if the corresponding input pixel is null.
 3117   If nullcheck = 2, then if the pixel is null then the corresponding value of
 3118   nullarray will be set to 1; the value of nullarray for non-null pixels 
 3119   will = 0.  The anynull parameter will be set = 1 if any of the returned
 3120   pixels are null, otherwise anynull will be returned with a value = 0;
 3121 */
 3122 {
 3123     long ii;
 3124     double dvalue;
 3125 
 3126     if (nullcheck == 0)     /* no null checking required */
 3127     {
 3128         if (scale == 1. && zero == 0.)      /* no scaling */
 3129         {       
 3130             for (ii = 0; ii < ntodo; ii++)
 3131         {
 3132             if (input[ii] < 0) 
 3133         {
 3134                    *status = OVERFLOW_ERR;
 3135                     output[ii] = 0;
 3136                 }
 3137         else
 3138         {
 3139                    output[ii] = (ULONGLONG) input[ii];   /* copy input to output */
 3140         }
 3141         }
 3142         }
 3143         else             /* must scale the data */
 3144         {
 3145             for (ii = 0; ii < ntodo; ii++)
 3146             {
 3147                 dvalue = input[ii] * scale + zero;
 3148 
 3149                 if (dvalue < 0)
 3150                 {
 3151                     *status = OVERFLOW_ERR;
 3152                     output[ii] = 0;
 3153                 }
 3154                 else if (dvalue > DULONGLONG_MAX)
 3155                 {
 3156                     *status = OVERFLOW_ERR;
 3157                     output[ii] = UINT64_MAX;
 3158                 }
 3159                 else
 3160                     output[ii] = (LONGLONG) dvalue;
 3161             }
 3162         }
 3163     }
 3164     else        /* must check for null values */
 3165     {
 3166         if (scale == 1. && zero == 0.)  /* no scaling */
 3167         {       
 3168             for (ii = 0; ii < ntodo; ii++)
 3169             {
 3170                 if (input[ii] == tnull)
 3171                 {
 3172                     *anynull = 1;
 3173                     if (nullcheck == 1)
 3174                         output[ii] = nullval;
 3175                     else
 3176                         nullarray[ii] = 1;
 3177                 }
 3178             else if (input[ii] < 0) 
 3179         {
 3180                    *status = OVERFLOW_ERR;
 3181                     output[ii] = 0;
 3182                 }
 3183                 else
 3184         {
 3185                     output[ii] = (ULONGLONG) input[ii];
 3186         }
 3187             }
 3188         }
 3189         else                  /* must scale the data */
 3190         {
 3191             for (ii = 0; ii < ntodo; ii++)
 3192             {
 3193                 if (input[ii] == tnull)
 3194                 {
 3195                     *anynull = 1;
 3196                     if (nullcheck == 1)
 3197                         output[ii] = nullval;
 3198                     else
 3199                         nullarray[ii] = 1;
 3200                 }
 3201                 else
 3202                 {
 3203                     dvalue = input[ii] * scale + zero;
 3204 
 3205                     if (dvalue < 0)
 3206                     {
 3207                         *status = OVERFLOW_ERR;
 3208                         output[ii] = 0;
 3209                     }
 3210                     else if (dvalue > DULONGLONG_MAX)
 3211                     {
 3212                         *status = OVERFLOW_ERR;
 3213                         output[ii] = UINT64_MAX;
 3214                     }
 3215                     else
 3216                         output[ii] = (ULONGLONG) dvalue;
 3217                 }
 3218             }
 3219         }
 3220     }
 3221     return(*status);
 3222 }
 3223 /*--------------------------------------------------------------------------*/
 3224 int fffi8u8(LONGLONG *input,      /* I - array of values to be converted     */
 3225             long ntodo,           /* I - number of elements in the array     */
 3226             double scale,         /* I - FITS TSCALn or BSCALE value         */
 3227             double zero,          /* I - FITS TZEROn or BZERO  value         */
 3228             int nullcheck,        /* I - null checking code; 0 = don't check */
 3229                                   /*     1:set null pixels = nullval         */
 3230                                   /*     2: if null pixel, set nullarray = 1 */
 3231             LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
 3232             ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
 3233             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 3234             int  *anynull,        /* O - set to 1 if any pixels are null     */
 3235             ULONGLONG *output,     /* O - array of converted pixels           */
 3236             int *status)          /* IO - error status                       */
 3237 /*
 3238   Copy input to output following reading of the input from a FITS file.
 3239   Check for null values and do datatype conversion and scaling if required.
 3240   The nullcheck code value determines how any null values in the input array
 3241   are treated.  A null value is an input pixel that is equal to tnull.  If 
 3242   nullcheck = 0, then no checking for nulls is performed and any null values
 3243   will be transformed just like any other pixel.  If nullcheck = 1, then the
 3244   output pixel will be set = nullval if the corresponding input pixel is null.
 3245   If nullcheck = 2, then if the pixel is null then the corresponding value of
 3246   nullarray will be set to 1; the value of nullarray for non-null pixels 
 3247   will = 0.  The anynull parameter will be set = 1 if any of the returned
 3248   pixels are null, otherwise anynull will be returned with a value = 0;
 3249 */
 3250 {
 3251     long ii;
 3252     double dvalue;
 3253 
 3254     if (nullcheck == 0)     /* no null checking required */
 3255     {
 3256         if (scale == 1. && zero ==  9223372036854775808.)
 3257         {       
 3258             /* The column we read contains unsigned long long values. */
 3259             /* Instead of adding 9223372036854775808, it is more efficient */
 3260             /* and more precise to just flip the sign bit with the XOR operator */
 3261 
 3262             for (ii = 0; ii < ntodo; ii++) {
 3263                 output[ii] = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
 3264             }
 3265         }
 3266         else        if (scale == 1. && zero == 0.)      /* no scaling */
 3267         {       
 3268             for (ii = 0; ii < ntodo; ii++)
 3269         {
 3270             if (input[ii] < 0) 
 3271         {
 3272                    *status = OVERFLOW_ERR;
 3273                     output[ii] = 0;
 3274                 }
 3275         else
 3276         {
 3277                     output[ii] =  input[ii];   /* copy input to output */
 3278         }
 3279         }
 3280         }
 3281         else             /* must scale the data */
 3282         {
 3283             for (ii = 0; ii < ntodo; ii++)
 3284             {
 3285                 dvalue = input[ii] * scale + zero;
 3286 
 3287                 if (dvalue < 0)
 3288                 {
 3289                     *status = OVERFLOW_ERR;
 3290                     output[ii] = 0;
 3291                 }
 3292                 else if (dvalue > DULONGLONG_MAX)
 3293                 {
 3294                     *status = OVERFLOW_ERR;
 3295                     output[ii] = UINT64_MAX;
 3296                 }
 3297                 else
 3298                     output[ii] = (ULONGLONG) dvalue;
 3299             }
 3300         }
 3301     }
 3302     else        /* must check for null values */
 3303     {
 3304         if (scale == 1. && zero ==  9223372036854775808.)
 3305         {       
 3306             /* The column we read contains unsigned long long values. */
 3307             /* Instead of adding 9223372036854775808, it is more efficient */
 3308             /* and more precise to just flip the sign bit with the XOR operator */
 3309 
 3310             for (ii = 0; ii < ntodo; ii++) {
 3311 
 3312                 if (input[ii] == tnull)
 3313                 {
 3314                     *anynull = 1;
 3315                     if (nullcheck == 1)
 3316                         output[ii] = nullval;
 3317                     else
 3318                         nullarray[ii] = 1;
 3319                 }
 3320                 else
 3321                 {
 3322                    output[ii] = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
 3323                 }
 3324             }
 3325         }
 3326         else if (scale == 1. && zero == 0.)  /* no scaling */
 3327         {       
 3328             for (ii = 0; ii < ntodo; ii++)
 3329             {
 3330                 if (input[ii] == tnull)
 3331                 {
 3332                     *anynull = 1;
 3333                     if (nullcheck == 1)
 3334                         output[ii] = nullval;
 3335                     else
 3336                         nullarray[ii] = 1;
 3337                 }
 3338                 else
 3339         {
 3340                 if (input[ii] < 0) 
 3341             {
 3342                        *status = OVERFLOW_ERR;
 3343                         output[ii] = 0;
 3344                     }
 3345             else
 3346             {
 3347                         output[ii] =  input[ii];   /* copy input to output */
 3348             }
 3349         }
 3350             }
 3351         }
 3352         else                  /* must scale the data */
 3353         {
 3354             for (ii = 0; ii < ntodo; ii++)
 3355             {
 3356                 if (input[ii] == tnull)
 3357                 {
 3358                     *anynull = 1;
 3359                     if (nullcheck == 1)
 3360                         output[ii] = nullval;
 3361                     else
 3362                         nullarray[ii] = 1;
 3363                 }
 3364                 else
 3365                 {
 3366                     dvalue = input[ii] * scale + zero;
 3367 
 3368                     if (dvalue < 0)
 3369                     {
 3370                         *status = OVERFLOW_ERR;
 3371                         output[ii] = 0;
 3372                     }
 3373                     else if (dvalue > DULONGLONG_MAX)
 3374                     {
 3375                         *status = OVERFLOW_ERR;
 3376                         output[ii] = UINT64_MAX;
 3377                     }
 3378                     else
 3379                         output[ii] = (ULONGLONG) dvalue;
 3380                 }
 3381             }
 3382         }
 3383     }
 3384     return(*status);
 3385 }
 3386 /*--------------------------------------------------------------------------*/
 3387 int fffr4u8(float *input,         /* I - array of values to be converted     */
 3388             long ntodo,           /* I - number of elements in the array     */
 3389             double scale,         /* I - FITS TSCALn or BSCALE value         */
 3390             double zero,          /* I - FITS TZEROn or BZERO  value         */
 3391             int nullcheck,        /* I - null checking code; 0 = don't check */
 3392                                   /*     1:set null pixels = nullval         */
 3393                                   /*     2: if null pixel, set nullarray = 1 */
 3394             ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
 3395             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 3396             int  *anynull,        /* O - set to 1 if any pixels are null     */
 3397             ULONGLONG *output,     /* O - array of converted pixels           */
 3398             int *status)          /* IO - error status                       */
 3399 /*
 3400   Copy input to output following reading of the input from a FITS file.
 3401   Check for null values and do datatype conversion and scaling if required.
 3402   The nullcheck code value determines how any null values in the input array
 3403   are treated.  A null value is an input pixel that is equal to NaN.  If 
 3404   nullcheck = 0, then no checking for nulls is performed and any null values
 3405   will be transformed just like any other pixel.  If nullcheck = 1, then the
 3406   output pixel will be set = nullval if the corresponding input pixel is null.
 3407   If nullcheck = 2, then if the pixel is null then the corresponding value of
 3408   nullarray will be set to 1; the value of nullarray for non-null pixels 
 3409   will = 0.  The anynull parameter will be set = 1 if any of the returned
 3410   pixels are null, otherwise anynull will be returned with a value = 0;
 3411 */
 3412 {
 3413     long ii;
 3414     double dvalue;
 3415     short *sptr, iret;
 3416 
 3417     if (nullcheck == 0)     /* no null checking required */
 3418     {
 3419         if (scale == 1. && zero == 0.)      /* no scaling */
 3420         {       
 3421             for (ii = 0; ii < ntodo; ii++)
 3422             {
 3423                 if (input[ii] < 0)
 3424                 {
 3425                     *status = OVERFLOW_ERR;
 3426                     output[ii] = 0;
 3427                 }
 3428                 else if (input[ii] > DULONGLONG_MAX)
 3429                 {
 3430                     *status = OVERFLOW_ERR;
 3431                     output[ii] = UINT64_MAX;
 3432                 }
 3433                 else
 3434                     output[ii] = (ULONGLONG) input[ii];
 3435             }
 3436         }
 3437         else             /* must scale the data */
 3438         {
 3439             for (ii = 0; ii < ntodo; ii++)
 3440             {
 3441                 dvalue = input[ii] * scale + zero;
 3442 
 3443                 if (dvalue < 0)
 3444                 {
 3445                     *status = OVERFLOW_ERR;
 3446                     output[ii] = 0;
 3447                 }
 3448                 else if (dvalue > DULONGLONG_MAX)
 3449                 {
 3450                     *status = OVERFLOW_ERR;
 3451                     output[ii] = UINT64_MAX;
 3452                 }
 3453                 else
 3454                     output[ii] = (ULONGLONG) dvalue;
 3455             }
 3456         }
 3457     }
 3458     else        /* must check for null values */
 3459     {
 3460         sptr = (short *) input;
 3461 
 3462 #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
 3463         sptr++;       /* point to MSBs */
 3464 #endif
 3465 
 3466         if (scale == 1. && zero == 0.)  /* no scaling */
 3467         {       
 3468             for (ii = 0; ii < ntodo; ii++, sptr += 2)
 3469             {
 3470               if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
 3471               {
 3472                   if (iret == 1)  /* is it a NaN? */
 3473                   {
 3474                     *anynull = 1;
 3475                     if (nullcheck == 1)
 3476                         output[ii] = nullval;
 3477                     else
 3478                         nullarray[ii] = 1;
 3479                   }
 3480                   else            /* it's an underflow */
 3481                      output[ii] = 0;
 3482               }
 3483               else
 3484                 {
 3485                     if (input[ii] < 0)
 3486                     {
 3487                         *status = OVERFLOW_ERR;
 3488                         output[ii] = 0;
 3489                     }
 3490                     else if (input[ii] > DULONGLONG_MAX)
 3491                     {
 3492                         *status = OVERFLOW_ERR;
 3493                         output[ii] = UINT64_MAX;
 3494                     }
 3495                     else
 3496                         output[ii] = (ULONGLONG) input[ii];
 3497                 }
 3498             }
 3499         }
 3500         else                  /* must scale the data */
 3501         {
 3502             for (ii = 0; ii < ntodo; ii++, sptr += 2)
 3503             {
 3504               if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
 3505               {
 3506                   if (iret == 1)  /* is it a NaN? */
 3507                   {  
 3508                     *anynull = 1;
 3509                     if (nullcheck == 1)
 3510                         output[ii] = nullval;
 3511                     else
 3512                         nullarray[ii] = 1;
 3513                   }
 3514                   else            /* it's an underflow */
 3515                   {
 3516                     if (zero < 0)
 3517                     {
 3518                         *status = OVERFLOW_ERR;
 3519                         output[ii] = 0;
 3520                     }
 3521                     else if (zero > DULONGLONG_MAX)
 3522                     {
 3523                         *status = OVERFLOW_ERR;
 3524                         output[ii] = UINT64_MAX;
 3525                     }
 3526                     else
 3527                         output[ii] = (ULONGLONG) zero;
 3528                   }
 3529               }
 3530               else
 3531                 {
 3532                     dvalue = input[ii] * scale + zero;
 3533 
 3534                     if (dvalue < 0)
 3535                     {
 3536                         *status = OVERFLOW_ERR;
 3537                         output[ii] = 0;
 3538                     }
 3539                     else if (dvalue > DULONGLONG_MAX)
 3540                     {
 3541                         *status = OVERFLOW_ERR;
 3542                         output[ii] = UINT64_MAX;
 3543                     }
 3544                     else
 3545                         output[ii] = (ULONGLONG) dvalue;
 3546                 }
 3547             }
 3548         }
 3549     }
 3550     return(*status);
 3551 }
 3552 /*--------------------------------------------------------------------------*/
 3553 int fffr8u8(double *input,        /* I - array of values to be converted     */
 3554             long ntodo,           /* I - number of elements in the array     */
 3555             double scale,         /* I - FITS TSCALn or BSCALE value         */
 3556             double zero,          /* I - FITS TZEROn or BZERO  value         */
 3557             int nullcheck,        /* I - null checking code; 0 = don't check */
 3558                                   /*     1:set null pixels = nullval         */
 3559                                   /*     2: if null pixel, set nullarray = 1 */
 3560             ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
 3561             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 3562             int  *anynull,        /* O - set to 1 if any pixels are null     */
 3563             ULONGLONG *output,     /* O - array of converted pixels           */
 3564             int *status)          /* IO - error status                       */
 3565 /*
 3566   Copy input to output following reading of the input from a FITS file.
 3567   Check for null values and do datatype conversion and scaling if required.
 3568   The nullcheck code value determines how any null values in the input array
 3569   are treated.  A null value is an input pixel that is equal to NaN.  If 
 3570   nullcheck = 0, then no checking for nulls is performed and any null values
 3571   will be transformed just like any other pixel.  If nullcheck = 1, then the
 3572   output pixel will be set = nullval if the corresponding input pixel is null.
 3573   If nullcheck = 2, then if the pixel is null then the corresponding value of
 3574   nullarray will be set to 1; the value of nullarray for non-null pixels 
 3575   will = 0.  The anynull parameter will be set = 1 if any of the returned
 3576   pixels are null, otherwise anynull will be returned with a value = 0;
 3577 */
 3578 {
 3579     long ii;
 3580     double dvalue;
 3581     short *sptr, iret;
 3582 
 3583     if (nullcheck == 0)     /* no null checking required */
 3584     {
 3585         if (scale == 1. && zero == 0.)      /* no scaling */
 3586         {       
 3587             for (ii = 0; ii < ntodo; ii++)
 3588             {
 3589                 if (input[ii] < 0)
 3590                 {
 3591                     *status = OVERFLOW_ERR;
 3592                     output[ii] = 0;
 3593                 }
 3594                 else if (input[ii] > DULONGLONG_MAX)
 3595                 {
 3596                     *status = OVERFLOW_ERR;
 3597                     output[ii] = UINT64_MAX;
 3598                 }
 3599                 else
 3600                     output[ii] = (ULONGLONG) input[ii];
 3601             }
 3602         }
 3603         else             /* must scale the data */
 3604         {
 3605             for (ii = 0; ii < ntodo; ii++)
 3606             {
 3607                 dvalue = input[ii] * scale + zero;
 3608 
 3609                 if (dvalue < 0)
 3610                 {
 3611                     *status = OVERFLOW_ERR;
 3612                     output[ii] = 0;
 3613                 }
 3614                 else if (dvalue > DULONGLONG_MAX)
 3615                 {
 3616                     *status = OVERFLOW_ERR;
 3617                     output[ii] = UINT64_MAX;
 3618                 }
 3619                 else
 3620                     output[ii] = (ULONGLONG) dvalue;
 3621             }
 3622         }
 3623     }
 3624     else        /* must check for null values */
 3625     {
 3626         sptr = (short *) input;
 3627 
 3628 #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
 3629         sptr += 3;       /* point to MSBs */
 3630 #endif
 3631         if (scale == 1. && zero == 0.)  /* no scaling */
 3632         {       
 3633             for (ii = 0; ii < ntodo; ii++, sptr += 4)
 3634             {
 3635               if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
 3636               {
 3637                   if (iret == 1)  /* is it a NaN? */
 3638                   {
 3639                     *anynull = 1;
 3640                     if (nullcheck == 1)
 3641                         output[ii] = nullval;
 3642                     else
 3643                         nullarray[ii] = 1;
 3644                   }
 3645                   else            /* it's an underflow */
 3646                      output[ii] = 0;
 3647               }
 3648               else
 3649                 {
 3650                     if (input[ii] < 0)
 3651                     {
 3652                         *status = OVERFLOW_ERR;
 3653                         output[ii] = 0;
 3654                     }
 3655                     else if (input[ii] > DULONGLONG_MAX)
 3656                     {
 3657                         *status = OVERFLOW_ERR;
 3658                         output[ii] = UINT64_MAX;
 3659                     }
 3660                     else
 3661                         output[ii] = (ULONGLONG) input[ii];
 3662                 }
 3663             }
 3664         }
 3665         else                  /* must scale the data */
 3666         {
 3667             for (ii = 0; ii < ntodo; ii++, sptr += 4)
 3668             {
 3669               if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
 3670               {
 3671                   if (iret == 1)  /* is it a NaN? */
 3672                   {  
 3673                     *anynull = 1;
 3674                     if (nullcheck == 1)
 3675                         output[ii] = nullval;
 3676                     else
 3677                         nullarray[ii] = 1;
 3678                   }
 3679                   else            /* it's an underflow */
 3680                   {
 3681                     if (zero < 0)
 3682                     {
 3683                         *status = OVERFLOW_ERR;
 3684                         output[ii] = 0;
 3685                     }
 3686                     else if (zero > DULONGLONG_MAX)
 3687                     {
 3688                         *status = OVERFLOW_ERR;
 3689                         output[ii] = UINT64_MAX;
 3690                     }
 3691                     else
 3692                         output[ii] = (ULONGLONG) zero;
 3693                   }
 3694               }
 3695               else
 3696                 {
 3697                     dvalue = input[ii] * scale + zero;
 3698 
 3699                     if (dvalue < 0)
 3700                     {
 3701                         *status = OVERFLOW_ERR;
 3702                         output[ii] = 0;
 3703                     }
 3704                     else if (dvalue > DULONGLONG_MAX)
 3705                     {
 3706                         *status = OVERFLOW_ERR;
 3707                         output[ii] = UINT64_MAX;
 3708                     }
 3709                     else
 3710                         output[ii] = (ULONGLONG) dvalue;
 3711                 }
 3712             }
 3713         }
 3714     }
 3715     return(*status);
 3716 }
 3717 /*--------------------------------------------------------------------------*/
 3718 int fffstru8(char *input,         /* I - array of values to be converted     */
 3719             long ntodo,           /* I - number of elements in the array     */
 3720             double scale,         /* I - FITS TSCALn or BSCALE value         */
 3721             double zero,          /* I - FITS TZEROn or BZERO  value         */
 3722             long twidth,          /* I - width of each substring of chars    */
 3723             double implipower,    /* I - power of 10 of implied decimal      */
 3724             int nullcheck,        /* I - null checking code; 0 = don't check */
 3725                                   /*     1:set null pixels = nullval         */
 3726                                   /*     2: if null pixel, set nullarray = 1 */
 3727             char  *snull,         /* I - value of FITS null string, if any   */
 3728             ULONGLONG nullval,     /* I - set null pixels, if nullcheck = 1   */
 3729             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 3730             int  *anynull,        /* O - set to 1 if any pixels are null     */
 3731             ULONGLONG *output,     /* O - array of converted pixels           */
 3732             int *status)          /* IO - error status                       */
 3733 /*
 3734   Copy input to output following reading of the input from a FITS file. Check
 3735   for null values and do scaling if required. The nullcheck code value
 3736   determines how any null values in the input array are treated. A null
 3737   value is an input pixel that is equal to snull.  If nullcheck= 0, then
 3738   no special checking for nulls is performed.  If nullcheck = 1, then the
 3739   output pixel will be set = nullval if the corresponding input pixel is null.
 3740   If nullcheck = 2, then if the pixel is null then the corresponding value of
 3741   nullarray will be set to 1; the value of nullarray for non-null pixels 
 3742   will = 0.  The anynull parameter will be set = 1 if any of the returned
 3743   pixels are null, otherwise anynull will be returned with a value = 0;
 3744 */
 3745 {
 3746     int nullen;
 3747     long ii;
 3748     double dvalue;
 3749     char *cstring, message[81];
 3750     char *cptr, *tpos;
 3751     char tempstore, chrzero = '0';
 3752     double val, power;
 3753     int exponent, sign, esign, decpt;
 3754 
 3755     nullen = strlen(snull);
 3756     cptr = input;  /* pointer to start of input string */
 3757     for (ii = 0; ii < ntodo; ii++)
 3758     {
 3759       cstring = cptr;
 3760       /* temporarily insert a null terminator at end of the string */
 3761       tpos = cptr + twidth;
 3762       tempstore = *tpos;
 3763       *tpos = 0;
 3764 
 3765       /* check if null value is defined, and if the    */
 3766       /* column string is identical to the null string */
 3767       if (snull[0] != ASCII_NULL_UNDEFINED && 
 3768          !strncmp(snull, cptr, nullen) )
 3769       {
 3770         if (nullcheck)  
 3771         {
 3772           *anynull = 1;    
 3773           if (nullcheck == 1)
 3774             output[ii] = nullval;
 3775           else
 3776             nullarray[ii] = 1;
 3777         }
 3778         cptr += twidth;
 3779       }
 3780       else
 3781       {
 3782         /* value is not the null value, so decode it */
 3783         /* remove any embedded blank characters from the string */
 3784 
 3785         decpt = 0;
 3786         sign = 1;
 3787         val  = 0.;
 3788         power = 1.;
 3789         exponent = 0;
 3790         esign = 1;
 3791 
 3792         while (*cptr == ' ')               /* skip leading blanks */
 3793            cptr++;
 3794 
 3795         if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
 3796         {
 3797           if (*cptr == '-')
 3798              sign = -1;
 3799 
 3800           cptr++;
 3801 
 3802           while (*cptr == ' ')         /* skip blanks between sign and value */
 3803             cptr++;
 3804         }
 3805 
 3806         while (*cptr >= '0' && *cptr <= '9')
 3807         {
 3808           val = val * 10. + *cptr - chrzero;  /* accumulate the value */
 3809           cptr++;
 3810 
 3811           while (*cptr == ' ')         /* skip embedded blanks in the value */
 3812             cptr++;
 3813         }
 3814 
 3815         if (*cptr == '.' || *cptr == ',')    /* check for decimal point */
 3816         {
 3817           decpt = 1;       /* set flag to show there was a decimal point */
 3818           cptr++;
 3819           while (*cptr == ' ')         /* skip any blanks */
 3820             cptr++;
 3821 
 3822           while (*cptr >= '0' && *cptr <= '9')
 3823           {
 3824             val = val * 10. + *cptr - chrzero;  /* accumulate the value */
 3825             power = power * 10.;
 3826             cptr++;
 3827 
 3828             while (*cptr == ' ')         /* skip embedded blanks in the value */
 3829               cptr++;
 3830           }
 3831         }
 3832 
 3833         if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
 3834         {
 3835           cptr++;
 3836           while (*cptr == ' ')         /* skip blanks */
 3837               cptr++;
 3838   
 3839           if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
 3840           {
 3841             if (*cptr == '-')
 3842                esign = -1;
 3843 
 3844             cptr++;
 3845 
 3846             while (*cptr == ' ')        /* skip blanks between sign and exp */
 3847               cptr++;
 3848           }
 3849 
 3850           while (*cptr >= '0' && *cptr <= '9')
 3851           {
 3852             exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
 3853             cptr++;
 3854 
 3855             while (*cptr == ' ')         /* skip embedded blanks */
 3856               cptr++;
 3857           }
 3858         }
 3859 
 3860         if (*cptr  != 0)  /* should end up at the null terminator */
 3861         {
 3862           sprintf(message, "Cannot read number from ASCII table");
 3863           ffpmsg(message);
 3864           snprintf(message, 81, "Column field = %s.", cstring);
 3865           ffpmsg(message);
 3866           /* restore the char that was overwritten by the null */
 3867           *tpos = tempstore;
 3868           return(*status = BAD_C2D);
 3869         }
 3870 
 3871         if (!decpt)  /* if no explicit decimal, use implied */
 3872            power = implipower;
 3873 
 3874         dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
 3875 
 3876         dvalue = dvalue * scale + zero;   /* apply the scaling */
 3877 
 3878         if (dvalue < 0)
 3879         {
 3880             *status = OVERFLOW_ERR;
 3881             output[ii] = 0;
 3882         }
 3883         else if (dvalue > DULONGLONG_MAX)
 3884         {
 3885             *status = OVERFLOW_ERR;
 3886             output[ii] = UINT64_MAX;
 3887         }
 3888         else
 3889             output[ii] = (ULONGLONG) dvalue;
 3890       }
 3891       /* restore the char that was overwritten by the null */
 3892       *tpos = tempstore;
 3893     }
 3894     return(*status);
 3895 }