1 /*  This file, getcolk.c, contains routines that read data elements from   */
2 /*  a FITS image or table, with 'unsigned int' 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 /*--------------------------------------------------------------------------*/
ffgpvuk(fitsfile * fptr,long group,LONGLONG firstelem,LONGLONG nelem,unsigned int nulval,unsigned int * array,int * anynul,int * status)15 int ffgpvuk( 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 int   nulval,     /* I - value for undefined pixels              */
20    unsigned int   *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 int 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, TUINT, 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     ffgcluk(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
57                array, &cdummy, anynul, status);
58     return(*status);
59 }
60 /*--------------------------------------------------------------------------*/
ffgpfuk(fitsfile * fptr,long group,LONGLONG firstelem,LONGLONG nelem,unsigned int * array,char * nularray,int * anynul,int * status)61 int ffgpfuk(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 int   *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, TUINT, 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     ffgcluk(fptr, 2, row, firstelem, nelem, 1, 2, 0L,
100                array, nularray, anynul, status);
101     return(*status);
102 }
103 /*--------------------------------------------------------------------------*/
ffg2duk(fitsfile * fptr,long group,unsigned int nulval,LONGLONG ncols,LONGLONG naxis1,LONGLONG naxis2,unsigned int * array,int * anynul,int * status)104 int ffg2duk(fitsfile *fptr,  /* I - FITS file pointer                       */
105            long  group,     /* I - group to read (1 = 1st group)           */
106   unsigned int  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 int  *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     ffg3duk(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array,
124            anynul, status);
125 
126     return(*status);
127 }
128 /*--------------------------------------------------------------------------*/
ffg3duk(fitsfile * fptr,long group,unsigned int nulval,LONGLONG ncols,LONGLONG nrows,LONGLONG naxis1,LONGLONG naxis2,LONGLONG naxis3,unsigned int * array,int * anynul,int * status)129 int ffg3duk(fitsfile *fptr,  /* I - FITS file pointer                       */
130            long  group,     /* I - group to read (1 = 1st group)           */
131   unsigned int   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 int   *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 int 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, TUINT, 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        ffgcluk(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 (ffgcluk(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 /*--------------------------------------------------------------------------*/
ffgsvuk(fitsfile * fptr,int colnum,int naxis,long * naxes,long * blc,long * trc,long * inc,unsigned int nulval,unsigned int * array,int * anynul,int * status)213 int ffgsvuk(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 int  nulval,    /* I - value to set undefined pixels             */
221   unsigned int  *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 int nullvalue;
237 
238     if (naxis < 1 || naxis > 9)
239     {
240         snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvuk 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, TUINT, 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,"ffgsvuk: 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 ( ffgcluk(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 /*--------------------------------------------------------------------------*/
ffgsfuk(fitsfile * fptr,int colnum,int naxis,long * naxes,long * blc,long * trc,long * inc,unsigned int * array,char * flagval,int * anynul,int * status)379 int ffgsfuk(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 int  *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     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, TUINT, 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 ( ffgcluk(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 /*--------------------------------------------------------------------------*/
ffggpuk(fitsfile * fptr,long group,long firstelem,long nelem,unsigned int * array,int * status)543 int ffggpuk( 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 int  *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     ffgcluk(fptr, 1, row, firstelem, nelem, 1, 1, 0L,
568                array, &cdummy, &idummy, status);
569     return(*status);
570 }
571 /*--------------------------------------------------------------------------*/
ffgcvuk(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,unsigned int nulval,unsigned int * array,int * anynul,int * status)572 int ffgcvuk(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 int   nulval,     /* I - value for null pixels                   */
578   unsigned int  *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     ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
593            array, &cdummy, anynul, status);
594     return(*status);
595 }
596 /*--------------------------------------------------------------------------*/
ffgcfuk(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,unsigned int * array,char * nularray,int * anynul,int * status)597 int ffgcfuk(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 int   *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     int dummy = 0;
616 
617     ffgcluk(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
618            array, nularray, anynul, status);
619     return(*status);
620 }
621 /*--------------------------------------------------------------------------*/
ffgcluk(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,long elemincre,int nultyp,unsigned int nulval,unsigned int * array,char * nularray,int * anynul,int * status)622 int ffgcluk( 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 int   nulval,     /* I - value for null pixels if nultyp = 1     */
632    unsigned int  *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     /* call the 'short' or 'long' version of this routine, if possible */
668     if (sizeof(int) == sizeof(short))
669         ffgclui(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
670           (unsigned short) nulval, (unsigned short *) array, nularray, anynul,
671            status);
672     else if (sizeof(int) == sizeof(long))
673         ffgcluj(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
674           (unsigned long) nulval, (unsigned long *) array, nularray, anynul,
675           status);
676     else
677     {
678     /*
679       This is a special case: sizeof(int) is not equal to sizeof(short) or
680       sizeof(long).  This occurs on Alpha OSF systems where short = 2 bytes,
681       int = 4 bytes, and long = 8 bytes.
682     */
683 
684     buffer = cbuff;
685 
686     if (anynul)
687         *anynul = 0;
688 
689     if (nultyp == 2)
690         memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
691 
692     /*---------------------------------------------------*/
693     /*  Check input and get parameters about the column: */
694     /*---------------------------------------------------*/
695     if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
696          tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
697          &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
698          return(*status);
699     maxelem = maxelem2;
700 
701     incre *= elemincre;   /* multiply incre to just get every nth pixel */
702 
703     if (tcode == TSTRING)    /* setup for ASCII tables */
704     {
705       /* get the number of implied decimal places if no explicit decmal point */
706       ffasfm(tform, &xcode, &xwidth, &decimals, status);
707       for(ii = 0; ii < decimals; ii++)
708         power *= 10.;
709     }
710     /*------------------------------------------------------------------*/
711     /*  Decide whether to check for null values in the input FITS file: */
712     /*------------------------------------------------------------------*/
713     nulcheck = nultyp; /* by default check for null values in the FITS file */
714 
715     if (nultyp == 1 && nulval == 0)
716        nulcheck = 0;    /* calling routine does not want to check for nulls */
717 
718     else if (tcode%10 == 1 &&        /* if reading an integer column, and  */
719             tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
720             nulcheck = 0;            /* then do not check for null values. */
721 
722     else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
723             nulcheck = 0;            /* Impossible null value */
724 
725     else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
726             nulcheck = 0;            /* Impossible null value */
727 
728     else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
729          nulcheck = 0;
730 
731     /*----------------------------------------------------------------------*/
732     /*  If FITS column and output data array have same datatype, then we do */
733     /*  not need to use a temporary buffer to store intermediate datatype.  */
734     /*----------------------------------------------------------------------*/
735     if (tcode == TLONG)  /* Special Case: */
736     {                             /* data are 4-bytes long, so read       */
737                                   /* data directly into output buffer.    */
738 
739         if (nelem < (LONGLONG)INT32_MAX/4) {
740             maxelem = nelem;
741         } else {
742             maxelem = INT32_MAX/4;
743         }
744     }
745 
746     /*---------------------------------------------------------------------*/
747     /*  Now read the pixels from the FITS column. If the column does not   */
748     /*  have the same datatype as the output array, then we have to read   */
749     /*  the raw values into a temporary buffer (of limited size).  In      */
750     /*  the case of a vector colum read only 1 vector of values at a time  */
751     /*  then skip to the next row if more values need to be read.          */
752     /*  After reading the raw values, then call the fffXXYY routine to (1) */
753     /*  test for undefined values, (2) convert the datatype if necessary,  */
754     /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
755     /*  scaling parameters.                                                */
756     /*---------------------------------------------------------------------*/
757     remain = nelem;           /* remaining number of values to read */
758     next = 0;                 /* next element in array to be read   */
759     rownum = 0;               /* row number, relative to firstrow   */
760 
761     while (remain)
762     {
763         /* limit the number of pixels to read at one time to the number that
764            will fit in the buffer or to the number of pixels that remain in
765            the current vector, which ever is smaller.
766         */
767         ntodo = (long) minvalue(remain, maxelem);
768         ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
769 
770         readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
771 
772         switch (tcode)
773         {
774             case (TLONG):
775                 ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next],
776                        status);
777                     fffi4uint((INT32BIT *) &array[next], ntodo, scale, zero,
778                            nulcheck, (INT32BIT) tnull, nulval, &nularray[next],
779                            anynul, &array[next], status);
780                 break;
781             case (TLONGLONG):
782 
783                 ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
784                 fffi8uint( (LONGLONG *) buffer, ntodo, scale, zero,
785                            nulcheck, tnull, nulval, &nularray[next],
786                             anynul, &array[next], status);
787                 break;
788             case (TBYTE):
789                 ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
790                        status);
791                 fffi1uint((unsigned char *) buffer, ntodo, scale, zero,nulcheck,
792                      (unsigned char) tnull, nulval, &nularray[next], anynul,
793                      &array[next], status);
794                 break;
795             case (TSHORT):
796                 ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
797                 fffi2uint((short  *) buffer, ntodo, scale, zero, nulcheck,
798                       (short) tnull, nulval, &nularray[next], anynul,
799                       &array[next], status);
800                 break;
801             case (TFLOAT):
802                 ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
803                 fffr4uint((float  *) buffer, ntodo, scale, zero, nulcheck,
804                        nulval, &nularray[next], anynul,
805                        &array[next], status);
806                 break;
807             case (TDOUBLE):
808                 ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
809                 fffr8uint((double *) buffer, ntodo, scale, zero, nulcheck,
810                           nulval, &nularray[next], anynul,
811                           &array[next], status);
812                 break;
813             case (TSTRING):
814                 ffmbyt(fptr, readptr, REPORT_EOF, status);
815 
816                 if (incre == twidth)    /* contiguous bytes */
817                      ffgbyt(fptr, ntodo * twidth, buffer, status);
818                 else
819                      ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
820                                status);
821 
822                 fffstruint((char *) buffer, ntodo, scale, zero, twidth, power,
823                      nulcheck, snull, nulval, &nularray[next], anynul,
824                      &array[next], status);
825                 break;
826 
827             default:  /*  error trap for invalid column format */
828                 snprintf(message, FLEN_ERRMSG,
829                    "Cannot read numbers from column %d which has format %s",
830                     colnum, tform);
831                 ffpmsg(message);
832                 if (hdutype == ASCII_TBL)
833                     return(*status = BAD_ATABLE_FORMAT);
834                 else
835                     return(*status = BAD_BTABLE_FORMAT);
836 
837         } /* End of switch block */
838 
839         /*-------------------------*/
840         /*  Check for fatal error  */
841         /*-------------------------*/
842         if (*status > 0)  /* test for error during previous read operation */
843         {
844 	  dtemp = (double) next;
845           if (hdutype > 0)
846             snprintf(message,FLEN_ERRMSG,
847             "Error reading elements %.0f thru %.0f from column %d (ffgcluk).",
848               dtemp+1., dtemp+ntodo, colnum);
849           else
850             snprintf(message,FLEN_ERRMSG,
851             "Error reading elements %.0f thru %.0f from image (ffgcluk).",
852               dtemp+1., dtemp+ntodo);
853 
854           ffpmsg(message);
855           return(*status);
856         }
857 
858         /*--------------------------------------------*/
859         /*  increment the counters for the next loop  */
860         /*--------------------------------------------*/
861         remain -= ntodo;
862         if (remain)
863         {
864             next += ntodo;
865             elemnum = elemnum + (ntodo * elemincre);
866 
867             if (elemnum >= repeat)  /* completed a row; start on later row */
868             {
869                 rowincre = elemnum / repeat;
870                 rownum += rowincre;
871                 elemnum = elemnum - (rowincre * repeat);
872             }
873         }
874     }  /*  End of main while Loop  */
875 
876 
877     /*--------------------------------*/
878     /*  check for numerical overflow  */
879     /*--------------------------------*/
880     if (*status == OVERFLOW_ERR)
881     {
882         ffpmsg(
883         "Numerical overflow during type conversion while reading FITS data.");
884         *status = NUM_OVERFLOW;
885     }
886 
887     }  /* end of DEC Alpha special case */
888 
889     return(*status);
890 }
891 /*--------------------------------------------------------------------------*/
fffi1uint(unsigned char * input,long ntodo,double scale,double zero,int nullcheck,unsigned char tnull,unsigned int nullval,char * nullarray,int * anynull,unsigned int * output,int * status)892 int fffi1uint(unsigned char *input,/* I - array of values to be converted     */
893             long ntodo,           /* I - number of elements in the array     */
894             double scale,         /* I - FITS TSCALn or BSCALE value         */
895             double zero,          /* I - FITS TZEROn or BZERO  value         */
896             int nullcheck,        /* I - null checking code; 0 = don't check */
897                                   /*     1:set null pixels = nullval         */
898                                   /*     2: if null pixel, set nullarray = 1 */
899             unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
900    unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
901             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
902             int  *anynull,        /* O - set to 1 if any pixels are null     */
903    unsigned int  *output,         /* O - array of converted pixels           */
904             int *status)          /* IO - error status                       */
905 /*
906   Copy input to output following reading of the input from a FITS file.
907   Check for null values and do datatype conversion and scaling if required.
908   The nullcheck code value determines how any null values in the input array
909   are treated.  A null value is an input pixel that is equal to tnull.  If
910   nullcheck = 0, then no checking for nulls is performed and any null values
911   will be transformed just like any other pixel.  If nullcheck = 1, then the
912   output pixel will be set = nullval if the corresponding input pixel is null.
913   If nullcheck = 2, then if the pixel is null then the corresponding value of
914   nullarray will be set to 1; the value of nullarray for non-null pixels
915   will = 0.  The anynull parameter will be set = 1 if any of the returned
916   pixels are null, otherwise anynull will be returned with a value = 0;
917 */
918 {
919     long ii;
920     double dvalue;
921 
922     if (nullcheck == 0)     /* no null checking required */
923     {
924         if (scale == 1. && zero == 0.)      /* no scaling */
925         {
926             for (ii = 0; ii < ntodo; ii++)
927                 output[ii] = (unsigned int) input[ii];  /* copy input */
928         }
929         else             /* must scale the data */
930         {
931             for (ii = 0; ii < ntodo; ii++)
932             {
933                 dvalue = input[ii] * scale + zero;
934 
935                 if (dvalue < DUINT_MIN)
936                 {
937                     *status = OVERFLOW_ERR;
938                     output[ii] = 0;
939                 }
940                 else if (dvalue > DUINT_MAX)
941                 {
942                     *status = OVERFLOW_ERR;
943                     output[ii] = UINT_MAX;
944                 }
945                 else
946                     output[ii] = (unsigned int) dvalue;
947             }
948         }
949     }
950     else        /* must check for null values */
951     {
952         if (scale == 1. && zero == 0.)  /* no scaling */
953         {
954             for (ii = 0; ii < ntodo; ii++)
955             {
956                 if (input[ii] == tnull)
957                 {
958                     *anynull = 1;
959                     if (nullcheck == 1)
960                         output[ii] = nullval;
961                     else
962                         nullarray[ii] = 1;
963                 }
964                 else
965                     output[ii] = (unsigned int) input[ii];
966             }
967         }
968         else                  /* must scale the data */
969         {
970             for (ii = 0; ii < ntodo; ii++)
971             {
972                 if (input[ii] == tnull)
973                 {
974                     *anynull = 1;
975                     if (nullcheck == 1)
976                         output[ii] = nullval;
977                     else
978                         nullarray[ii] = 1;
979                 }
980                 else
981                 {
982                     dvalue = input[ii] * scale + zero;
983 
984                     if (dvalue < DUINT_MIN)
985                     {
986                         *status = OVERFLOW_ERR;
987                         output[ii] = 0;
988                     }
989                     else if (dvalue > DUINT_MAX)
990                     {
991                         *status = OVERFLOW_ERR;
992                         output[ii] = UINT_MAX;
993                     }
994                     else
995                         output[ii] = (unsigned int) dvalue;
996                 }
997             }
998         }
999     }
1000     return(*status);
1001 }
1002 /*--------------------------------------------------------------------------*/
fffi2uint(short * input,long ntodo,double scale,double zero,int nullcheck,short tnull,unsigned int nullval,char * nullarray,int * anynull,unsigned int * output,int * status)1003 int fffi2uint(short *input,        /* I - array of values to be converted     */
1004             long ntodo,           /* I - number of elements in the array     */
1005             double scale,         /* I - FITS TSCALn or BSCALE value         */
1006             double zero,          /* I - FITS TZEROn or BZERO  value         */
1007             int nullcheck,        /* I - null checking code; 0 = don't check */
1008                                   /*     1:set null pixels = nullval         */
1009                                   /*     2: if null pixel, set nullarray = 1 */
1010             short tnull,          /* I - value of FITS TNULLn keyword if any */
1011    unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
1012             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1013             int  *anynull,        /* O - set to 1 if any pixels are null     */
1014    unsigned int  *output,         /* O - array of converted pixels           */
1015             int *status)          /* IO - error status                       */
1016 /*
1017   Copy input to output following reading of the input from a FITS file.
1018   Check for null values and do datatype conversion and scaling if required.
1019   The nullcheck code value determines how any null values in the input array
1020   are treated.  A null value is an input pixel that is equal to tnull.  If
1021   nullcheck = 0, then no checking for nulls is performed and any null values
1022   will be transformed just like any other pixel.  If nullcheck = 1, then the
1023   output pixel will be set = nullval if the corresponding input pixel is null.
1024   If nullcheck = 2, then if the pixel is null then the corresponding value of
1025   nullarray will be set to 1; the value of nullarray for non-null pixels
1026   will = 0.  The anynull parameter will be set = 1 if any of the returned
1027   pixels are null, otherwise anynull will be returned with a value = 0;
1028 */
1029 {
1030     long ii;
1031     double dvalue;
1032 
1033     if (nullcheck == 0)     /* no null checking required */
1034     {
1035         if (scale == 1. && zero == 0.)      /* no scaling */
1036         {
1037             for (ii = 0; ii < ntodo; ii++)
1038             {
1039                 if (input[ii] < 0)
1040                 {
1041                     *status = OVERFLOW_ERR;
1042                     output[ii] = 0;
1043                 }
1044                 else
1045                     output[ii] = (unsigned int) input[ii];
1046             }
1047         }
1048         else             /* must scale the data */
1049         {
1050             for (ii = 0; ii < ntodo; ii++)
1051             {
1052                 dvalue = input[ii] * scale + zero;
1053 
1054                 if (dvalue < DUINT_MIN)
1055                 {
1056                     *status = OVERFLOW_ERR;
1057                     output[ii] = 0;
1058                 }
1059                 else if (dvalue > DUINT_MAX)
1060                 {
1061                     *status = OVERFLOW_ERR;
1062                     output[ii] = UINT_MAX;
1063                 }
1064                 else
1065                     output[ii] = (unsigned int) dvalue;
1066             }
1067         }
1068     }
1069     else        /* must check for null values */
1070     {
1071         if (scale == 1. && zero == 0.)  /* no scaling */
1072         {
1073             for (ii = 0; ii < ntodo; ii++)
1074             {
1075                 if (input[ii] == tnull)
1076                 {
1077                     *anynull = 1;
1078                     if (nullcheck == 1)
1079                         output[ii] = nullval;
1080                     else
1081                         nullarray[ii] = 1;
1082                 }
1083                 else
1084                 {
1085                     if (input[ii] < 0)
1086                     {
1087                         *status = OVERFLOW_ERR;
1088                         output[ii] = 0;
1089                     }
1090                     else
1091                         output[ii] = (unsigned int) input[ii];
1092                 }
1093             }
1094         }
1095         else                  /* must scale the data */
1096         {
1097             for (ii = 0; ii < ntodo; ii++)
1098             {
1099                 if (input[ii] == tnull)
1100                 {
1101                     *anynull = 1;
1102                     if (nullcheck == 1)
1103                         output[ii] = nullval;
1104                     else
1105                         nullarray[ii] = 1;
1106                 }
1107                 else
1108                 {
1109                     dvalue = input[ii] * scale + zero;
1110 
1111                     if (dvalue < DUINT_MIN)
1112                     {
1113                         *status = OVERFLOW_ERR;
1114                         output[ii] = 0;
1115                     }
1116                     else if (dvalue > DUINT_MAX)
1117                     {
1118                         *status = OVERFLOW_ERR;
1119                         output[ii] = UINT_MAX;
1120                     }
1121                     else
1122                         output[ii] = (unsigned int) dvalue;
1123                 }
1124             }
1125         }
1126     }
1127     return(*status);
1128 }
1129 /*--------------------------------------------------------------------------*/
fffi4uint(INT32BIT * input,long ntodo,double scale,double zero,int nullcheck,INT32BIT tnull,unsigned int nullval,char * nullarray,int * anynull,unsigned int * output,int * status)1130 int fffi4uint(INT32BIT *input,    /* I - array of values to be converted     */
1131             long ntodo,           /* I - number of elements in the array     */
1132             double scale,         /* I - FITS TSCALn or BSCALE value         */
1133             double zero,          /* I - FITS TZEROn or BZERO  value         */
1134             int nullcheck,        /* I - null checking code; 0 = don't check */
1135                                   /*     1:set null pixels = nullval         */
1136                                   /*     2: if null pixel, set nullarray = 1 */
1137             INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
1138    unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
1139             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1140             int  *anynull,        /* O - set to 1 if any pixels are null     */
1141    unsigned int  *output,         /* O - array of converted pixels           */
1142             int *status)          /* IO - error status                       */
1143 /*
1144   Copy input to output following reading of the input from a FITS file.
1145   Check for null values and do datatype conversion and scaling if required.
1146   The nullcheck code value determines how any null values in the input array
1147   are treated.  A null value is an input pixel that is equal to tnull.  If
1148   nullcheck = 0, then no checking for nulls is performed and any null values
1149   will be transformed just like any other pixel.  If nullcheck = 1, then the
1150   output pixel will be set = nullval if the corresponding input pixel is null.
1151   If nullcheck = 2, then if the pixel is null then the corresponding value of
1152   nullarray will be set to 1; the value of nullarray for non-null pixels
1153   will = 0.  The anynull parameter will be set = 1 if any of the returned
1154   pixels are null, otherwise anynull will be returned with a value = 0;
1155 */
1156 {
1157     long ii;
1158     double dvalue;
1159 
1160     if (nullcheck == 0)     /* no null checking required */
1161     {
1162         if (scale == 1. && zero == 2147483648.)
1163         {
1164            /* Instead of adding 2147483648, it is more efficient */
1165            /* to just flip the sign bit with the XOR operator */
1166 
1167             for (ii = 0; ii < ntodo; ii++)
1168                output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
1169         }
1170         else if (scale == 1. && zero == 0.)      /* no scaling */
1171         {
1172             for (ii = 0; ii < ntodo; ii++)
1173             {
1174                 if (input[ii] < 0)
1175                 {
1176                     *status = OVERFLOW_ERR;
1177                     output[ii] = 0;
1178                 }
1179                 else
1180                     output[ii] = (unsigned int) input[ii]; /* copy to output */
1181             }
1182         }
1183         else             /* must scale the data */
1184         {
1185             for (ii = 0; ii < ntodo; ii++)
1186             {
1187                 dvalue = input[ii] * scale + zero;
1188 
1189                 if (dvalue < DUINT_MIN)
1190                 {
1191                     *status = OVERFLOW_ERR;
1192                     output[ii] = 0;
1193                 }
1194                 else if (dvalue > DUINT_MAX)
1195                 {
1196                     *status = OVERFLOW_ERR;
1197                     output[ii] = UINT_MAX;
1198                 }
1199                 else
1200                     output[ii] = (unsigned int) dvalue;
1201             }
1202         }
1203     }
1204     else        /* must check for null values */
1205     {
1206         if (scale == 1. && zero == 2147483648.)
1207         {
1208             for (ii = 0; ii < ntodo; ii++)
1209             {
1210                 if (input[ii] == tnull)
1211                 {
1212                     *anynull = 1;
1213                     if (nullcheck == 1)
1214                         output[ii] = nullval;
1215                     else
1216                         nullarray[ii] = 1;
1217                 }
1218                 else
1219                    output[ii] =  ( *(unsigned int *) &input[ii] ) ^ 0x80000000;
1220             }
1221         }
1222         else if (scale == 1. && zero == 0.)  /* no scaling */
1223         {
1224             for (ii = 0; ii < ntodo; ii++)
1225             {
1226                 if (input[ii] == tnull)
1227                 {
1228                     *anynull = 1;
1229                     if (nullcheck == 1)
1230                         output[ii] = nullval;
1231                     else
1232                         nullarray[ii] = 1;
1233                 }
1234                 else if (input[ii] < 0)
1235                 {
1236                     *status = OVERFLOW_ERR;
1237                     output[ii] = 0;
1238                 }
1239                 else
1240                     output[ii] = (unsigned int) input[ii];
1241             }
1242         }
1243         else                  /* must scale the data */
1244         {
1245             for (ii = 0; ii < ntodo; ii++)
1246             {
1247                 if (input[ii] == tnull)
1248                 {
1249                     *anynull = 1;
1250                     if (nullcheck == 1)
1251                         output[ii] = nullval;
1252                     else
1253                         nullarray[ii] = 1;
1254                 }
1255                 else
1256                 {
1257                     dvalue = input[ii] * scale + zero;
1258 
1259                     if (dvalue < DUINT_MIN)
1260                     {
1261                         *status = OVERFLOW_ERR;
1262                         output[ii] = 0;
1263                     }
1264                     else if (dvalue > DUINT_MAX)
1265                     {
1266                         *status = OVERFLOW_ERR;
1267                         output[ii] = UINT_MAX;
1268                     }
1269                     else
1270                         output[ii] = (unsigned int) dvalue;
1271                 }
1272             }
1273         }
1274     }
1275     return(*status);
1276 }
1277 /*--------------------------------------------------------------------------*/
fffi8uint(LONGLONG * input,long ntodo,double scale,double zero,int nullcheck,LONGLONG tnull,unsigned int nullval,char * nullarray,int * anynull,unsigned int * output,int * status)1278 int fffi8uint(LONGLONG *input,    /* I - array of values to be converted     */
1279             long ntodo,           /* I - number of elements in the array     */
1280             double scale,         /* I - FITS TSCALn or BSCALE value         */
1281             double zero,          /* I - FITS TZEROn or BZERO  value         */
1282             int nullcheck,        /* I - null checking code; 0 = don't check */
1283                                   /*     1:set null pixels = nullval         */
1284                                   /*     2: if null pixel, set nullarray = 1 */
1285             LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
1286    unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
1287             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1288             int  *anynull,        /* O - set to 1 if any pixels are null     */
1289    unsigned int  *output,         /* O - array of converted pixels           */
1290             int *status)          /* IO - error status                       */
1291 /*
1292   Copy input to output following reading of the input from a FITS file.
1293   Check for null values and do datatype conversion and scaling if required.
1294   The nullcheck code value determines how any null values in the input array
1295   are treated.  A null value is an input pixel that is equal to tnull.  If
1296   nullcheck = 0, then no checking for nulls is performed and any null values
1297   will be transformed just like any other pixel.  If nullcheck = 1, then the
1298   output pixel will be set = nullval if the corresponding input pixel is null.
1299   If nullcheck = 2, then if the pixel is null then the corresponding value of
1300   nullarray will be set to 1; the value of nullarray for non-null pixels
1301   will = 0.  The anynull parameter will be set = 1 if any of the returned
1302   pixels are null, otherwise anynull will be returned with a value = 0;
1303 */
1304 {
1305     long ii;
1306     double dvalue;
1307     ULONGLONG ulltemp;
1308 
1309     if (nullcheck == 0)     /* no null checking required */
1310     {
1311         if (scale == 1. && zero ==  9223372036854775808.)
1312         {
1313             /* The column we read contains unsigned long long values. */
1314             /* Instead of adding 9223372036854775808, it is more efficient */
1315             /* and more precise to just flip the sign bit with the XOR operator */
1316 
1317             for (ii = 0; ii < ntodo; ii++) {
1318 
1319                 ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
1320 
1321                 if (ulltemp > UINT_MAX)
1322                 {
1323                     *status = OVERFLOW_ERR;
1324                     output[ii] = UINT_MAX;
1325                 }
1326                 else
1327                     output[ii] = (unsigned int) ulltemp;
1328             }
1329         }
1330         else if (scale == 1. && zero == 0.)      /* no scaling */
1331         {
1332             for (ii = 0; ii < ntodo; ii++)
1333             {
1334                 if (input[ii] < 0)
1335                 {
1336                     *status = OVERFLOW_ERR;
1337                     output[ii] = 0;
1338                 }
1339                 else if (input[ii] > UINT_MAX)
1340                 {
1341                     *status = OVERFLOW_ERR;
1342                     output[ii] = UINT_MAX;
1343                 }
1344                 else
1345                     output[ii] = (unsigned int) input[ii];
1346             }
1347         }
1348         else             /* must scale the data */
1349         {
1350             for (ii = 0; ii < ntodo; ii++)
1351             {
1352                 dvalue = input[ii] * scale + zero;
1353 
1354                 if (dvalue < DUINT_MIN)
1355                 {
1356                     *status = OVERFLOW_ERR;
1357                     output[ii] = 0;
1358                 }
1359                 else if (dvalue > DUINT_MAX)
1360                 {
1361                     *status = OVERFLOW_ERR;
1362                     output[ii] = UINT_MAX;
1363                 }
1364                 else
1365                     output[ii] = (unsigned int) dvalue;
1366             }
1367         }
1368     }
1369     else        /* must check for null values */
1370     {
1371         if (scale == 1. && zero ==  9223372036854775808.)
1372         {
1373             /* The column we read contains unsigned long long values. */
1374             /* Instead of adding 9223372036854775808, it is more efficient */
1375             /* and more precise to just flip the sign bit with the XOR operator */
1376 
1377             for (ii = 0; ii < ntodo; ii++) {
1378 
1379                 if (input[ii] == tnull)
1380                 {
1381                     *anynull = 1;
1382                     if (nullcheck == 1)
1383                         output[ii] = nullval;
1384                     else
1385                         nullarray[ii] = 1;
1386                 }
1387                 else
1388                 {
1389                     ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
1390 
1391                     if (ulltemp > UINT_MAX)
1392                     {
1393                         *status = OVERFLOW_ERR;
1394                         output[ii] = UINT_MAX;
1395                     }
1396                     else
1397 		    {
1398                         output[ii] = (unsigned int) ulltemp;
1399 		    }
1400                 }
1401             }
1402         }
1403         else if (scale == 1. && zero == 0.)  /* no scaling */
1404         {
1405             for (ii = 0; ii < ntodo; ii++)
1406             {
1407                 if (input[ii] == tnull)
1408                 {
1409                     *anynull = 1;
1410                     if (nullcheck == 1)
1411                         output[ii] = nullval;
1412                     else
1413                         nullarray[ii] = 1;
1414                 }
1415                 else
1416                 {
1417                     if (input[ii] < 0)
1418                     {
1419                         *status = OVERFLOW_ERR;
1420                         output[ii] = 0;
1421                     }
1422                     else if (input[ii] > UINT_MAX)
1423                     {
1424                         *status = OVERFLOW_ERR;
1425                         output[ii] = UINT_MAX;
1426                     }
1427                     else
1428                         output[ii] = (unsigned int) input[ii];
1429                 }
1430             }
1431         }
1432         else                  /* must scale the data */
1433         {
1434             for (ii = 0; ii < ntodo; ii++)
1435             {
1436                 if (input[ii] == tnull)
1437                 {
1438                     *anynull = 1;
1439                     if (nullcheck == 1)
1440                         output[ii] = nullval;
1441                     else
1442                         nullarray[ii] = 1;
1443                 }
1444                 else
1445                 {
1446                     dvalue = input[ii] * scale + zero;
1447 
1448                     if (dvalue < DUINT_MIN)
1449                     {
1450                         *status = OVERFLOW_ERR;
1451                         output[ii] = 0;
1452                     }
1453                     else if (dvalue > DUINT_MAX)
1454                     {
1455                         *status = OVERFLOW_ERR;
1456                         output[ii] = UINT_MAX;
1457                     }
1458                     else
1459                         output[ii] = (unsigned int) dvalue;
1460                 }
1461             }
1462         }
1463     }
1464     return(*status);
1465 }
1466 /*--------------------------------------------------------------------------*/
fffr4uint(float * input,long ntodo,double scale,double zero,int nullcheck,unsigned int nullval,char * nullarray,int * anynull,unsigned int * output,int * status)1467 int fffr4uint(float *input,        /* I - array of values to be converted     */
1468             long ntodo,           /* I - number of elements in the array     */
1469             double scale,         /* I - FITS TSCALn or BSCALE value         */
1470             double zero,          /* I - FITS TZEROn or BZERO  value         */
1471             int nullcheck,        /* I - null checking code; 0 = don't check */
1472                                   /*     1:set null pixels = nullval         */
1473                                   /*     2: if null pixel, set nullarray = 1 */
1474    unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
1475             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1476             int  *anynull,        /* O - set to 1 if any pixels are null     */
1477    unsigned int  *output,         /* O - array of converted pixels           */
1478             int *status)          /* IO - error status                       */
1479 /*
1480   Copy input to output following reading of the input from a FITS file.
1481   Check for null values and do datatype conversion and scaling if required.
1482   The nullcheck code value determines how any null values in the input array
1483   are treated.  A null value is an input pixel that is equal to NaN.  If
1484   nullcheck = 0, then no checking for nulls is performed and any null values
1485   will be transformed just like any other pixel.  If nullcheck = 1, then the
1486   output pixel will be set = nullval if the corresponding input pixel is null.
1487   If nullcheck = 2, then if the pixel is null then the corresponding value of
1488   nullarray will be set to 1; the value of nullarray for non-null pixels
1489   will = 0.  The anynull parameter will be set = 1 if any of the returned
1490   pixels are null, otherwise anynull will be returned with a value = 0;
1491 */
1492 {
1493     long ii;
1494     double dvalue;
1495     short *sptr, iret;
1496 
1497     if (nullcheck == 0)     /* no null checking required */
1498     {
1499         if (scale == 1. && zero == 0.)      /* no scaling */
1500         {
1501             for (ii = 0; ii < ntodo; ii++)
1502             {
1503                 if (input[ii] < DUINT_MIN)
1504                 {
1505                     *status = OVERFLOW_ERR;
1506                     output[ii] = 0;
1507                 }
1508                 else if (input[ii] > DUINT_MAX)
1509                 {
1510                     *status = OVERFLOW_ERR;
1511                     output[ii] = UINT_MAX;
1512                 }
1513                 else
1514                     output[ii] = (unsigned int) input[ii];
1515             }
1516         }
1517         else             /* must scale the data */
1518         {
1519             for (ii = 0; ii < ntodo; ii++)
1520             {
1521                 dvalue = input[ii] * scale + zero;
1522 
1523                 if (dvalue < DUINT_MIN)
1524                 {
1525                     *status = OVERFLOW_ERR;
1526                     output[ii] = 0;
1527                 }
1528                 else if (dvalue > DUINT_MAX)
1529                 {
1530                     *status = OVERFLOW_ERR;
1531                     output[ii] = UINT_MAX;
1532                 }
1533                 else
1534                     output[ii] = (unsigned int) dvalue;
1535             }
1536         }
1537     }
1538     else        /* must check for null values */
1539     {
1540         sptr = (short *) input;
1541 
1542 #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
1543         sptr++;       /* point to MSBs */
1544 #endif
1545 
1546         if (scale == 1. && zero == 0.)  /* no scaling */
1547         {
1548             for (ii = 0; ii < ntodo; ii++, sptr += 2)
1549             {
1550               if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
1551               {
1552                   if (iret == 1)  /* is it a NaN? */
1553                   {
1554                     *anynull = 1;
1555                     if (nullcheck == 1)
1556                         output[ii] = nullval;
1557                     else
1558                         nullarray[ii] = 1;
1559                   }
1560                   else            /* it's an underflow */
1561                      output[ii] = 0;
1562               }
1563               else
1564                 {
1565                     if (input[ii] < DUINT_MIN)
1566                     {
1567                         *status = OVERFLOW_ERR;
1568                         output[ii] = 0;
1569                     }
1570                     else if (input[ii] > DUINT_MAX)
1571                     {
1572                         *status = OVERFLOW_ERR;
1573                         output[ii] = UINT_MAX;
1574                     }
1575                     else
1576                         output[ii] = (unsigned int) input[ii];
1577                 }
1578             }
1579         }
1580         else                  /* must scale the data */
1581         {
1582             for (ii = 0; ii < ntodo; ii++, sptr += 2)
1583             {
1584               if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
1585               {
1586                   if (iret == 1)  /* is it a NaN? */
1587                   {
1588                     *anynull = 1;
1589                     if (nullcheck == 1)
1590                         output[ii] = nullval;
1591                     else
1592                         nullarray[ii] = 1;
1593                   }
1594                   else            /* it's an underflow */
1595                   {
1596                     if (zero < DUINT_MIN)
1597                     {
1598                         *status = OVERFLOW_ERR;
1599                         output[ii] = 0;
1600                     }
1601                     else if (zero > DUINT_MAX)
1602                     {
1603                         *status = OVERFLOW_ERR;
1604                         output[ii] = UINT_MAX;
1605                     }
1606                     else
1607                       output[ii] = (unsigned int) zero;
1608                   }
1609               }
1610               else
1611                 {
1612                     dvalue = input[ii] * scale + zero;
1613 
1614                     if (dvalue < DUINT_MIN)
1615                     {
1616                         *status = OVERFLOW_ERR;
1617                         output[ii] = 0;
1618                     }
1619                     else if (dvalue > DUINT_MAX)
1620                     {
1621                         *status = OVERFLOW_ERR;
1622                         output[ii] = UINT_MAX;
1623                     }
1624                     else
1625                         output[ii] = (unsigned int) dvalue;
1626                 }
1627             }
1628         }
1629     }
1630     return(*status);
1631 }
1632 /*--------------------------------------------------------------------------*/
fffr8uint(double * input,long ntodo,double scale,double zero,int nullcheck,unsigned int nullval,char * nullarray,int * anynull,unsigned int * output,int * status)1633 int fffr8uint(double *input,       /* I - array of values to be converted     */
1634             long ntodo,           /* I - number of elements in the array     */
1635             double scale,         /* I - FITS TSCALn or BSCALE value         */
1636             double zero,          /* I - FITS TZEROn or BZERO  value         */
1637             int nullcheck,        /* I - null checking code; 0 = don't check */
1638                                   /*     1:set null pixels = nullval         */
1639                                   /*     2: if null pixel, set nullarray = 1 */
1640    unsigned int  nullval,         /* I - set null pixels, if nullcheck = 1   */
1641             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1642             int  *anynull,        /* O - set to 1 if any pixels are null     */
1643    unsigned int  *output,         /* O - array of converted pixels           */
1644             int *status)          /* IO - error status                       */
1645 /*
1646   Copy input to output following reading of the input from a FITS file.
1647   Check for null values and do datatype conversion and scaling if required.
1648   The nullcheck code value determines how any null values in the input array
1649   are treated.  A null value is an input pixel that is equal to NaN.  If
1650   nullcheck = 0, then no checking for nulls is performed and any null values
1651   will be transformed just like any other pixel.  If nullcheck = 1, then the
1652   output pixel will be set = nullval if the corresponding input pixel is null.
1653   If nullcheck = 2, then if the pixel is null then the corresponding value of
1654   nullarray will be set to 1; the value of nullarray for non-null pixels
1655   will = 0.  The anynull parameter will be set = 1 if any of the returned
1656   pixels are null, otherwise anynull will be returned with a value = 0;
1657 */
1658 {
1659     long ii;
1660     double dvalue;
1661     short *sptr, iret;
1662 
1663     if (nullcheck == 0)     /* no null checking required */
1664     {
1665         if (scale == 1. && zero == 0.)      /* no scaling */
1666         {
1667             for (ii = 0; ii < ntodo; ii++)
1668             {
1669                 if (input[ii] < DUINT_MIN)
1670                 {
1671                     *status = OVERFLOW_ERR;
1672                     output[ii] = 0;
1673                 }
1674                 else if (input[ii] > DUINT_MAX)
1675                 {
1676                     *status = OVERFLOW_ERR;
1677                     output[ii] = UINT_MAX;
1678                 }
1679                 else
1680                     output[ii] = (unsigned int) input[ii];
1681             }
1682         }
1683         else             /* must scale the data */
1684         {
1685             for (ii = 0; ii < ntodo; ii++)
1686             {
1687                 dvalue = input[ii] * scale + zero;
1688 
1689                 if (dvalue < DUINT_MIN)
1690                 {
1691                     *status = OVERFLOW_ERR;
1692                     output[ii] = 0;
1693                 }
1694                 else if (dvalue > DUINT_MAX)
1695                 {
1696                     *status = OVERFLOW_ERR;
1697                     output[ii] = UINT_MAX;
1698                 }
1699                 else
1700                     output[ii] = (unsigned int) dvalue;
1701             }
1702         }
1703     }
1704     else        /* must check for null values */
1705     {
1706         sptr = (short *) input;
1707 
1708 #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
1709         sptr += 3;       /* point to MSBs */
1710 #endif
1711         if (scale == 1. && zero == 0.)  /* no scaling */
1712         {
1713             for (ii = 0; ii < ntodo; ii++, sptr += 4)
1714             {
1715               if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
1716               {
1717                   if (iret == 1)  /* is it a NaN? */
1718                   {
1719                     *anynull = 1;
1720                     if (nullcheck == 1)
1721                         output[ii] = nullval;
1722                     else
1723                         nullarray[ii] = 1;
1724                   }
1725                   else            /* it's an underflow */
1726                      output[ii] = 0;
1727               }
1728               else
1729                 {
1730                     if (input[ii] < DUINT_MIN)
1731                     {
1732                         *status = OVERFLOW_ERR;
1733                         output[ii] = 0;
1734                     }
1735                     else if (input[ii] > DUINT_MAX)
1736                     {
1737                         *status = OVERFLOW_ERR;
1738                         output[ii] = UINT_MAX;
1739                     }
1740                     else
1741                         output[ii] = (unsigned int) input[ii];
1742                 }
1743             }
1744         }
1745         else                  /* must scale the data */
1746         {
1747             for (ii = 0; ii < ntodo; ii++, sptr += 4)
1748             {
1749               if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
1750               {
1751                   if (iret == 1)  /* is it a NaN? */
1752                   {
1753                     *anynull = 1;
1754                     if (nullcheck == 1)
1755                         output[ii] = nullval;
1756                     else
1757                         nullarray[ii] = 1;
1758                   }
1759                   else            /* it's an underflow */
1760                   {
1761                     if (zero < DUINT_MIN)
1762                     {
1763                         *status = OVERFLOW_ERR;
1764                         output[ii] = 0;
1765                     }
1766                     else if (zero > DUINT_MAX)
1767                     {
1768                         *status = OVERFLOW_ERR;
1769                         output[ii] = UINT_MAX;
1770                     }
1771                     else
1772                       output[ii] = (unsigned int) zero;
1773                   }
1774               }
1775               else
1776                 {
1777                     dvalue = input[ii] * scale + zero;
1778 
1779                     if (dvalue < DUINT_MIN)
1780                     {
1781                         *status = OVERFLOW_ERR;
1782                         output[ii] = 0;
1783                     }
1784                     else if (dvalue > DUINT_MAX)
1785                     {
1786                         *status = OVERFLOW_ERR;
1787                         output[ii] = UINT_MAX;
1788                     }
1789                     else
1790                         output[ii] = (unsigned int) dvalue;
1791                 }
1792             }
1793         }
1794     }
1795     return(*status);
1796 }
1797 /*--------------------------------------------------------------------------*/
fffstruint(char * input,long ntodo,double scale,double zero,long twidth,double implipower,int nullcheck,char * snull,unsigned int nullval,char * nullarray,int * anynull,unsigned int * output,int * status)1798 int fffstruint(char *input,        /* I - array of values to be converted     */
1799             long ntodo,           /* I - number of elements in the array     */
1800             double scale,         /* I - FITS TSCALn or BSCALE value         */
1801             double zero,          /* I - FITS TZEROn or BZERO  value         */
1802             long twidth,          /* I - width of each substring of chars    */
1803             double implipower,    /* I - power of 10 of implied decimal      */
1804             int nullcheck,        /* I - null checking code; 0 = don't check */
1805                                   /*     1:set null pixels = nullval         */
1806                                   /*     2: if null pixel, set nullarray = 1 */
1807             char  *snull,         /* I - value of FITS null string, if any   */
1808    unsigned int nullval,          /* I - set null pixels, if nullcheck = 1   */
1809             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1810             int  *anynull,        /* O - set to 1 if any pixels are null     */
1811    unsigned int *output,          /* O - array of converted pixels           */
1812             int *status)          /* IO - error status                       */
1813 /*
1814   Copy input to output following reading of the input from a FITS file. Check
1815   for null values and do scaling if required. The nullcheck code value
1816   determines how any null values in the input array are treated. A null
1817   value is an input pixel that is equal to snull.  If nullcheck= 0, then
1818   no special checking for nulls is performed.  If nullcheck = 1, then the
1819   output pixel will be set = nullval if the corresponding input pixel is null.
1820   If nullcheck = 2, then if the pixel is null then the corresponding value of
1821   nullarray will be set to 1; the value of nullarray for non-null pixels
1822   will = 0.  The anynull parameter will be set = 1 if any of the returned
1823   pixels are null, otherwise anynull will be returned with a value = 0;
1824 */
1825 {
1826     int nullen;
1827     long ii;
1828     double dvalue;
1829     char *cstring, message[FLEN_ERRMSG];
1830     char *cptr, *tpos;
1831     char tempstore, chrzero = '0';
1832     double val, power;
1833     int exponent, sign, esign, decpt;
1834 
1835     nullen = strlen(snull);
1836     cptr = input;  /* pointer to start of input string */
1837     for (ii = 0; ii < ntodo; ii++)
1838     {
1839       cstring = cptr;
1840       /* temporarily insert a null terminator at end of the string */
1841       tpos = cptr + twidth;
1842       tempstore = *tpos;
1843       *tpos = 0;
1844 
1845       /* check if null value is defined, and if the    */
1846       /* column string is identical to the null string */
1847       if (snull[0] != ASCII_NULL_UNDEFINED &&
1848          !strncmp(snull, cptr, nullen) )
1849       {
1850         if (nullcheck)
1851         {
1852           *anynull = 1;
1853           if (nullcheck == 1)
1854             output[ii] = nullval;
1855           else
1856             nullarray[ii] = 1;
1857         }
1858         cptr += twidth;
1859       }
1860       else
1861       {
1862         /* value is not the null value, so decode it */
1863         /* remove any embedded blank characters from the string */
1864 
1865         decpt = 0;
1866         sign = 1;
1867         val  = 0.;
1868         power = 1.;
1869         exponent = 0;
1870         esign = 1;
1871 
1872         while (*cptr == ' ')               /* skip leading blanks */
1873            cptr++;
1874 
1875         if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
1876         {
1877           if (*cptr == '-')
1878              sign = -1;
1879 
1880           cptr++;
1881 
1882           while (*cptr == ' ')         /* skip blanks between sign and value */
1883             cptr++;
1884         }
1885 
1886         while (*cptr >= '0' && *cptr <= '9')
1887         {
1888           val = val * 10. + *cptr - chrzero;  /* accumulate the value */
1889           cptr++;
1890 
1891           while (*cptr == ' ')         /* skip embedded blanks in the value */
1892             cptr++;
1893         }
1894 
1895         if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
1896         {
1897           decpt = 1;       /* set flag to show there was a decimal point */
1898           cptr++;
1899           while (*cptr == ' ')         /* skip any blanks */
1900             cptr++;
1901 
1902           while (*cptr >= '0' && *cptr <= '9')
1903           {
1904             val = val * 10. + *cptr - chrzero;  /* accumulate the value */
1905             power = power * 10.;
1906             cptr++;
1907 
1908             while (*cptr == ' ')         /* skip embedded blanks in the value */
1909               cptr++;
1910           }
1911         }
1912 
1913         if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
1914         {
1915           cptr++;
1916           while (*cptr == ' ')         /* skip blanks */
1917               cptr++;
1918 
1919           if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
1920           {
1921             if (*cptr == '-')
1922                esign = -1;
1923 
1924             cptr++;
1925 
1926             while (*cptr == ' ')        /* skip blanks between sign and exp */
1927               cptr++;
1928           }
1929 
1930           while (*cptr >= '0' && *cptr <= '9')
1931           {
1932             exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
1933             cptr++;
1934 
1935             while (*cptr == ' ')         /* skip embedded blanks */
1936               cptr++;
1937           }
1938         }
1939 
1940         if (*cptr  != 0)  /* should end up at the null terminator */
1941         {
1942           snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
1943           ffpmsg(message);
1944           snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
1945           ffpmsg(message);
1946           /* restore the char that was overwritten by the null */
1947           *tpos = tempstore;
1948           return(*status = BAD_C2D);
1949         }
1950 
1951         if (!decpt)  /* if no explicit decimal, use implied */
1952            power = implipower;
1953 
1954         dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
1955 
1956         dvalue = dvalue * scale + zero;   /* apply the scaling */
1957 
1958         if (dvalue < DUINT_MIN)
1959         {
1960             *status = OVERFLOW_ERR;
1961             output[ii] = 0;
1962         }
1963         else if (dvalue > DUINT_MAX)
1964         {
1965             *status = OVERFLOW_ERR;
1966             output[ii] = UINT_MAX;
1967         }
1968         else
1969             output[ii] = (long) dvalue;
1970       }
1971       /* restore the char that was overwritten by the null */
1972       *tpos = tempstore;
1973     }
1974     return(*status);
1975 }
1976