1 /*  This file, getcolui.c, contains routines that read data elements from   */
2 /*  a FITS image or table, with unsigned short datatype.                    */
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 /*--------------------------------------------------------------------------*/
ffgpvui(fitsfile * fptr,long group,LONGLONG firstelem,LONGLONG nelem,unsigned short nulval,unsigned short * array,int * anynul,int * status)15 int ffgpvui( 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 short nulval,     /* I - value for undefined pixels              */
20    unsigned short *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 short 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, TUSHORT, 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     ffgclui(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
57                array, &cdummy, anynul, status);
58     return(*status);
59 }
60 /*--------------------------------------------------------------------------*/
ffgpfui(fitsfile * fptr,long group,LONGLONG firstelem,LONGLONG nelem,unsigned short * array,char * nularray,int * anynul,int * status)61 int ffgpfui( 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 short *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, TUSHORT, 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     ffgclui(fptr, 2, row, firstelem, nelem, 1, 2, 0,
100                array, nularray, anynul, status);
101     return(*status);
102 }
103 /*--------------------------------------------------------------------------*/
ffg2dui(fitsfile * fptr,long group,unsigned short nulval,LONGLONG ncols,LONGLONG naxis1,LONGLONG naxis2,unsigned short * array,int * anynul,int * status)104 int ffg2dui(fitsfile *fptr,  /* I - FITS file pointer                       */
105            long  group,     /* I - group to read (1 = 1st group)           */
106   unsigned short 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 short *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     ffg3dui(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array,
124            anynul, status);
125 
126     return(*status);
127 }
128 /*--------------------------------------------------------------------------*/
ffg3dui(fitsfile * fptr,long group,unsigned short nulval,LONGLONG ncols,LONGLONG nrows,LONGLONG naxis1,LONGLONG naxis2,LONGLONG naxis3,unsigned short * array,int * anynul,int * status)129 int ffg3dui(fitsfile *fptr,  /* I - FITS file pointer                       */
130            long  group,     /* I - group to read (1 = 1st group)           */
131   unsigned short 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 short *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 short 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, TUSHORT, 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        ffgclui(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 (ffgclui(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 /*--------------------------------------------------------------------------*/
ffgsvui(fitsfile * fptr,int colnum,int naxis,long * naxes,long * blc,long * trc,long * inc,unsigned short nulval,unsigned short * array,int * anynul,int * status)213 int ffgsvui(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 short nulval,   /* I - value to set undefined pixels             */
221   unsigned short *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 short nullvalue;
237 
238     if (naxis < 1 || naxis > 9)
239     {
240         snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvui 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, TUSHORT, 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,"ffgsvui: 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               if ( ffgclui(fptr, numcol, row, felem, nelem, ninc, nultyp,
359                    nulval, &array[i0], &ldummy, &anyf, status) > 0)
360                    return(*status);
361 
362               if (anyf && anynul)
363                   *anynul = TRUE;
364 
365               i0 += nelem;
366             }
367            }
368           }
369          }
370         }
371        }
372       }
373      }
374     }
375     return(*status);
376 }
377 /*--------------------------------------------------------------------------*/
ffgsfui(fitsfile * fptr,int colnum,int naxis,long * naxes,long * blc,long * trc,long * inc,unsigned short * array,char * flagval,int * anynul,int * status)378 int ffgsfui(fitsfile *fptr, /* I - FITS file pointer                         */
379            int  colnum,    /* I - number of the column to read (1 = 1st)    */
380            int naxis,      /* I - number of dimensions in the FITS array    */
381            long  *naxes,   /* I - size of each dimension                    */
382            long  *blc,     /* I - 'bottom left corner' of the subsection    */
383            long  *trc,     /* I - 'top right corner' of the subsection      */
384            long  *inc,     /* I - increment to be applied in each dimension */
385   unsigned short *array,   /* O - array to be filled and returned           */
386            char *flagval,  /* O - set to 1 if corresponding value is null   */
387            int  *anynul,   /* O - set to 1 if any values are null; else 0   */
388            int  *status)   /* IO - error status                             */
389 /*
390   Read a subsection of data values from an image or a table column.
391   This routine is set up to handle a maximum of nine dimensions.
392 */
393 {
394     long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
395     long str[9],stp[9],incr[9],dsize[10];
396     LONGLONG blcll[9], trcll[9];
397     long felem, nelem, nultyp, ninc, numcol;
398     int hdutype, anyf;
399     unsigned short nulval = 0;
400     char msg[FLEN_ERRMSG];
401     int nullcheck = 2;
402 
403     if (naxis < 1 || naxis > 9)
404     {
405         snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvi is out of range", naxis);
406         ffpmsg(msg);
407         return(*status = BAD_DIMEN);
408     }
409 
410     if (fits_is_compressed_image(fptr, status))
411     {
412         /* this is a compressed image in a binary table */
413 
414         for (ii=0; ii < naxis; ii++) {
415 	    blcll[ii] = blc[ii];
416 	    trcll[ii] = trc[ii];
417 	}
418 
419         fits_read_compressed_img(fptr, TUSHORT, blcll, trcll, inc,
420             nullcheck, NULL, array, flagval, anynul, status);
421         return(*status);
422     }
423 
424 /*
425     if this is a primary array, then the input COLNUM parameter should
426     be interpreted as the row number, and we will alway read the image
427     data from column 2 (any group parameters are in column 1).
428 */
429     if (ffghdt(fptr, &hdutype, status) > 0)
430         return(*status);
431 
432     if (hdutype == IMAGE_HDU)
433     {
434         /* this is a primary array, or image extension */
435         if (colnum == 0)
436         {
437             rstr = 1;
438             rstp = 1;
439         }
440         else
441         {
442             rstr = colnum;
443             rstp = colnum;
444         }
445         rinc = 1;
446         numcol = 2;
447     }
448     else
449     {
450         /* this is a table, so the row info is in the (naxis+1) elements */
451         rstr = blc[naxis];
452         rstp = trc[naxis];
453         rinc = inc[naxis];
454         numcol = colnum;
455     }
456 
457     nultyp = 2;
458     if (anynul)
459         *anynul = FALSE;
460 
461     i0 = 0;
462     for (ii = 0; ii < 9; ii++)
463     {
464         str[ii] = 1;
465         stp[ii] = 1;
466         incr[ii] = 1;
467         dsize[ii] = 1;
468     }
469 
470     for (ii = 0; ii < naxis; ii++)
471     {
472       if (trc[ii] < blc[ii])
473       {
474         snprintf(msg, FLEN_ERRMSG,"ffgsvi: illegal range specified for axis %ld", ii + 1);
475         ffpmsg(msg);
476         return(*status = BAD_PIX_NUM);
477       }
478 
479       str[ii] = blc[ii];
480       stp[ii] = trc[ii];
481       incr[ii] = inc[ii];
482       dsize[ii + 1] = dsize[ii] * naxes[ii];
483     }
484 
485     if (naxis == 1 && naxes[0] == 1)
486     {
487       /* This is not a vector column, so read all the rows at once */
488       nelem = (rstp - rstr) / rinc + 1;
489       ninc = rinc;
490       rstp = rstr;
491     }
492     else
493     {
494       /* have to read each row individually, in all dimensions */
495       nelem = (stp[0] - str[0]) / inc[0] + 1;
496       ninc = incr[0];
497     }
498 
499     for (row = rstr; row <= rstp; row += rinc)
500     {
501      for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
502      {
503       for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
504       {
505        for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
506        {
507         for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
508         {
509          for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
510          {
511           for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
512           {
513            for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
514            {
515             for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
516             {
517               felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] +
518                              (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
519                              (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
520                              (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
521 
522               if ( ffgclui(fptr, numcol, row, felem, nelem, ninc, nultyp,
523                    nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
524                    return(*status);
525 
526               if (anyf && anynul)
527                   *anynul = TRUE;
528 
529               i0 += nelem;
530             }
531            }
532           }
533          }
534         }
535        }
536       }
537      }
538     }
539     return(*status);
540 }
541 /*--------------------------------------------------------------------------*/
ffggpui(fitsfile * fptr,long group,long firstelem,long nelem,unsigned short * array,int * status)542 int ffggpui( fitsfile *fptr,   /* I - FITS file pointer                       */
543             long  group,      /* I - group to read (1 = 1st group)           */
544             long  firstelem,  /* I - first vector element to read (1 = 1st)  */
545             long  nelem,      /* I - number of values to read                */
546    unsigned short *array,     /* O - array of values that are returned       */
547             int  *status)     /* IO - error status                           */
548 /*
549   Read an array of group parameters from the primary array. Data conversion
550   and scaling will be performed if necessary (e.g, if the datatype of
551   the FITS array is not the same as the array being read).
552 */
553 {
554     long row;
555     int idummy;
556     char cdummy;
557     /*
558       the primary array is represented as a binary table:
559       each group of the primary array is a row in the table,
560       where the first column contains the group parameters
561       and the second column contains the image itself.
562     */
563 
564     row=maxvalue(1,group);
565 
566     ffgclui(fptr, 1, row, firstelem, nelem, 1, 1, 0,
567                array, &cdummy, &idummy, status);
568     return(*status);
569 }
570 /*--------------------------------------------------------------------------*/
ffgcvui(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,unsigned short nulval,unsigned short * array,int * anynul,int * status)571 int ffgcvui(fitsfile *fptr,   /* I - FITS file pointer                       */
572            int  colnum,      /* I - number of column to read (1 = 1st col)  */
573            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
574            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
575            LONGLONG  nelem,      /* I - number of values to read                */
576   unsigned short nulval,     /* I - value for null pixels                   */
577   unsigned short *array,     /* O - array of values that are read           */
578            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
579            int  *status)     /* IO - error status                           */
580 /*
581   Read an array of values from a column in the current FITS HDU. Automatic
582   datatype conversion will be performed if the datatype of the column does not
583   match the datatype of the array parameter. The output values will be scaled
584   by the FITS TSCALn and TZEROn values if these values have been defined.
585   Any undefined pixels will be set equal to the value of 'nulval' unless
586   nulval = 0 in which case no checks for undefined pixels will be made.
587 */
588 {
589     char cdummy;
590 
591     ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
592            array, &cdummy, anynul, status);
593     return(*status);
594 }
595 /*--------------------------------------------------------------------------*/
ffgcfui(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,unsigned short * array,char * nularray,int * anynul,int * status)596 int ffgcfui(fitsfile *fptr,   /* I - FITS file pointer                       */
597            int  colnum,      /* I - number of column to read (1 = 1st col)  */
598            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
599            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
600            LONGLONG  nelem,      /* I - number of values to read                */
601   unsigned short *array,     /* O - array of values that are read           */
602            char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
603            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
604            int  *status)     /* IO - error status                           */
605 /*
606   Read an array of values from a column in the current FITS HDU. Automatic
607   datatype conversion will be performed if the datatype of the column does not
608   match the datatype of the array parameter. The output values will be scaled
609   by the FITS TSCALn and TZEROn values if these values have been defined.
610   Nularray will be set = 1 if the corresponding array pixel is undefined,
611   otherwise nularray will = 0.
612 */
613 {
614     unsigned short dummy = 0;
615 
616     ffgclui(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
617            array, nularray, anynul, status);
618     return(*status);
619 }
620 /*--------------------------------------------------------------------------*/
ffgclui(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,long elemincre,int nultyp,unsigned short nulval,unsigned short * array,char * nularray,int * anynul,int * status)621 int ffgclui( fitsfile *fptr,   /* I - FITS file pointer                       */
622             int  colnum,      /* I - number of column to read (1 = 1st col)  */
623             LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
624             LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
625             LONGLONG  nelem,      /* I - number of values to read                */
626             long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
627             int   nultyp,     /* I - null value handling code:               */
628                               /*     1: set undefined pixels = nulval        */
629                               /*     2: set nularray=1 for undefined pixels  */
630    unsigned short nulval,     /* I - value for null pixels if nultyp = 1     */
631    unsigned short *array,     /* O - array of values that are read           */
632             char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
633             int  *anynul,     /* O - set to 1 if any values are null; else 0 */
634             int  *status)     /* IO - error status                           */
635 /*
636   Read an array of values from a column in the current FITS HDU.
637   The column number may refer to a real column in an ASCII or binary table,
638   or it may refer be a virtual column in a 1 or more grouped FITS primary
639   array or image extension.  FITSIO treats a primary array as a binary table
640   with 2 vector columns: the first column contains the group parameters (often
641   with length = 0) and the second column contains the array of image pixels.
642   Each row of the table represents a group in the case of multigroup FITS
643   images.
644 
645   The output array of values will be converted from the datatype of the column
646   and will be scaled by the FITS TSCALn and TZEROn values if necessary.
647 */
648 {
649     double scale, zero, power = 1., dtemp;
650     int tcode, maxelem2, hdutype, xcode, decimals;
651     long twidth, incre;
652     long ii, xwidth, ntodo;
653     int nulcheck;
654     LONGLONG repeat, startpos, elemnum, readptr, tnull;
655     LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
656     char tform[20];
657     char message[FLEN_ERRMSG];
658     char snull[20];   /*  the FITS null value if reading from ASCII table  */
659 
660     double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
661     void *buffer;
662 
663     if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
664         return(*status);
665 
666     buffer = cbuff;
667 
668     if (anynul)
669         *anynul = 0;
670 
671     if (nultyp == 2)
672         memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
673 
674     /*---------------------------------------------------*/
675     /*  Check input and get parameters about the column: */
676     /*---------------------------------------------------*/
677     if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 0, &scale, &zero,
678          tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
679          &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
680          return(*status);
681     maxelem = maxelem2;
682 
683     incre *= elemincre;   /* multiply incre to just get every nth pixel */
684 
685     if (tcode == TSTRING)    /* setup for ASCII tables */
686     {
687       /* get the number of implied decimal places if no explicit decmal point */
688       ffasfm(tform, &xcode, &xwidth, &decimals, status);
689       for(ii = 0; ii < decimals; ii++)
690         power *= 10.;
691     }
692     /*------------------------------------------------------------------*/
693     /*  Decide whether to check for null values in the input FITS file: */
694     /*------------------------------------------------------------------*/
695     nulcheck = nultyp; /* by default check for null values in the FITS file */
696 
697     if (nultyp == 1 && nulval == 0)
698        nulcheck = 0;    /* calling routine does not want to check for nulls */
699 
700     else if (tcode%10 == 1 &&        /* if reading an integer column, and  */
701             tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
702             nulcheck = 0;            /* then do not check for null values. */
703 
704     else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
705             nulcheck = 0;            /* Impossible null value */
706 
707     else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
708             nulcheck = 0;            /* Impossible null value */
709 
710     else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
711          nulcheck = 0;
712 
713     /*----------------------------------------------------------------------*/
714     /*  If FITS column and output data array have same datatype, then we do */
715     /*  not need to use a temporary buffer to store intermediate datatype.  */
716     /*----------------------------------------------------------------------*/
717     if (tcode == TSHORT) /* Special Case:                        */
718     {                             /* no type convertion required, so read */
719                                   /* data directly into output buffer.    */
720 
721         if (nelem < (LONGLONG)INT32_MAX/2) {
722             maxelem = nelem;
723         } else {
724             maxelem = INT32_MAX/2;
725         }
726     }
727 
728     /*---------------------------------------------------------------------*/
729     /*  Now read the pixels from the FITS column. If the column does not   */
730     /*  have the same datatype as the output array, then we have to read   */
731     /*  the raw values into a temporary buffer (of limited size).  In      */
732     /*  the case of a vector colum read only 1 vector of values at a time  */
733     /*  then skip to the next row if more values need to be read.          */
734     /*  After reading the raw values, then call the fffXXYY routine to (1) */
735     /*  test for undefined values, (2) convert the datatype if necessary,  */
736     /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
737     /*  scaling parameters.                                                */
738     /*---------------------------------------------------------------------*/
739     remain = nelem;           /* remaining number of values to read */
740     next = 0;                 /* next element in array to be read   */
741     rownum = 0;               /* row number, relative to firstrow   */
742 
743     while (remain)
744     {
745         /* limit the number of pixels to read at one time to the number that
746            will fit in the buffer or to the number of pixels that remain in
747            the current vector, which ever is smaller.
748         */
749         ntodo = (long) minvalue(remain, maxelem);
750         ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
751 
752         readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
753 
754         switch (tcode)
755         {
756             case (TSHORT):
757                 ffgi2b(fptr, readptr, ntodo, incre,
758                        (short *) &array[next], status);
759                 fffi2u2((short *) &array[next], ntodo, scale,
760                        zero, nulcheck, (short) tnull, nulval, &nularray[next],
761                        anynul, &array[next], status);
762                 break;
763             case (TLONGLONG):
764 
765                 ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
766                 fffi8u2( (LONGLONG *) buffer, ntodo, scale, zero,
767                            nulcheck, tnull, nulval, &nularray[next],
768                             anynul, &array[next], status);
769                 break;
770             case (TBYTE):
771                 ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
772                       status);
773                 fffi1u2((unsigned char *) buffer, ntodo, scale, zero, nulcheck,
774                     (unsigned char) tnull, nulval, &nularray[next], anynul,
775                     &array[next], status);
776                 break;
777             case (TLONG):
778                 ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
779                        status);
780                 fffi4u2((INT32BIT *) buffer, ntodo, scale, zero, nulcheck,
781                        (INT32BIT) tnull, nulval, &nularray[next], anynul,
782                        &array[next], status);
783                 break;
784             case (TFLOAT):
785                 ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
786                 fffr4u2((float  *) buffer, ntodo, scale, zero, nulcheck,
787                        nulval, &nularray[next], anynul,
788                        &array[next], status);
789                 break;
790             case (TDOUBLE):
791                 ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
792                 fffr8u2((double *) buffer, ntodo, scale, zero, nulcheck,
793                           nulval, &nularray[next], anynul,
794                           &array[next], status);
795                 break;
796             case (TSTRING):
797                 ffmbyt(fptr, readptr, REPORT_EOF, status);
798 
799                 if (incre == twidth)    /* contiguous bytes */
800                      ffgbyt(fptr, ntodo * twidth, buffer, status);
801                 else
802                      ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
803                                status);
804 
805                 fffstru2((char *) buffer, ntodo, scale, zero, twidth, power,
806                      nulcheck, snull, nulval, &nularray[next], anynul,
807                      &array[next], status);
808                 break;
809 
810             default:  /*  error trap for invalid column format */
811                 snprintf(message, FLEN_ERRMSG,
812                    "Cannot read numbers from column %d which has format %s",
813                     colnum, tform);
814                 ffpmsg(message);
815                 if (hdutype == ASCII_TBL)
816                     return(*status = BAD_ATABLE_FORMAT);
817                 else
818                     return(*status = BAD_BTABLE_FORMAT);
819 
820         } /* End of switch block */
821 
822         /*-------------------------*/
823         /*  Check for fatal error  */
824         /*-------------------------*/
825         if (*status > 0)  /* test for error during previous read operation */
826         {
827 	  dtemp = (double) next;
828           if (hdutype > 0)
829             snprintf(message,FLEN_ERRMSG,
830             "Error reading elements %.0f thru %.0f from column %d (ffgclui).",
831               dtemp+1., dtemp+ntodo, colnum);
832           else
833             snprintf(message,FLEN_ERRMSG,
834             "Error reading elements %.0f thru %.0f from image (ffgclui).",
835               dtemp+1., dtemp+ntodo);
836 
837           ffpmsg(message);
838           return(*status);
839         }
840 
841         /*--------------------------------------------*/
842         /*  increment the counters for the next loop  */
843         /*--------------------------------------------*/
844         remain -= ntodo;
845         if (remain)
846         {
847             next += ntodo;
848             elemnum = elemnum + (ntodo * elemincre);
849 
850             if (elemnum >= repeat)  /* completed a row; start on later row */
851             {
852                 rowincre = elemnum / repeat;
853                 rownum += rowincre;
854                 elemnum = elemnum - (rowincre * repeat);
855             }
856         }
857     }  /*  End of main while Loop  */
858 
859 
860     /*--------------------------------*/
861     /*  check for numerical overflow  */
862     /*--------------------------------*/
863     if (*status == OVERFLOW_ERR)
864     {
865         ffpmsg(
866         "Numerical overflow during type conversion while reading FITS data.");
867         *status = NUM_OVERFLOW;
868     }
869 
870     return(*status);
871 }
872 /*--------------------------------------------------------------------------*/
fffi1u2(unsigned char * input,long ntodo,double scale,double zero,int nullcheck,unsigned char tnull,unsigned short nullval,char * nullarray,int * anynull,unsigned short * output,int * status)873 int fffi1u2(unsigned char *input, /* I - array of values to be converted     */
874             long ntodo,           /* I - number of elements in the array     */
875             double scale,         /* I - FITS TSCALn or BSCALE value         */
876             double zero,          /* I - FITS TZEROn or BZERO  value         */
877             int nullcheck,        /* I - null checking code; 0 = don't check */
878                                   /*     1:set null pixels = nullval         */
879                                   /*     2: if null pixel, set nullarray = 1 */
880             unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
881    unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
882             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
883             int  *anynull,        /* O - set to 1 if any pixels are null     */
884    unsigned short *output,        /* O - array of converted pixels           */
885             int *status)          /* IO - error status                       */
886 /*
887   Copy input to output following reading of the input from a FITS file.
888   Check for null values and do datatype conversion and scaling if required.
889   The nullcheck code value determines how any null values in the input array
890   are treated.  A null value is an input pixel that is equal to tnull.  If
891   nullcheck = 0, then no checking for nulls is performed and any null values
892   will be transformed just like any other pixel.  If nullcheck = 1, then the
893   output pixel will be set = nullval if the corresponding input pixel is null.
894   If nullcheck = 2, then if the pixel is null then the corresponding value of
895   nullarray will be set to 1; the value of nullarray for non-null pixels
896   will = 0.  The anynull parameter will be set = 1 if any of the returned
897   pixels are null, otherwise anynull will be returned with a value = 0;
898 */
899 {
900     long ii;
901     double dvalue;
902 
903     if (nullcheck == 0)     /* no null checking required */
904     {
905         if (scale == 1. && zero == 0.)      /* no scaling */
906         {
907             for (ii = 0; ii < ntodo; ii++)
908                 output[ii] = (unsigned short) input[ii]; /* copy input */
909         }
910         else             /* must scale the data */
911         {
912             for (ii = 0; ii < ntodo; ii++)
913             {
914                 dvalue = input[ii] * scale + zero;
915 
916                 if (dvalue < DUSHRT_MIN)
917                 {
918                     *status = OVERFLOW_ERR;
919                     output[ii] = 0;
920                 }
921                 else if (dvalue > DUSHRT_MAX)
922                 {
923                     *status = OVERFLOW_ERR;
924                     output[ii] = USHRT_MAX;
925                 }
926                 else
927                     output[ii] = (unsigned short) dvalue;
928             }
929         }
930     }
931     else        /* must check for null values */
932     {
933         if (scale == 1. && zero == 0.)  /* no scaling */
934         {
935             for (ii = 0; ii < ntodo; ii++)
936             {
937                 if (input[ii] == tnull)
938                 {
939                     *anynull = 1;
940                     if (nullcheck == 1)
941                         output[ii] = nullval;
942                     else
943                         nullarray[ii] = 1;
944                 }
945                 else
946                     output[ii] = (unsigned short) input[ii];
947             }
948         }
949         else                  /* must scale the data */
950         {
951             for (ii = 0; ii < ntodo; ii++)
952             {
953                 if (input[ii] == tnull)
954                 {
955                     *anynull = 1;
956                     if (nullcheck == 1)
957                         output[ii] = nullval;
958                     else
959                         nullarray[ii] = 1;
960                 }
961                 else
962                 {
963                     dvalue = input[ii] * scale + zero;
964 
965                     if (dvalue < DUSHRT_MIN)
966                     {
967                         *status = OVERFLOW_ERR;
968                         output[ii] = 0;
969                     }
970                     else if (dvalue > DUSHRT_MAX)
971                     {
972                         *status = OVERFLOW_ERR;
973                         output[ii] = USHRT_MAX;
974                     }
975                     else
976                         output[ii] = (unsigned short) dvalue;
977                 }
978             }
979         }
980     }
981     return(*status);
982 }
983 /*--------------------------------------------------------------------------*/
fffi2u2(short * input,long ntodo,double scale,double zero,int nullcheck,short tnull,unsigned short nullval,char * nullarray,int * anynull,unsigned short * output,int * status)984 int fffi2u2(short *input,         /* I - array of values to be converted     */
985             long ntodo,           /* I - number of elements in the array     */
986             double scale,         /* I - FITS TSCALn or BSCALE value         */
987             double zero,          /* I - FITS TZEROn or BZERO  value         */
988             int nullcheck,        /* I - null checking code; 0 = don't check */
989                                   /*     1:set null pixels = nullval         */
990                                   /*     2: if null pixel, set nullarray = 1 */
991             short tnull,          /* I - value of FITS TNULLn keyword if any */
992    unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
993             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
994             int  *anynull,        /* O - set to 1 if any pixels are null     */
995    unsigned short *output,        /* O - array of converted pixels           */
996             int *status)          /* IO - error status                       */
997 /*
998   Copy input to output following reading of the input from a FITS file.
999   Check for null values and do datatype conversion and scaling if required.
1000   The nullcheck code value determines how any null values in the input array
1001   are treated.  A null value is an input pixel that is equal to tnull.  If
1002   nullcheck = 0, then no checking for nulls is performed and any null values
1003   will be transformed just like any other pixel.  If nullcheck = 1, then the
1004   output pixel will be set = nullval if the corresponding input pixel is null.
1005   If nullcheck = 2, then if the pixel is null then the corresponding value of
1006   nullarray will be set to 1; the value of nullarray for non-null pixels
1007   will = 0.  The anynull parameter will be set = 1 if any of the returned
1008   pixels are null, otherwise anynull will be returned with a value = 0;
1009 */
1010 {
1011     long ii;
1012     double dvalue;
1013 
1014     if (nullcheck == 0)     /* no null checking required */
1015     {
1016         if (scale == 1. && zero == 32768.)
1017         {
1018            /* Instead of adding 32768, it is more efficient */
1019            /* to just flip the sign bit with the XOR operator */
1020 
1021            for (ii = 0; ii < ntodo; ii++)
1022               output[ii] =  ( *(unsigned short *) &input[ii] ) ^ 0x8000;
1023         }
1024         else if (scale == 1. && zero == 0.)      /* no scaling */
1025         {
1026             for (ii = 0; ii < ntodo; ii++)
1027             {
1028                 if (input[ii] < 0)
1029                 {
1030                     *status = OVERFLOW_ERR;
1031                     output[ii] = 0;
1032                 }
1033                 else
1034                     output[ii] = (unsigned short) input[ii]; /* copy input */
1035             }
1036         }
1037         else             /* must scale the data */
1038         {
1039             for (ii = 0; ii < ntodo; ii++)
1040             {
1041                 dvalue = input[ii] * scale + zero;
1042 
1043                 if (dvalue < DUSHRT_MIN)
1044                 {
1045                     *status = OVERFLOW_ERR;
1046                     output[ii] = 0;
1047                 }
1048                 else if (dvalue > DUSHRT_MAX)
1049                 {
1050                     *status = OVERFLOW_ERR;
1051                     output[ii] = USHRT_MAX;
1052                 }
1053                 else
1054                     output[ii] = (unsigned short) dvalue;
1055             }
1056         }
1057     }
1058     else        /* must check for null values */
1059     {
1060         if (scale == 1. && zero == 32768.)  /* no scaling */
1061         {
1062             for (ii = 0; ii < ntodo; ii++)
1063             {
1064                 if (input[ii] == tnull)
1065                 {
1066                     *anynull = 1;
1067                     if (nullcheck == 1)
1068                         output[ii] = nullval;
1069                     else
1070                         nullarray[ii] = 1;
1071                 }
1072                 else
1073                     output[ii] =  ( *(unsigned short *) &input[ii] ) ^ 0x8000;
1074             }
1075         }
1076         else if (scale == 1. && zero == 0.)  /* no scaling */
1077         {
1078             for (ii = 0; ii < ntodo; ii++)
1079             {
1080                 if (input[ii] == tnull)
1081                 {
1082                     *anynull = 1;
1083                     if (nullcheck == 1)
1084                         output[ii] = nullval;
1085                     else
1086                         nullarray[ii] = 1;
1087                 }
1088                 else if (input[ii] < 0)
1089                 {
1090                     *status = OVERFLOW_ERR;
1091                     output[ii] = 0;
1092                 }
1093                 else
1094                     output[ii] = (unsigned short) input[ii]; /* copy input */
1095             }
1096         }
1097         else                  /* must scale the data */
1098         {
1099             for (ii = 0; ii < ntodo; ii++)
1100             {
1101                 if (input[ii] == tnull)
1102                 {
1103                     *anynull = 1;
1104                     if (nullcheck == 1)
1105                         output[ii] = nullval;
1106                     else
1107                         nullarray[ii] = 1;
1108                 }
1109                 else
1110                 {
1111                     dvalue = input[ii] * scale + zero;
1112 
1113                     if (dvalue < DUSHRT_MIN)
1114                     {
1115                         *status = OVERFLOW_ERR;
1116                         output[ii] = 0;
1117                     }
1118                     else if (dvalue > DUSHRT_MAX)
1119                     {
1120                         *status = OVERFLOW_ERR;
1121                         output[ii] = USHRT_MAX;
1122                     }
1123                     else
1124                         output[ii] = (unsigned short) dvalue;
1125                 }
1126             }
1127         }
1128     }
1129     return(*status);
1130 }
1131 /*--------------------------------------------------------------------------*/
fffi4u2(INT32BIT * input,long ntodo,double scale,double zero,int nullcheck,INT32BIT tnull,unsigned short nullval,char * nullarray,int * anynull,unsigned short * output,int * status)1132 int fffi4u2(INT32BIT *input,      /* I - array of values to be converted     */
1133             long ntodo,           /* I - number of elements in the array     */
1134             double scale,         /* I - FITS TSCALn or BSCALE value         */
1135             double zero,          /* I - FITS TZEROn or BZERO  value         */
1136             int nullcheck,        /* I - null checking code; 0 = don't check */
1137                                   /*     1:set null pixels = nullval         */
1138                                   /*     2: if null pixel, set nullarray = 1 */
1139             INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
1140    unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
1141             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1142             int  *anynull,        /* O - set to 1 if any pixels are null     */
1143    unsigned short *output,        /* O - array of converted pixels           */
1144             int *status)          /* IO - error status                       */
1145 /*
1146   Copy input to output following reading of the input from a FITS file.
1147   Check for null values and do datatype conversion and scaling if required.
1148   The nullcheck code value determines how any null values in the input array
1149   are treated.  A null value is an input pixel that is equal to tnull.  If
1150   nullcheck = 0, then no checking for nulls is performed and any null values
1151   will be transformed just like any other pixel.  If nullcheck = 1, then the
1152   output pixel will be set = nullval if the corresponding input pixel is null.
1153   If nullcheck = 2, then if the pixel is null then the corresponding value of
1154   nullarray will be set to 1; the value of nullarray for non-null pixels
1155   will = 0.  The anynull parameter will be set = 1 if any of the returned
1156   pixels are null, otherwise anynull will be returned with a value = 0;
1157 */
1158 {
1159     long ii;
1160     double dvalue;
1161 
1162     if (nullcheck == 0)     /* no null checking required */
1163     {
1164         if (scale == 1. && zero == 0.)      /* no scaling */
1165         {
1166             for (ii = 0; ii < ntodo; ii++)
1167             {
1168                 if (input[ii] < 0)
1169                 {
1170                     *status = OVERFLOW_ERR;
1171                     output[ii] = 0;
1172                 }
1173                 else if (input[ii] > USHRT_MAX)
1174                 {
1175                     *status = OVERFLOW_ERR;
1176                     output[ii] = USHRT_MAX;
1177                 }
1178                 else
1179                     output[ii] = (unsigned short) input[ii];
1180             }
1181         }
1182         else             /* must scale the data */
1183         {
1184             for (ii = 0; ii < ntodo; ii++)
1185             {
1186                 dvalue = input[ii] * scale + zero;
1187 
1188                 if (dvalue < DUSHRT_MIN)
1189                 {
1190                     *status = OVERFLOW_ERR;
1191                     output[ii] = 0;
1192                 }
1193                 else if (dvalue > DUSHRT_MAX)
1194                 {
1195                     *status = OVERFLOW_ERR;
1196                     output[ii] = USHRT_MAX;
1197                 }
1198                 else
1199                     output[ii] = (unsigned short) dvalue;
1200             }
1201         }
1202     }
1203     else        /* must check for null values */
1204     {
1205         if (scale == 1. && zero == 0.)  /* no scaling */
1206         {
1207             for (ii = 0; ii < ntodo; ii++)
1208             {
1209                 if (input[ii] == tnull)
1210                 {
1211                     *anynull = 1;
1212                     if (nullcheck == 1)
1213                         output[ii] = nullval;
1214                     else
1215                         nullarray[ii] = 1;
1216                 }
1217                 else
1218                 {
1219                     if (input[ii] < 0)
1220                     {
1221                         *status = OVERFLOW_ERR;
1222                         output[ii] = 0;
1223                     }
1224                     else if (input[ii] > USHRT_MAX)
1225                     {
1226                         *status = OVERFLOW_ERR;
1227                         output[ii] = USHRT_MAX;
1228                     }
1229                     else
1230                         output[ii] = (unsigned short) input[ii];
1231                 }
1232             }
1233         }
1234         else                  /* must scale the data */
1235         {
1236             for (ii = 0; ii < ntodo; ii++)
1237             {
1238                 if (input[ii] == tnull)
1239                 {
1240                     *anynull = 1;
1241                     if (nullcheck == 1)
1242                         output[ii] = nullval;
1243                     else
1244                         nullarray[ii] = 1;
1245                 }
1246                 else
1247                 {
1248                     dvalue = input[ii] * scale + zero;
1249 
1250                     if (dvalue < DUSHRT_MIN)
1251                     {
1252                         *status = OVERFLOW_ERR;
1253                         output[ii] = 0;
1254                     }
1255                     else if (dvalue > DUSHRT_MAX)
1256                     {
1257                         *status = OVERFLOW_ERR;
1258                         output[ii] = USHRT_MAX;
1259                     }
1260                     else
1261                         output[ii] = (unsigned short) dvalue;
1262                 }
1263             }
1264         }
1265     }
1266     return(*status);
1267 }
1268 /*--------------------------------------------------------------------------*/
fffi8u2(LONGLONG * input,long ntodo,double scale,double zero,int nullcheck,LONGLONG tnull,unsigned short nullval,char * nullarray,int * anynull,unsigned short * output,int * status)1269 int fffi8u2(LONGLONG *input,      /* I - array of values to be converted     */
1270             long ntodo,           /* I - number of elements in the array     */
1271             double scale,         /* I - FITS TSCALn or BSCALE value         */
1272             double zero,          /* I - FITS TZEROn or BZERO  value         */
1273             int nullcheck,        /* I - null checking code; 0 = don't check */
1274                                   /*     1:set null pixels = nullval         */
1275                                   /*     2: if null pixel, set nullarray = 1 */
1276             LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
1277    unsigned short nullval,        /* I - set null pixels, if nullcheck = 1   */
1278             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1279             int  *anynull,        /* O - set to 1 if any pixels are null     */
1280    unsigned short *output,        /* O - array of converted pixels           */
1281             int *status)          /* IO - error status                       */
1282 /*
1283   Copy input to output following reading of the input from a FITS file.
1284   Check for null values and do datatype conversion and scaling if required.
1285   The nullcheck code value determines how any null values in the input array
1286   are treated.  A null value is an input pixel that is equal to tnull.  If
1287   nullcheck = 0, then no checking for nulls is performed and any null values
1288   will be transformed just like any other pixel.  If nullcheck = 1, then the
1289   output pixel will be set = nullval if the corresponding input pixel is null.
1290   If nullcheck = 2, then if the pixel is null then the corresponding value of
1291   nullarray will be set to 1; the value of nullarray for non-null pixels
1292   will = 0.  The anynull parameter will be set = 1 if any of the returned
1293   pixels are null, otherwise anynull will be returned with a value = 0;
1294 */
1295 {
1296     long ii;
1297     double dvalue;
1298     ULONGLONG ulltemp;
1299 
1300     if (nullcheck == 0)     /* no null checking required */
1301     {
1302         if (scale == 1. && zero ==  9223372036854775808.)
1303         {
1304             /* The column we read contains unsigned long long values. */
1305             /* Instead of adding 9223372036854775808, it is more efficient */
1306             /* and more precise to just flip the sign bit with the XOR operator */
1307 
1308             for (ii = 0; ii < ntodo; ii++) {
1309 
1310                 ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
1311 
1312                 if (ulltemp > USHRT_MAX)
1313                 {
1314                     *status = OVERFLOW_ERR;
1315                     output[ii] = USHRT_MAX;
1316                 }
1317                 else
1318                     output[ii] = (unsigned short) ulltemp;
1319 
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] > USHRT_MAX)
1332                 {
1333                     *status = OVERFLOW_ERR;
1334                     output[ii] = USHRT_MAX;
1335                 }
1336                 else
1337                     output[ii] = (unsigned short) 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 < DUSHRT_MIN)
1347                 {
1348                     *status = OVERFLOW_ERR;
1349                     output[ii] = 0;
1350                 }
1351                 else if (dvalue > DUSHRT_MAX)
1352                 {
1353                     *status = OVERFLOW_ERR;
1354                     output[ii] = USHRT_MAX;
1355                 }
1356                 else
1357                     output[ii] = (unsigned short) 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 > USHRT_MAX)
1384                     {
1385                         *status = OVERFLOW_ERR;
1386                         output[ii] = USHRT_MAX;
1387                     }
1388                     else
1389 		    {
1390                         output[ii] = (unsigned short) 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] > USHRT_MAX)
1415                     {
1416                         *status = OVERFLOW_ERR;
1417                         output[ii] = USHRT_MAX;
1418                     }
1419                     else
1420                         output[ii] = (unsigned short) 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 < DUSHRT_MIN)
1441                     {
1442                         *status = OVERFLOW_ERR;
1443                         output[ii] = 0;
1444                     }
1445                     else if (dvalue > DUSHRT_MAX)
1446                     {
1447                         *status = OVERFLOW_ERR;
1448                         output[ii] = USHRT_MAX;
1449                     }
1450                     else
1451                         output[ii] = (unsigned short) dvalue;
1452                 }
1453             }
1454         }
1455     }
1456     return(*status);
1457 }
1458 /*--------------------------------------------------------------------------*/
fffr4u2(float * input,long ntodo,double scale,double zero,int nullcheck,unsigned short nullval,char * nullarray,int * anynull,unsigned short * output,int * status)1459 int fffr4u2(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 short 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 short *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] < DUSHRT_MIN)
1496                 {
1497                     *status = OVERFLOW_ERR;
1498                     output[ii] = 0;
1499                 }
1500                 else if (input[ii] > DUSHRT_MAX)
1501                 {
1502                     *status = OVERFLOW_ERR;
1503                     output[ii] = USHRT_MAX;
1504                 }
1505                 else
1506                     output[ii] = (unsigned short) 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 < DUSHRT_MIN)
1516                 {
1517                     *status = OVERFLOW_ERR;
1518                     output[ii] = 0;
1519                 }
1520                 else if (dvalue > DUSHRT_MAX)
1521                 {
1522                     *status = OVERFLOW_ERR;
1523                     output[ii] = USHRT_MAX;
1524                 }
1525                 else
1526                     output[ii] = (unsigned short) 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] < DUSHRT_MIN)
1558                     {
1559                         *status = OVERFLOW_ERR;
1560                         output[ii] = 0;
1561                     }
1562                     else if (input[ii] > DUSHRT_MAX)
1563                     {
1564                         *status = OVERFLOW_ERR;
1565                         output[ii] = USHRT_MAX;
1566                     }
1567                     else
1568                         output[ii] = (unsigned short) 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 < DUSHRT_MIN)
1589                     {
1590                         *status = OVERFLOW_ERR;
1591                         output[ii] = 0;
1592                     }
1593                     else if (zero > DUSHRT_MAX)
1594                     {
1595                         *status = OVERFLOW_ERR;
1596                         output[ii] = USHRT_MAX;
1597                     }
1598                     else
1599                       output[ii] = (unsigned short) zero;
1600                   }
1601               }
1602               else
1603               {
1604                     dvalue = input[ii] * scale + zero;
1605 
1606                     if (dvalue < DUSHRT_MIN)
1607                     {
1608                         *status = OVERFLOW_ERR;
1609                         output[ii] = 0;
1610                     }
1611                     else if (dvalue > DUSHRT_MAX)
1612                     {
1613                         *status = OVERFLOW_ERR;
1614                         output[ii] = USHRT_MAX;
1615                     }
1616                     else
1617                         output[ii] = (unsigned short) dvalue;
1618               }
1619             }
1620         }
1621     }
1622     return(*status);
1623 }
1624 /*--------------------------------------------------------------------------*/
fffr8u2(double * input,long ntodo,double scale,double zero,int nullcheck,unsigned short nullval,char * nullarray,int * anynull,unsigned short * output,int * status)1625 int fffr8u2(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 short 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 short *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] < DUSHRT_MIN)
1662                 {
1663                     *status = OVERFLOW_ERR;
1664                     output[ii] = 0;
1665                 }
1666                 else if (input[ii] > DUSHRT_MAX)
1667                 {
1668                     *status = OVERFLOW_ERR;
1669                     output[ii] = USHRT_MAX;
1670                 }
1671                 else
1672                     output[ii] = (unsigned short) 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 < DUSHRT_MIN)
1682                 {
1683                     *status = OVERFLOW_ERR;
1684                     output[ii] = 0;
1685                 }
1686                 else if (dvalue > DUSHRT_MAX)
1687                 {
1688                     *status = OVERFLOW_ERR;
1689                     output[ii] = USHRT_MAX;
1690                 }
1691                 else
1692                     output[ii] = (unsigned short) 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] < DUSHRT_MIN)
1723                     {
1724                         *status = OVERFLOW_ERR;
1725                         output[ii] = 0;
1726                     }
1727                     else if (input[ii] > DUSHRT_MAX)
1728                     {
1729                         *status = OVERFLOW_ERR;
1730                         output[ii] = USHRT_MAX;
1731                     }
1732                     else
1733                         output[ii] = (unsigned short) 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 < DUSHRT_MIN)
1754                     {
1755                         *status = OVERFLOW_ERR;
1756                         output[ii] = 0;
1757                     }
1758                     else if (zero > DUSHRT_MAX)
1759                     {
1760                         *status = OVERFLOW_ERR;
1761                         output[ii] = USHRT_MAX;
1762                     }
1763                     else
1764                       output[ii] = (unsigned short) zero;
1765                   }
1766               }
1767               else
1768                 {
1769                     dvalue = input[ii] * scale + zero;
1770 
1771                     if (dvalue < DUSHRT_MIN)
1772                     {
1773                         *status = OVERFLOW_ERR;
1774                         output[ii] = 0;
1775                     }
1776                     else if (dvalue > DUSHRT_MAX)
1777                     {
1778                         *status = OVERFLOW_ERR;
1779                         output[ii] = USHRT_MAX;
1780                     }
1781                     else
1782                         output[ii] = (unsigned short) dvalue;
1783                 }
1784             }
1785         }
1786     }
1787     return(*status);
1788 }
1789 /*--------------------------------------------------------------------------*/
fffstru2(char * input,long ntodo,double scale,double zero,long twidth,double implipower,int nullcheck,char * snull,unsigned short nullval,char * nullarray,int * anynull,unsigned short * output,int * status)1790 int fffstru2(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 short 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 short *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 < DUSHRT_MIN)
1951         {
1952             *status = OVERFLOW_ERR;
1953             output[ii] = 0;
1954         }
1955         else if (dvalue > DUSHRT_MAX)
1956         {
1957             *status = OVERFLOW_ERR;
1958             output[ii] = USHRT_MAX;
1959         }
1960         else
1961             output[ii] = (unsigned short) dvalue;
1962       }
1963       /* restore the char that was overwritten by the null */
1964       *tpos = tempstore;
1965     }
1966     return(*status);
1967 }
1968