1 /*  This file, getcolk.c, contains routines that read data elements from   */
2 /*  a FITS image or table, with '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 /*--------------------------------------------------------------------------*/
ffgpvk(fitsfile * fptr,long group,LONGLONG firstelem,LONGLONG nelem,int nulval,int * array,int * anynul,int * status)15 int ffgpvk( 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             int   nulval,     /* I - value for undefined pixels              */
20             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     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, TINT, 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     ffgclk(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
57                array, &cdummy, anynul, status);
58     return(*status);
59 }
60 /*--------------------------------------------------------------------------*/
ffgpfk(fitsfile * fptr,long group,LONGLONG firstelem,LONGLONG nelem,int * array,char * nularray,int * anynul,int * status)61 int ffgpfk( 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             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, TINT, 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     ffgclk(fptr, 2, row, firstelem, nelem, 1, 2, 0L,
100                array, nularray, anynul, status);
101     return(*status);
102 }
103 /*--------------------------------------------------------------------------*/
ffg2dk(fitsfile * fptr,long group,int nulval,LONGLONG ncols,LONGLONG naxis1,LONGLONG naxis2,int * array,int * anynul,int * status)104 int ffg2dk(fitsfile *fptr,  /* I - FITS file pointer                       */
105            long  group,     /* I - group to read (1 = 1st group)           */
106            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            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     ffg3dk(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array,
124            anynul, status);
125 
126     return(*status);
127 }
128 /*--------------------------------------------------------------------------*/
ffg3dk(fitsfile * fptr,long group,int nulval,LONGLONG ncols,LONGLONG nrows,LONGLONG naxis1,LONGLONG naxis2,LONGLONG naxis3,int * array,int * anynul,int * status)129 int ffg3dk(fitsfile *fptr,  /* I - FITS file pointer                       */
130            long  group,     /* I - group to read (1 = 1st group)           */
131            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            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     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, TINT, 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        ffgclk(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 (ffgclk(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 /*--------------------------------------------------------------------------*/
ffgsvk(fitsfile * fptr,int colnum,int naxis,long * naxes,long * blc,long * trc,long * inc,int nulval,int * array,int * anynul,int * status)213 int ffgsvk(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            int  nulval,    /* I - value to set undefined pixels             */
221            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],dir[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     int nullvalue;
237 
238     if (naxis < 1 || naxis > 9)
239     {
240         snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj 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, TINT, 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         dir[ii] = 1;
306     }
307 
308     for (ii = 0; ii < naxis; ii++)
309     {
310       if (trc[ii] < blc[ii])
311       {
312         if (hdutype == IMAGE_HDU)
313         {
314            dir[ii] = -1;
315         }
316         else
317         {
318           snprintf(msg, FLEN_ERRMSG,"ffgsvk: illegal range specified for axis %ld", ii + 1);
319           ffpmsg(msg);
320           return(*status = BAD_PIX_NUM);
321         }
322       }
323 
324       str[ii] = blc[ii];
325       stp[ii] = trc[ii];
326       incr[ii] = inc[ii];
327       dsize[ii + 1] = dsize[ii] * naxes[ii];
328       dsize[ii] = dsize[ii] * dir[ii];
329     }
330     dsize[naxis] = dsize[naxis] * dir[naxis];
331 
332     if (naxis == 1 && naxes[0] == 1)
333     {
334       /* This is not a vector column, so read all the rows at once */
335       nelem = (rstp - rstr) / rinc + 1;
336       ninc = rinc;
337       rstp = rstr;
338     }
339     else
340     {
341       /* have to read each row individually, in all dimensions */
342       nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
343       ninc = incr[0] * dir[0];
344     }
345 
346     for (row = rstr; row <= rstp; row += rinc)
347     {
348      for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
349      {
350       for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
351       {
352        for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
353        {
354         for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
355         {
356          for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
357          {
358           for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
359           {
360            for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
361            {
362             for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
363             {
364 
365               felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] +
366                              (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
367                              (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
368                              (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];
369 
370               if ( ffgclk(fptr, numcol, row, felem, nelem, ninc, nultyp,
371                    nulval, &array[i0], &ldummy, &anyf, status) > 0)
372                    return(*status);
373 
374               if (anyf && anynul)
375                   *anynul = TRUE;
376 
377               i0 += nelem;
378             }
379            }
380           }
381          }
382         }
383        }
384       }
385      }
386     }
387     return(*status);
388 }
389 /*--------------------------------------------------------------------------*/
ffgsfk(fitsfile * fptr,int colnum,int naxis,long * naxes,long * blc,long * trc,long * inc,int * array,char * flagval,int * anynul,int * status)390 int ffgsfk(fitsfile *fptr, /* I - FITS file pointer                         */
391            int  colnum,    /* I - number of the column to read (1 = 1st)    */
392            int naxis,      /* I - number of dimensions in the FITS array    */
393            long  *naxes,   /* I - size of each dimension                    */
394            long  *blc,     /* I - 'bottom left corner' of the subsection    */
395            long  *trc,     /* I - 'top right corner' of the subsection      */
396            long  *inc,     /* I - increment to be applied in each dimension */
397            int  *array,    /* O - array to be filled and returned           */
398            char *flagval,  /* O - set to 1 if corresponding value is null   */
399            int  *anynul,   /* O - set to 1 if any values are null; else 0   */
400            int  *status)   /* IO - error status                             */
401 /*
402   Read a subsection of data values from an image or a table column.
403   This routine is set up to handle a maximum of nine dimensions.
404 */
405 {
406     long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
407     long str[9],stp[9],incr[9],dsize[10];
408     LONGLONG blcll[9], trcll[9];
409     long felem, nelem, nultyp, ninc, numcol;
410     long nulval = 0;
411     int hdutype, anyf;
412     char msg[FLEN_ERRMSG];
413     int nullcheck = 2;
414 
415     if (naxis < 1 || naxis > 9)
416     {
417         snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
418         ffpmsg(msg);
419         return(*status = BAD_DIMEN);
420     }
421 
422     if (fits_is_compressed_image(fptr, status))
423     {
424         /* this is a compressed image in a binary table */
425 
426         for (ii=0; ii < naxis; ii++) {
427 	    blcll[ii] = blc[ii];
428 	    trcll[ii] = trc[ii];
429 	}
430 
431         fits_read_compressed_img(fptr, TINT, blcll, trcll, inc,
432             nullcheck, NULL, array, flagval, anynul, status);
433         return(*status);
434     }
435 
436 /*
437     if this is a primary array, then the input COLNUM parameter should
438     be interpreted as the row number, and we will alway read the image
439     data from column 2 (any group parameters are in column 1).
440 */
441     if (ffghdt(fptr, &hdutype, status) > 0)
442         return(*status);
443 
444     if (hdutype == IMAGE_HDU)
445     {
446         /* this is a primary array, or image extension */
447         if (colnum == 0)
448         {
449             rstr = 1;
450             rstp = 1;
451         }
452         else
453         {
454             rstr = colnum;
455             rstp = colnum;
456         }
457         rinc = 1;
458         numcol = 2;
459     }
460     else
461     {
462         /* this is a table, so the row info is in the (naxis+1) elements */
463         rstr = blc[naxis];
464         rstp = trc[naxis];
465         rinc = inc[naxis];
466         numcol = colnum;
467     }
468 
469     nultyp = 2;
470     if (anynul)
471         *anynul = FALSE;
472 
473     i0 = 0;
474     for (ii = 0; ii < 9; ii++)
475     {
476         str[ii] = 1;
477         stp[ii] = 1;
478         incr[ii] = 1;
479         dsize[ii] = 1;
480     }
481 
482     for (ii = 0; ii < naxis; ii++)
483     {
484       if (trc[ii] < blc[ii])
485       {
486         snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1);
487         ffpmsg(msg);
488         return(*status = BAD_PIX_NUM);
489       }
490 
491       str[ii] = blc[ii];
492       stp[ii] = trc[ii];
493       incr[ii] = inc[ii];
494       dsize[ii + 1] = dsize[ii] * naxes[ii];
495     }
496 
497     if (naxis == 1 && naxes[0] == 1)
498     {
499       /* This is not a vector column, so read all the rows at once */
500       nelem = (rstp - rstr) / rinc + 1;
501       ninc = rinc;
502       rstp = rstr;
503     }
504     else
505     {
506       /* have to read each row individually, in all dimensions */
507       nelem = (stp[0] - str[0]) / inc[0] + 1;
508       ninc = incr[0];
509     }
510 
511     for (row = rstr; row <= rstp; row += rinc)
512     {
513      for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
514      {
515       for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
516       {
517        for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
518        {
519         for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
520         {
521          for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
522          {
523           for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
524           {
525            for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
526            {
527             for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
528             {
529               felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] +
530                              (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
531                              (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
532                              (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
533 
534               if ( ffgclk(fptr, numcol, row, felem, nelem, ninc, nultyp,
535                    nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
536                    return(*status);
537 
538               if (anyf && anynul)
539                   *anynul = TRUE;
540 
541               i0 += nelem;
542             }
543            }
544           }
545          }
546         }
547        }
548       }
549      }
550     }
551     return(*status);
552 }
553 /*--------------------------------------------------------------------------*/
ffggpk(fitsfile * fptr,long group,long firstelem,long nelem,int * array,int * status)554 int ffggpk( fitsfile *fptr,   /* I - FITS file pointer                       */
555             long  group,      /* I - group to read (1 = 1st group)           */
556             long  firstelem,  /* I - first vector element to read (1 = 1st)  */
557             long  nelem,      /* I - number of values to read                */
558             int  *array,     /* O - array of values that are returned       */
559             int  *status)     /* IO - error status                           */
560 /*
561   Read an array of group parameters from the primary array. Data conversion
562   and scaling will be performed if necessary (e.g, if the datatype of
563   the FITS array is not the same as the array being read).
564 */
565 {
566     long row;
567     int idummy;
568     char cdummy;
569     /*
570       the primary array is represented as a binary table:
571       each group of the primary array is a row in the table,
572       where the first column contains the group parameters
573       and the second column contains the image itself.
574     */
575 
576     row=maxvalue(1,group);
577 
578     ffgclk(fptr, 1, row, firstelem, nelem, 1, 1, 0L,
579                array, &cdummy, &idummy, status);
580     return(*status);
581 }
582 /*--------------------------------------------------------------------------*/
ffgcvk(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,int nulval,int * array,int * anynul,int * status)583 int ffgcvk(fitsfile *fptr,   /* I - FITS file pointer                       */
584            int  colnum,      /* I - number of column to read (1 = 1st col)  */
585            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
586            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
587            LONGLONG  nelem,      /* I - number of values to read                */
588            int   nulval,     /* I - value for null pixels                   */
589            int  *array,      /* O - array of values that are read           */
590            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
591            int  *status)     /* IO - error status                           */
592 /*
593   Read an array of values from a column in the current FITS HDU. Automatic
594   datatype conversion will be performed if the datatype of the column does not
595   match the datatype of the array parameter. The output values will be scaled
596   by the FITS TSCALn and TZEROn values if these values have been defined.
597   Any undefined pixels will be set equal to the value of 'nulval' unless
598   nulval = 0 in which case no checks for undefined pixels will be made.
599 */
600 {
601     char cdummy;
602 
603     ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
604            array, &cdummy, anynul, status);
605     return(*status);
606 }
607 /*--------------------------------------------------------------------------*/
ffgcfk(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,int * array,char * nularray,int * anynul,int * status)608 int ffgcfk(fitsfile *fptr,   /* I - FITS file pointer                       */
609            int  colnum,      /* I - number of column to read (1 = 1st col)  */
610            LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
611            LONGLONG  firstelem,  /* I - first vector element to read (1 = 1st)  */
612            LONGLONG  nelem,      /* I - number of values to read                */
613            int   *array,     /* O - array of values that are read           */
614            char *nularray,   /* O - array of flags: 1 if null pixel; else 0 */
615            int  *anynul,     /* O - set to 1 if any values are null; else 0 */
616            int  *status)     /* IO - error status                           */
617 /*
618   Read an array of values from a column in the current FITS HDU. Automatic
619   datatype conversion will be performed if the datatype of the column does not
620   match the datatype of the array parameter. The output values will be scaled
621   by the FITS TSCALn and TZEROn values if these values have been defined.
622   Nularray will be set = 1 if the corresponding array pixel is undefined,
623   otherwise nularray will = 0.
624 */
625 {
626     int dummy = 0;
627 
628     ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
629            array, nularray, anynul, status);
630     return(*status);
631 }
632 /*--------------------------------------------------------------------------*/
ffgclk(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,long elemincre,int nultyp,int nulval,int * array,char * nularray,int * anynul,int * status)633 int ffgclk( fitsfile *fptr,   /* I - FITS file pointer                       */
634             int  colnum,      /* I - number of column to read (1 = 1st col)  */
635             LONGLONG  firstrow,   /* I - first row to read (1 = 1st row)         */
636             LONGLONG firstelem,  /* I - first vector element to read (1 = 1st)  */
637             LONGLONG  nelem,      /* I - number of values to read                */
638             long  elemincre,  /* I - pixel increment; e.g., 2 = every other  */
639             int   nultyp,     /* I - null value handling code:               */
640                               /*     1: set undefined pixels = nulval        */
641                               /*     2: set nularray=1 for undefined pixels  */
642             int   nulval,     /* I - value for null pixels if nultyp = 1     */
643             int  *array,      /* O - array of values that are read           */
644             char *nularray,   /* O - array of flags = 1 if nultyp = 2        */
645             int  *anynul,     /* O - set to 1 if any values are null; else 0 */
646             int  *status)     /* IO - error status                           */
647 /*
648   Read an array of values from a column in the current FITS HDU.
649   The column number may refer to a real column in an ASCII or binary table,
650   or it may refer be a virtual column in a 1 or more grouped FITS primary
651   array or image extension.  FITSIO treats a primary array as a binary table
652   with 2 vector columns: the first column contains the group parameters (often
653   with length = 0) and the second column contains the array of image pixels.
654   Each row of the table represents a group in the case of multigroup FITS
655   images.
656 
657   The output array of values will be converted from the datatype of the column
658   and will be scaled by the FITS TSCALn and TZEROn values if necessary.
659 */
660 {
661     double scale, zero, power, dtemp;
662     int tcode, maxelem2, hdutype, xcode, decimals;
663     long twidth, incre;
664     long ii, xwidth, ntodo;
665     int convert, nulcheck, readcheck = 0;
666     LONGLONG repeat, startpos, elemnum, readptr, tnull;
667     LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
668     char tform[20];
669     char message[FLEN_ERRMSG];
670     char snull[20];   /*  the FITS null value if reading from ASCII table  */
671 
672     double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
673     void *buffer;
674 
675     if (*status > 0 || nelem == 0)  /* inherit input status value if > 0 */
676         return(*status);
677 
678     /* call the 'short' or 'long' version of this routine, if possible */
679     if (sizeof(int) == sizeof(short))
680         ffgcli(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
681               (short) nulval, (short *) array, nularray, anynul, status);
682     else if (sizeof(int) == sizeof(long))
683         ffgclj(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
684               (long) nulval, (long *) array, nularray, anynul, status);
685     else
686     {
687     /*
688       This is a special case: sizeof(int) is not equal to sizeof(short) or
689       sizeof(long).  This occurs on Alpha OSF systems where short = 2 bytes,
690       int = 4 bytes, and long = 8 bytes.
691     */
692 
693     buffer = cbuff;
694     power = 1.;
695 
696     if (anynul)
697         *anynul = 0;
698 
699     if (nultyp == 2)
700         memset(nularray, 0, (size_t) nelem);   /* initialize nullarray */
701 
702     /*---------------------------------------------------*/
703     /*  Check input and get parameters about the column: */
704     /*---------------------------------------------------*/
705     if (elemincre < 0)
706         readcheck = -1;  /* don't do range checking in this case */
707 
708     if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
709          tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
710          &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
711          return(*status);
712     maxelem = maxelem2;
713 
714     incre *= elemincre;   /* multiply incre to just get every nth pixel */
715 
716     if (tcode == TSTRING)    /* setup for ASCII tables */
717     {
718       /* get the number of implied decimal places if no explicit decmal point */
719       ffasfm(tform, &xcode, &xwidth, &decimals, status);
720       for(ii = 0; ii < decimals; ii++)
721         power *= 10.;
722     }
723     /*------------------------------------------------------------------*/
724     /*  Decide whether to check for null values in the input FITS file: */
725     /*------------------------------------------------------------------*/
726     nulcheck = nultyp; /* by default check for null values in the FITS file */
727 
728     if (nultyp == 1 && nulval == 0)
729        nulcheck = 0;    /* calling routine does not want to check for nulls */
730 
731     else if (tcode%10 == 1 &&        /* if reading an integer column, and  */
732             tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
733             nulcheck = 0;            /* then do not check for null values. */
734 
735     else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
736             nulcheck = 0;            /* Impossible null value */
737 
738     else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
739             nulcheck = 0;            /* Impossible null value */
740 
741     else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
742          nulcheck = 0;
743 
744     /*----------------------------------------------------------------------*/
745     /*  If FITS column and output data array have same datatype, then we do */
746     /*  not need to use a temporary buffer to store intermediate datatype.  */
747     /*----------------------------------------------------------------------*/
748     convert = 1;
749     if (tcode == TLONG)           /* Special Case:                        */
750     {                             /* no type convertion required, so read */
751                                   /* data directly into output buffer.    */
752 
753         if (nelem < (LONGLONG)INT32_MAX/4) {
754             maxelem = nelem;
755         } else {
756             maxelem = INT32_MAX/4;
757         }
758 
759         if (nulcheck == 0 && scale == 1. && zero == 0.)
760             convert = 0;  /* no need to scale data or find nulls */
761     }
762 
763     /*---------------------------------------------------------------------*/
764     /*  Now read the pixels from the FITS column. If the column does not   */
765     /*  have the same datatype as the output array, then we have to read   */
766     /*  the raw values into a temporary buffer (of limited size).  In      */
767     /*  the case of a vector colum read only 1 vector of values at a time  */
768     /*  then skip to the next row if more values need to be read.          */
769     /*  After reading the raw values, then call the fffXXYY routine to (1) */
770     /*  test for undefined values, (2) convert the datatype if necessary,  */
771     /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
772     /*  scaling parameters.                                                */
773     /*---------------------------------------------------------------------*/
774     remain = nelem;           /* remaining number of values to read */
775     next = 0;                 /* next element in array to be read   */
776     rownum = 0;               /* row number, relative to firstrow   */
777 
778     while (remain)
779     {
780         /* limit the number of pixels to read at one time to the number that
781            will fit in the buffer or to the number of pixels that remain in
782            the current vector, which ever is smaller.
783         */
784         ntodo = (long) minvalue(remain, maxelem);
785         if (elemincre >= 0)
786         {
787           ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
788         }
789         else
790         {
791           ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
792         }
793 
794         readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
795 
796         switch (tcode)
797         {
798             case (TLONG):
799                 ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next],
800                        status);
801                 if (convert)
802                     fffi4int((INT32BIT *) &array[next], ntodo, scale, zero,
803                              nulcheck, (INT32BIT) tnull, nulval,
804                              &nularray[next], anynul, &array[next], status);
805                 break;
806             case (TLONGLONG):
807 
808                 ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
809                 fffi8int( (LONGLONG *) buffer, ntodo, scale, zero,
810                            nulcheck, tnull, nulval, &nularray[next],
811                             anynul, &array[next], status);
812                 break;
813             case (TBYTE):
814                 ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
815                        status);
816                 fffi1int((unsigned char *) buffer, ntodo, scale, zero, nulcheck,
817                      (unsigned char) tnull, nulval, &nularray[next], anynul,
818                      &array[next], status);
819                 break;
820             case (TSHORT):
821                 ffgi2b(fptr, readptr, ntodo, incre, (short  *) buffer, status);
822                 fffi2int((short  *) buffer, ntodo, scale, zero, nulcheck,
823                       (short) tnull, nulval, &nularray[next], anynul,
824                       &array[next], status);
825                 break;
826             case (TFLOAT):
827                 ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
828                 fffr4int((float  *) buffer, ntodo, scale, zero, nulcheck,
829                        nulval, &nularray[next], anynul,
830                        &array[next], status);
831                 break;
832             case (TDOUBLE):
833                 ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
834                 fffr8int((double *) buffer, ntodo, scale, zero, nulcheck,
835                           nulval, &nularray[next], anynul,
836                           &array[next], status);
837                 break;
838             case (TSTRING):
839                 ffmbyt(fptr, readptr, REPORT_EOF, status);
840 
841                 if (incre == twidth)    /* contiguous bytes */
842                      ffgbyt(fptr, ntodo * twidth, buffer, status);
843                 else
844                      ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
845                                status);
846 
847                 fffstrint((char *) buffer, ntodo, scale, zero, twidth, power,
848                      nulcheck, snull, nulval, &nularray[next], anynul,
849                      &array[next], status);
850                 break;
851 
852             default:  /*  error trap for invalid column format */
853                 snprintf(message, FLEN_ERRMSG,
854                    "Cannot read numbers from column %d which has format %s",
855                     colnum, tform);
856                 ffpmsg(message);
857                 if (hdutype == ASCII_TBL)
858                     return(*status = BAD_ATABLE_FORMAT);
859                 else
860                     return(*status = BAD_BTABLE_FORMAT);
861 
862         } /* End of switch block */
863 
864         /*-------------------------*/
865         /*  Check for fatal error  */
866         /*-------------------------*/
867         if (*status > 0)  /* test for error during previous read operation */
868         {
869 	  dtemp = (double) next;
870           if (hdutype > 0)
871             snprintf(message, FLEN_ERRMSG,
872             "Error reading elements %.0f thru %.0f from column %d (ffgclk).",
873               dtemp+1., dtemp+ntodo, colnum);
874           else
875             snprintf(message, FLEN_ERRMSG,
876             "Error reading elements %.0f thru %.0f from image (ffgclk).",
877               dtemp+1., dtemp+ntodo);
878 
879           ffpmsg(message);
880           return(*status);
881         }
882 
883         /*--------------------------------------------*/
884         /*  increment the counters for the next loop  */
885         /*--------------------------------------------*/
886         remain -= ntodo;
887         if (remain)
888         {
889             next += ntodo;
890             elemnum = elemnum + (ntodo * elemincre);
891 
892             if (elemnum >= repeat)  /* completed a row; start on later row */
893             {
894                 rowincre = elemnum / repeat;
895                 rownum += rowincre;
896                 elemnum = elemnum - (rowincre * repeat);
897             }
898             else if (elemnum < 0)  /* completed a row; start on a previous row */
899             {
900                 rowincre = (-elemnum - 1) / repeat + 1;
901                 rownum -= rowincre;
902                 elemnum = (rowincre * repeat) + elemnum;
903             }
904         }
905     }  /*  End of main while Loop  */
906 
907 
908     /*--------------------------------*/
909     /*  check for numerical overflow  */
910     /*--------------------------------*/
911     if (*status == OVERFLOW_ERR)
912     {
913         ffpmsg(
914         "Numerical overflow during type conversion while reading FITS data.");
915         *status = NUM_OVERFLOW;
916     }
917 
918     }  /* end of DEC Alpha special case */
919 
920     return(*status);
921 }
922 /*--------------------------------------------------------------------------*/
fffi1int(unsigned char * input,long ntodo,double scale,double zero,int nullcheck,unsigned char tnull,int nullval,char * nullarray,int * anynull,int * output,int * status)923 int fffi1int(unsigned char *input,/* I - array of values to be converted     */
924             long ntodo,           /* I - number of elements in the array     */
925             double scale,         /* I - FITS TSCALn or BSCALE value         */
926             double zero,          /* I - FITS TZEROn or BZERO  value         */
927             int nullcheck,        /* I - null checking code; 0 = don't check */
928                                   /*     1:set null pixels = nullval         */
929                                   /*     2: if null pixel, set nullarray = 1 */
930             unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
931             int  nullval,         /* I - set null pixels, if nullcheck = 1   */
932             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
933             int  *anynull,        /* O - set to 1 if any pixels are null     */
934             int  *output,         /* O - array of converted pixels           */
935             int *status)          /* IO - error status                       */
936 /*
937   Copy input to output following reading of the input from a FITS file.
938   Check for null values and do datatype conversion and scaling if required.
939   The nullcheck code value determines how any null values in the input array
940   are treated.  A null value is an input pixel that is equal to tnull.  If
941   nullcheck = 0, then no checking for nulls is performed and any null values
942   will be transformed just like any other pixel.  If nullcheck = 1, then the
943   output pixel will be set = nullval if the corresponding input pixel is null.
944   If nullcheck = 2, then if the pixel is null then the corresponding value of
945   nullarray will be set to 1; the value of nullarray for non-null pixels
946   will = 0.  The anynull parameter will be set = 1 if any of the returned
947   pixels are null, otherwise anynull will be returned with a value = 0;
948 */
949 {
950     long ii;
951     double dvalue;
952 
953     if (nullcheck == 0)     /* no null checking required */
954     {
955         if (scale == 1. && zero == 0.)      /* no scaling */
956         {
957             for (ii = 0; ii < ntodo; ii++)
958                 output[ii] = (int) input[ii];  /* copy input to output */
959         }
960         else             /* must scale the data */
961         {
962             for (ii = 0; ii < ntodo; ii++)
963             {
964                 dvalue = input[ii] * scale + zero;
965 
966                 if (dvalue < DINT_MIN)
967                 {
968                     *status = OVERFLOW_ERR;
969                     output[ii] = INT_MIN;
970                 }
971                 else if (dvalue > DINT_MAX)
972                 {
973                     *status = OVERFLOW_ERR;
974                     output[ii] = INT_MAX;
975                 }
976                 else
977                     output[ii] = (int) dvalue;
978             }
979         }
980     }
981     else        /* must check for null values */
982     {
983         if (scale == 1. && zero == 0.)  /* no scaling */
984         {
985             for (ii = 0; ii < ntodo; ii++)
986             {
987                 if (input[ii] == tnull)
988                 {
989                     *anynull = 1;
990                     if (nullcheck == 1)
991                         output[ii] = nullval;
992                     else
993                         nullarray[ii] = 1;
994                 }
995                 else
996                     output[ii] = (int) input[ii];
997             }
998         }
999         else                  /* must scale the data */
1000         {
1001             for (ii = 0; ii < ntodo; ii++)
1002             {
1003                 if (input[ii] == tnull)
1004                 {
1005                     *anynull = 1;
1006                     if (nullcheck == 1)
1007                         output[ii] = nullval;
1008                     else
1009                         nullarray[ii] = 1;
1010                 }
1011                 else
1012                 {
1013                     dvalue = input[ii] * scale + zero;
1014 
1015                     if (dvalue < DINT_MIN)
1016                     {
1017                         *status = OVERFLOW_ERR;
1018                         output[ii] = INT_MIN;
1019                     }
1020                     else if (dvalue > DINT_MAX)
1021                     {
1022                         *status = OVERFLOW_ERR;
1023                         output[ii] = INT_MAX;
1024                     }
1025                     else
1026                         output[ii] = (int) dvalue;
1027                 }
1028             }
1029         }
1030     }
1031     return(*status);
1032 }
1033 /*--------------------------------------------------------------------------*/
fffi2int(short * input,long ntodo,double scale,double zero,int nullcheck,short tnull,int nullval,char * nullarray,int * anynull,int * output,int * status)1034 int fffi2int(short *input,        /* I - array of values to be converted     */
1035             long ntodo,           /* I - number of elements in the array     */
1036             double scale,         /* I - FITS TSCALn or BSCALE value         */
1037             double zero,          /* I - FITS TZEROn or BZERO  value         */
1038             int nullcheck,        /* I - null checking code; 0 = don't check */
1039                                   /*     1:set null pixels = nullval         */
1040                                   /*     2: if null pixel, set nullarray = 1 */
1041             short tnull,          /* I - value of FITS TNULLn keyword if any */
1042             int  nullval,         /* I - set null pixels, if nullcheck = 1   */
1043             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1044             int  *anynull,        /* O - set to 1 if any pixels are null     */
1045             int  *output,         /* O - array of converted pixels           */
1046             int *status)          /* IO - error status                       */
1047 /*
1048   Copy input to output following reading of the input from a FITS file.
1049   Check for null values and do datatype conversion and scaling if required.
1050   The nullcheck code value determines how any null values in the input array
1051   are treated.  A null value is an input pixel that is equal to tnull.  If
1052   nullcheck = 0, then no checking for nulls is performed and any null values
1053   will be transformed just like any other pixel.  If nullcheck = 1, then the
1054   output pixel will be set = nullval if the corresponding input pixel is null.
1055   If nullcheck = 2, then if the pixel is null then the corresponding value of
1056   nullarray will be set to 1; the value of nullarray for non-null pixels
1057   will = 0.  The anynull parameter will be set = 1 if any of the returned
1058   pixels are null, otherwise anynull will be returned with a value = 0;
1059 */
1060 {
1061     long ii;
1062     double dvalue;
1063 
1064     if (nullcheck == 0)     /* no null checking required */
1065     {
1066         if (scale == 1. && zero == 0.)      /* no scaling */
1067         {
1068             for (ii = 0; ii < ntodo; ii++)
1069                 output[ii] = (int) input[ii];   /* copy input to output */
1070         }
1071         else             /* must scale the data */
1072         {
1073             for (ii = 0; ii < ntodo; ii++)
1074             {
1075                 dvalue = input[ii] * scale + zero;
1076 
1077                 if (dvalue < DINT_MIN)
1078                 {
1079                     *status = OVERFLOW_ERR;
1080                     output[ii] = INT_MIN;
1081                 }
1082                 else if (dvalue > DINT_MAX)
1083                 {
1084                     *status = OVERFLOW_ERR;
1085                     output[ii] = INT_MAX;
1086                 }
1087                 else
1088                     output[ii] = (int) dvalue;
1089             }
1090         }
1091     }
1092     else        /* must check for null values */
1093     {
1094         if (scale == 1. && zero == 0.)  /* no scaling */
1095         {
1096             for (ii = 0; ii < ntodo; ii++)
1097             {
1098                 if (input[ii] == tnull)
1099                 {
1100                     *anynull = 1;
1101                     if (nullcheck == 1)
1102                         output[ii] = nullval;
1103                     else
1104                         nullarray[ii] = 1;
1105                 }
1106                 else
1107                     output[ii] = (int) input[ii];
1108             }
1109         }
1110         else                  /* must scale the data */
1111         {
1112             for (ii = 0; ii < ntodo; ii++)
1113             {
1114                 if (input[ii] == tnull)
1115                 {
1116                     *anynull = 1;
1117                     if (nullcheck == 1)
1118                         output[ii] = nullval;
1119                     else
1120                         nullarray[ii] = 1;
1121                 }
1122                 else
1123                 {
1124                     dvalue = input[ii] * scale + zero;
1125 
1126                     if (dvalue < DINT_MIN)
1127                     {
1128                         *status = OVERFLOW_ERR;
1129                         output[ii] = INT_MIN;
1130                     }
1131                     else if (dvalue > DINT_MAX)
1132                     {
1133                         *status = OVERFLOW_ERR;
1134                         output[ii] = INT_MAX;
1135                     }
1136                     else
1137                         output[ii] = (int) dvalue;
1138                 }
1139             }
1140         }
1141     }
1142     return(*status);
1143 }
1144 /*--------------------------------------------------------------------------*/
fffi4int(INT32BIT * input,long ntodo,double scale,double zero,int nullcheck,INT32BIT tnull,int nullval,char * nullarray,int * anynull,int * output,int * status)1145 int fffi4int(INT32BIT *input,     /* I - array of values to be converted     */
1146             long ntodo,           /* I - number of elements in the array     */
1147             double scale,         /* I - FITS TSCALn or BSCALE value         */
1148             double zero,          /* I - FITS TZEROn or BZERO  value         */
1149             int nullcheck,        /* I - null checking code; 0 = don't check */
1150                                   /*     1:set null pixels = nullval         */
1151                                   /*     2: if null pixel, set nullarray = 1 */
1152             INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
1153             int  nullval,         /* I - set null pixels, if nullcheck = 1   */
1154             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1155             int  *anynull,        /* O - set to 1 if any pixels are null     */
1156             int  *output,         /* O - array of converted pixels           */
1157             int *status)          /* IO - error status                       */
1158 /*
1159   Copy input to output following reading of the input from a FITS file.
1160   Check for null values and do datatype conversion and scaling if required.
1161   The nullcheck code value determines how any null values in the input array
1162   are treated.  A null value is an input pixel that is equal to tnull.  If
1163   nullcheck = 0, then no checking for nulls is performed and any null values
1164   will be transformed just like any other pixel.  If nullcheck = 1, then the
1165   output pixel will be set = nullval if the corresponding input pixel is null.
1166   If nullcheck = 2, then if the pixel is null then the corresponding value of
1167   nullarray will be set to 1; the value of nullarray for non-null pixels
1168   will = 0.  The anynull parameter will be set = 1 if any of the returned
1169   pixels are null, otherwise anynull will be returned with a value = 0;
1170 */
1171 {
1172     long ii;
1173     double dvalue;
1174     if (nullcheck == 0)     /* no null checking required */
1175     {
1176         if (scale == 1. && zero == 0.)      /* no scaling */
1177         {
1178             for (ii = 0; ii < ntodo; ii++)
1179                 output[ii] = (int) input[ii];   /* copy input to output */
1180         }
1181         else             /* must scale the data */
1182         {
1183             for (ii = 0; ii < ntodo; ii++)
1184             {
1185                 dvalue = input[ii] * scale + zero;
1186 
1187                 if (dvalue < DINT_MIN)
1188                 {
1189                     *status = OVERFLOW_ERR;
1190                     output[ii] = INT_MIN;
1191                 }
1192                 else if (dvalue > DINT_MAX)
1193                 {
1194                     *status = OVERFLOW_ERR;
1195                     output[ii] = INT_MAX;
1196                 }
1197                 else
1198                     output[ii] = (int) dvalue;
1199             }
1200         }
1201     }
1202     else        /* must check for null values */
1203     {
1204         if (scale == 1. && zero == 0.)  /* no scaling */
1205         {
1206             for (ii = 0; ii < ntodo; ii++)
1207             {
1208                 if (input[ii] == tnull)
1209                 {
1210                     *anynull = 1;
1211                     if (nullcheck == 1)
1212                         output[ii] = nullval;
1213                     else
1214                         nullarray[ii] = 1;
1215                 }
1216                 else
1217                     output[ii] = (int) input[ii];
1218 
1219             }
1220         }
1221         else                  /* must scale the data */
1222         {
1223             for (ii = 0; ii < ntodo; ii++)
1224             {
1225                 if (input[ii] == tnull)
1226                 {
1227                     *anynull = 1;
1228                     if (nullcheck == 1)
1229                         output[ii] = nullval;
1230                     else
1231                         nullarray[ii] = 1;
1232                 }
1233                 else
1234                 {
1235                     dvalue = input[ii] * scale + zero;
1236 
1237                     if (dvalue < DINT_MIN)
1238                     {
1239                         *status = OVERFLOW_ERR;
1240                         output[ii] = INT_MIN;
1241                     }
1242                     else if (dvalue > DINT_MAX)
1243                     {
1244                         *status = OVERFLOW_ERR;
1245                         output[ii] = INT_MAX;
1246                     }
1247                     else
1248                         output[ii] = (int) dvalue;
1249                 }
1250             }
1251         }
1252     }
1253     return(*status);
1254 }
1255 /*--------------------------------------------------------------------------*/
fffi8int(LONGLONG * input,long ntodo,double scale,double zero,int nullcheck,LONGLONG tnull,int nullval,char * nullarray,int * anynull,int * output,int * status)1256 int fffi8int(LONGLONG *input,     /* I - array of values to be converted     */
1257             long ntodo,           /* I - number of elements in the array     */
1258             double scale,         /* I - FITS TSCALn or BSCALE value         */
1259             double zero,          /* I - FITS TZEROn or BZERO  value         */
1260             int nullcheck,        /* I - null checking code; 0 = don't check */
1261                                   /*     1:set null pixels = nullval         */
1262                                   /*     2: if null pixel, set nullarray = 1 */
1263             LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
1264             int  nullval,         /* I - set null pixels, if nullcheck = 1   */
1265             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1266             int  *anynull,        /* O - set to 1 if any pixels are null     */
1267             int  *output,         /* O - array of converted pixels           */
1268             int *status)          /* IO - error status                       */
1269 /*
1270   Copy input to output following reading of the input from a FITS file.
1271   Check for null values and do datatype conversion and scaling if required.
1272   The nullcheck code value determines how any null values in the input array
1273   are treated.  A null value is an input pixel that is equal to tnull.  If
1274   nullcheck = 0, then no checking for nulls is performed and any null values
1275   will be transformed just like any other pixel.  If nullcheck = 1, then the
1276   output pixel will be set = nullval if the corresponding input pixel is null.
1277   If nullcheck = 2, then if the pixel is null then the corresponding value of
1278   nullarray will be set to 1; the value of nullarray for non-null pixels
1279   will = 0.  The anynull parameter will be set = 1 if any of the returned
1280   pixels are null, otherwise anynull will be returned with a value = 0;
1281 */
1282 {
1283     long ii;
1284     double dvalue;
1285     ULONGLONG ulltemp;
1286 
1287     if (nullcheck == 0)     /* no null checking required */
1288     {
1289         if (scale == 1. && zero ==  9223372036854775808.)
1290         {
1291             /* The column we read contains unsigned long long values. */
1292             /* Instead of adding 9223372036854775808, it is more efficient */
1293             /* and more precise to just flip the sign bit with the XOR operator */
1294 
1295             for (ii = 0; ii < ntodo; ii++) {
1296 
1297                 ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
1298 
1299                 if (ulltemp > INT_MAX)
1300                 {
1301                     *status = OVERFLOW_ERR;
1302                     output[ii] = INT_MAX;
1303                 }
1304                 else
1305 		{
1306                     output[ii] = (int) ulltemp;
1307 		}
1308             }
1309         }
1310         else if (scale == 1. && zero == 0.)      /* no scaling */
1311         {
1312             for (ii = 0; ii < ntodo; ii++)
1313             {
1314                 if (input[ii] < INT_MIN)
1315                 {
1316                     *status = OVERFLOW_ERR;
1317                     output[ii] = INT_MIN;
1318                 }
1319                 else if (input[ii] > INT_MAX)
1320                 {
1321                     *status = OVERFLOW_ERR;
1322                     output[ii] = INT_MAX;
1323                 }
1324                 else
1325                     output[ii] = (int) input[ii];
1326             }
1327         }
1328         else             /* must scale the data */
1329         {
1330             for (ii = 0; ii < ntodo; ii++)
1331             {
1332                 dvalue = input[ii] * scale + zero;
1333 
1334                 if (dvalue < DINT_MIN)
1335                 {
1336                     *status = OVERFLOW_ERR;
1337                     output[ii] = INT_MIN;
1338                 }
1339                 else if (dvalue > DINT_MAX)
1340                 {
1341                     *status = OVERFLOW_ERR;
1342                     output[ii] = INT_MAX;
1343                 }
1344                 else
1345                     output[ii] = (int) dvalue;
1346             }
1347         }
1348     }
1349     else        /* must check for null values */
1350     {
1351         if (scale == 1. && zero ==  9223372036854775808.)
1352         {
1353             /* The column we read contains unsigned long long values. */
1354             /* Instead of subtracting 9223372036854775808, it is more efficient */
1355             /* and more precise to just flip the sign bit with the XOR operator */
1356 
1357             for (ii = 0; ii < ntodo; ii++) {
1358 
1359                 if (input[ii] == tnull)
1360                 {
1361                     *anynull = 1;
1362                     if (nullcheck == 1)
1363                         output[ii] = nullval;
1364                     else
1365                         nullarray[ii] = 1;
1366                 }
1367                 else
1368 		{
1369                     ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
1370 
1371                     if (ulltemp > INT_MAX)
1372                     {
1373                         *status = OVERFLOW_ERR;
1374                         output[ii] = INT_MAX;
1375                     }
1376                     else
1377 		    {
1378                         output[ii] = (int) ulltemp;
1379 		    }
1380                 }
1381             }
1382         }
1383         else if (scale == 1. && zero == 0.)  /* no scaling */
1384         {
1385             for (ii = 0; ii < ntodo; ii++)
1386             {
1387                 if (input[ii] == tnull)
1388                 {
1389                     *anynull = 1;
1390                     if (nullcheck == 1)
1391                         output[ii] = nullval;
1392                     else
1393                         nullarray[ii] = 1;
1394                 }
1395                 else
1396                 {
1397                     if (input[ii] < INT_MIN)
1398                     {
1399                         *status = OVERFLOW_ERR;
1400                         output[ii] = INT_MIN;
1401                     }
1402                     else if (input[ii] > INT_MAX)
1403                     {
1404                         *status = OVERFLOW_ERR;
1405                         output[ii] = INT_MAX;
1406                     }
1407                     else
1408                         output[ii] = (int) input[ii];
1409                 }
1410             }
1411         }
1412         else                  /* must scale the data */
1413         {
1414             for (ii = 0; ii < ntodo; ii++)
1415             {
1416                 if (input[ii] == tnull)
1417                 {
1418                     *anynull = 1;
1419                     if (nullcheck == 1)
1420                         output[ii] = nullval;
1421                     else
1422                         nullarray[ii] = 1;
1423                 }
1424                 else
1425                 {
1426                     dvalue = input[ii] * scale + zero;
1427 
1428                     if (dvalue < DINT_MIN)
1429                     {
1430                         *status = OVERFLOW_ERR;
1431                         output[ii] = INT_MIN;
1432                     }
1433                     else if (dvalue > DINT_MAX)
1434                     {
1435                         *status = OVERFLOW_ERR;
1436                         output[ii] = INT_MAX;
1437                     }
1438                     else
1439                         output[ii] = (int) dvalue;
1440                 }
1441             }
1442         }
1443     }
1444     return(*status);
1445 }
1446 /*--------------------------------------------------------------------------*/
fffr4int(float * input,long ntodo,double scale,double zero,int nullcheck,int nullval,char * nullarray,int * anynull,int * output,int * status)1447 int fffr4int(float *input,        /* I - array of values to be converted     */
1448             long ntodo,           /* I - number of elements in the array     */
1449             double scale,         /* I - FITS TSCALn or BSCALE value         */
1450             double zero,          /* I - FITS TZEROn or BZERO  value         */
1451             int nullcheck,        /* I - null checking code; 0 = don't check */
1452                                   /*     1:set null pixels = nullval         */
1453                                   /*     2: if null pixel, set nullarray = 1 */
1454             int  nullval,         /* I - set null pixels, if nullcheck = 1   */
1455             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1456             int  *anynull,        /* O - set to 1 if any pixels are null     */
1457             int  *output,         /* O - array of converted pixels           */
1458             int *status)          /* IO - error status                       */
1459 /*
1460   Copy input to output following reading of the input from a FITS file.
1461   Check for null values and do datatype conversion and scaling if required.
1462   The nullcheck code value determines how any null values in the input array
1463   are treated.  A null value is an input pixel that is equal to NaN.  If
1464   nullcheck = 0, then no checking for nulls is performed and any null values
1465   will be transformed just like any other pixel.  If nullcheck = 1, then the
1466   output pixel will be set = nullval if the corresponding input pixel is null.
1467   If nullcheck = 2, then if the pixel is null then the corresponding value of
1468   nullarray will be set to 1; the value of nullarray for non-null pixels
1469   will = 0.  The anynull parameter will be set = 1 if any of the returned
1470   pixels are null, otherwise anynull will be returned with a value = 0;
1471 */
1472 {
1473     long ii;
1474     double dvalue;
1475     short *sptr, iret;
1476 
1477     if (nullcheck == 0)     /* no null checking required */
1478     {
1479         if (scale == 1. && zero == 0.)      /* no scaling */
1480         {
1481             for (ii = 0; ii < ntodo; ii++)
1482             {
1483                 if (input[ii] < DINT_MIN)
1484                 {
1485                     *status = OVERFLOW_ERR;
1486                     output[ii] = INT_MIN;
1487                 }
1488                 else if (input[ii] > DINT_MAX)
1489                 {
1490                     *status = OVERFLOW_ERR;
1491                     output[ii] = INT_MAX;
1492                 }
1493                 else
1494                     output[ii] = (int) input[ii];
1495             }
1496         }
1497         else             /* must scale the data */
1498         {
1499             for (ii = 0; ii < ntodo; ii++)
1500             {
1501                 dvalue = input[ii] * scale + zero;
1502 
1503                 if (dvalue < DINT_MIN)
1504                 {
1505                     *status = OVERFLOW_ERR;
1506                     output[ii] = INT_MIN;
1507                 }
1508                 else if (dvalue > DINT_MAX)
1509                 {
1510                     *status = OVERFLOW_ERR;
1511                     output[ii] = INT_MAX;
1512                 }
1513                 else
1514                     output[ii] = (int) dvalue;
1515             }
1516         }
1517     }
1518     else        /* must check for null values */
1519     {
1520         sptr = (short *) input;
1521 
1522 #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
1523         sptr++;       /* point to MSBs */
1524 #endif
1525 
1526         if (scale == 1. && zero == 0.)  /* no scaling */
1527         {
1528             for (ii = 0; ii < ntodo; ii++, sptr += 2)
1529             {
1530               if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
1531               {
1532                   if (iret == 1)  /* is it a NaN? */
1533                   {
1534                     *anynull = 1;
1535                     if (nullcheck == 1)
1536                         output[ii] = nullval;
1537                     else
1538                         nullarray[ii] = 1;
1539                   }
1540                   else            /* it's an underflow */
1541                      output[ii] = 0;
1542               }
1543               else
1544                 {
1545                     if (input[ii] < DINT_MIN)
1546                     {
1547                         *status = OVERFLOW_ERR;
1548                         output[ii] = INT_MIN;
1549                     }
1550                     else if (input[ii] > DINT_MAX)
1551                     {
1552                         *status = OVERFLOW_ERR;
1553                         output[ii] = INT_MAX;
1554                     }
1555                     else
1556                         output[ii] = (int) input[ii];
1557                 }
1558             }
1559         }
1560         else                  /* must scale the data */
1561         {
1562             for (ii = 0; ii < ntodo; ii++, sptr += 2)
1563             {
1564               if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
1565               {
1566                   if (iret == 1)  /* is it a NaN? */
1567                   {
1568                     *anynull = 1;
1569                     if (nullcheck == 1)
1570                         output[ii] = nullval;
1571                     else
1572                         nullarray[ii] = 1;
1573                   }
1574                   else            /* it's an underflow */
1575                   {
1576                     if (zero < DINT_MIN)
1577                     {
1578                         *status = OVERFLOW_ERR;
1579                         output[ii] = INT_MIN;
1580                     }
1581                     else if (zero > DINT_MAX)
1582                     {
1583                         *status = OVERFLOW_ERR;
1584                         output[ii] = INT_MAX;
1585                     }
1586                     else
1587                       output[ii] = (int) zero;
1588                   }
1589               }
1590               else
1591                 {
1592                     dvalue = input[ii] * scale + zero;
1593 
1594                     if (dvalue < DINT_MIN)
1595                     {
1596                         *status = OVERFLOW_ERR;
1597                         output[ii] = INT_MIN;
1598                     }
1599                     else if (dvalue > DINT_MAX)
1600                     {
1601                         *status = OVERFLOW_ERR;
1602                         output[ii] = INT_MAX;
1603                     }
1604                     else
1605                         output[ii] = (int) dvalue;
1606                 }
1607             }
1608         }
1609     }
1610     return(*status);
1611 }
1612 /*--------------------------------------------------------------------------*/
fffr8int(double * input,long ntodo,double scale,double zero,int nullcheck,int nullval,char * nullarray,int * anynull,int * output,int * status)1613 int fffr8int(double *input,       /* I - array of values to be converted     */
1614             long ntodo,           /* I - number of elements in the array     */
1615             double scale,         /* I - FITS TSCALn or BSCALE value         */
1616             double zero,          /* I - FITS TZEROn or BZERO  value         */
1617             int nullcheck,        /* I - null checking code; 0 = don't check */
1618                                   /*     1:set null pixels = nullval         */
1619                                   /*     2: if null pixel, set nullarray = 1 */
1620             int  nullval,         /* I - set null pixels, if nullcheck = 1   */
1621             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1622             int  *anynull,        /* O - set to 1 if any pixels are null     */
1623             int  *output,         /* O - array of converted pixels           */
1624             int *status)          /* IO - error status                       */
1625 /*
1626   Copy input to output following reading of the input from a FITS file.
1627   Check for null values and do datatype conversion and scaling if required.
1628   The nullcheck code value determines how any null values in the input array
1629   are treated.  A null value is an input pixel that is equal to NaN.  If
1630   nullcheck = 0, then no checking for nulls is performed and any null values
1631   will be transformed just like any other pixel.  If nullcheck = 1, then the
1632   output pixel will be set = nullval if the corresponding input pixel is null.
1633   If nullcheck = 2, then if the pixel is null then the corresponding value of
1634   nullarray will be set to 1; the value of nullarray for non-null pixels
1635   will = 0.  The anynull parameter will be set = 1 if any of the returned
1636   pixels are null, otherwise anynull will be returned with a value = 0;
1637 */
1638 {
1639     long ii;
1640     double dvalue;
1641     short *sptr, iret;
1642 
1643     if (nullcheck == 0)     /* no null checking required */
1644     {
1645         if (scale == 1. && zero == 0.)      /* no scaling */
1646         {
1647             for (ii = 0; ii < ntodo; ii++)
1648             {
1649                 if (input[ii] < DINT_MIN)
1650                 {
1651                     *status = OVERFLOW_ERR;
1652                     output[ii] = INT_MIN;
1653                 }
1654                 else if (input[ii] > DINT_MAX)
1655                 {
1656                     *status = OVERFLOW_ERR;
1657                     output[ii] = INT_MAX;
1658                 }
1659                 else
1660                     output[ii] = (int) input[ii];
1661             }
1662         }
1663         else             /* must scale the data */
1664         {
1665             for (ii = 0; ii < ntodo; ii++)
1666             {
1667                 dvalue = input[ii] * scale + zero;
1668 
1669                 if (dvalue < DINT_MIN)
1670                 {
1671                     *status = OVERFLOW_ERR;
1672                     output[ii] = INT_MIN;
1673                 }
1674                 else if (dvalue > DINT_MAX)
1675                 {
1676                     *status = OVERFLOW_ERR;
1677                     output[ii] = INT_MAX;
1678                 }
1679                 else
1680                     output[ii] = (int) dvalue;
1681             }
1682         }
1683     }
1684     else        /* must check for null values */
1685     {
1686         sptr = (short *) input;
1687 
1688 #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
1689         sptr += 3;       /* point to MSBs */
1690 #endif
1691         if (scale == 1. && zero == 0.)  /* no scaling */
1692         {
1693             for (ii = 0; ii < ntodo; ii++, sptr += 4)
1694             {
1695               if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
1696               {
1697                   if (iret == 1)  /* is it a NaN? */
1698                   {
1699                     *anynull = 1;
1700                     if (nullcheck == 1)
1701                         output[ii] = nullval;
1702                     else
1703                         nullarray[ii] = 1;
1704                   }
1705                   else            /* it's an underflow */
1706                      output[ii] = 0;
1707               }
1708               else
1709                 {
1710                     if (input[ii] < DINT_MIN)
1711                     {
1712                         *status = OVERFLOW_ERR;
1713                         output[ii] = INT_MIN;
1714                     }
1715                     else if (input[ii] > DINT_MAX)
1716                     {
1717                         *status = OVERFLOW_ERR;
1718                         output[ii] = INT_MAX;
1719                     }
1720                     else
1721                         output[ii] = (int) input[ii];
1722                 }
1723             }
1724         }
1725         else                  /* must scale the data */
1726         {
1727             for (ii = 0; ii < ntodo; ii++, sptr += 4)
1728             {
1729               if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
1730               {
1731                   if (iret == 1)  /* is it a NaN? */
1732                   {
1733                     *anynull = 1;
1734                     if (nullcheck == 1)
1735                         output[ii] = nullval;
1736                     else
1737                         nullarray[ii] = 1;
1738                   }
1739                   else            /* it's an underflow */
1740                   {
1741                     if (zero < DINT_MIN)
1742                     {
1743                         *status = OVERFLOW_ERR;
1744                         output[ii] = INT_MIN;
1745                     }
1746                     else if (zero > DINT_MAX)
1747                     {
1748                         *status = OVERFLOW_ERR;
1749                         output[ii] = INT_MAX;
1750                     }
1751                     else
1752                       output[ii] = (int) zero;
1753                   }
1754               }
1755               else
1756                 {
1757                     dvalue = input[ii] * scale + zero;
1758 
1759                     if (dvalue < DINT_MIN)
1760                     {
1761                         *status = OVERFLOW_ERR;
1762                         output[ii] = INT_MIN;
1763                     }
1764                     else if (dvalue > DINT_MAX)
1765                     {
1766                         *status = OVERFLOW_ERR;
1767                         output[ii] = INT_MAX;
1768                     }
1769                     else
1770                         output[ii] = (int) dvalue;
1771                 }
1772             }
1773         }
1774     }
1775     return(*status);
1776 }
1777 /*--------------------------------------------------------------------------*/
fffstrint(char * input,long ntodo,double scale,double zero,long twidth,double implipower,int nullcheck,char * snull,int nullval,char * nullarray,int * anynull,int * output,int * status)1778 int fffstrint(char *input,        /* I - array of values to be converted     */
1779             long ntodo,           /* I - number of elements in the array     */
1780             double scale,         /* I - FITS TSCALn or BSCALE value         */
1781             double zero,          /* I - FITS TZEROn or BZERO  value         */
1782             long twidth,          /* I - width of each substring of chars    */
1783             double implipower,    /* I - power of 10 of implied decimal      */
1784             int nullcheck,        /* I - null checking code; 0 = don't check */
1785                                   /*     1:set null pixels = nullval         */
1786                                   /*     2: if null pixel, set nullarray = 1 */
1787             char  *snull,         /* I - value of FITS null string, if any   */
1788             int nullval,          /* I - set null pixels, if nullcheck = 1   */
1789             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
1790             int  *anynull,        /* O - set to 1 if any pixels are null     */
1791             int *output,          /* O - array of converted pixels           */
1792             int *status)          /* IO - error status                       */
1793 /*
1794   Copy input to output following reading of the input from a FITS file. Check
1795   for null values and do scaling if required. The nullcheck code value
1796   determines how any null values in the input array are treated. A null
1797   value is an input pixel that is equal to snull.  If nullcheck= 0, then
1798   no special checking for nulls is performed.  If nullcheck = 1, then the
1799   output pixel will be set = nullval if the corresponding input pixel is null.
1800   If nullcheck = 2, then if the pixel is null then the corresponding value of
1801   nullarray will be set to 1; the value of nullarray for non-null pixels
1802   will = 0.  The anynull parameter will be set = 1 if any of the returned
1803   pixels are null, otherwise anynull will be returned with a value = 0;
1804 */
1805 {
1806     int nullen;
1807     long ii;
1808     double dvalue;
1809     char *cstring, message[FLEN_ERRMSG];
1810     char *cptr, *tpos;
1811     char tempstore, chrzero = '0';
1812     double val, power;
1813     int exponent, sign, esign, decpt;
1814 
1815     nullen = strlen(snull);
1816     cptr = input;  /* pointer to start of input string */
1817     for (ii = 0; ii < ntodo; ii++)
1818     {
1819       cstring = cptr;
1820       /* temporarily insert a null terminator at end of the string */
1821       tpos = cptr + twidth;
1822       tempstore = *tpos;
1823       *tpos = 0;
1824 
1825       /* check if null value is defined, and if the    */
1826       /* column string is identical to the null string */
1827       if (snull[0] != ASCII_NULL_UNDEFINED &&
1828          !strncmp(snull, cptr, nullen) )
1829       {
1830         if (nullcheck)
1831         {
1832           *anynull = 1;
1833           if (nullcheck == 1)
1834             output[ii] = nullval;
1835           else
1836             nullarray[ii] = 1;
1837         }
1838         cptr += twidth;
1839       }
1840       else
1841       {
1842         /* value is not the null value, so decode it */
1843         /* remove any embedded blank characters from the string */
1844 
1845         decpt = 0;
1846         sign = 1;
1847         val  = 0.;
1848         power = 1.;
1849         exponent = 0;
1850         esign = 1;
1851 
1852         while (*cptr == ' ')               /* skip leading blanks */
1853            cptr++;
1854 
1855         if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
1856         {
1857           if (*cptr == '-')
1858              sign = -1;
1859 
1860           cptr++;
1861 
1862           while (*cptr == ' ')         /* skip blanks between sign and value */
1863             cptr++;
1864         }
1865 
1866         while (*cptr >= '0' && *cptr <= '9')
1867         {
1868           val = val * 10. + *cptr - chrzero;  /* accumulate the value */
1869           cptr++;
1870 
1871           while (*cptr == ' ')         /* skip embedded blanks in the value */
1872             cptr++;
1873         }
1874 
1875         if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
1876         {
1877           decpt = 1;       /* set flag to show there was a decimal point */
1878           cptr++;
1879           while (*cptr == ' ')         /* skip any blanks */
1880             cptr++;
1881 
1882           while (*cptr >= '0' && *cptr <= '9')
1883           {
1884             val = val * 10. + *cptr - chrzero;  /* accumulate the value */
1885             power = power * 10.;
1886             cptr++;
1887 
1888             while (*cptr == ' ')         /* skip embedded blanks in the value */
1889               cptr++;
1890           }
1891         }
1892 
1893         if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
1894         {
1895           cptr++;
1896           while (*cptr == ' ')         /* skip blanks */
1897               cptr++;
1898 
1899           if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
1900           {
1901             if (*cptr == '-')
1902                esign = -1;
1903 
1904             cptr++;
1905 
1906             while (*cptr == ' ')        /* skip blanks between sign and exp */
1907               cptr++;
1908           }
1909 
1910           while (*cptr >= '0' && *cptr <= '9')
1911           {
1912             exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
1913             cptr++;
1914 
1915             while (*cptr == ' ')         /* skip embedded blanks */
1916               cptr++;
1917           }
1918         }
1919 
1920         if (*cptr  != 0)  /* should end up at the null terminator */
1921         {
1922           snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
1923           ffpmsg(message);
1924           snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
1925           ffpmsg(message);
1926           /* restore the char that was overwritten by the null */
1927           *tpos = tempstore;
1928           return(*status = BAD_C2D);
1929         }
1930 
1931         if (!decpt)  /* if no explicit decimal, use implied */
1932            power = implipower;
1933 
1934         dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
1935 
1936         dvalue = dvalue * scale + zero;   /* apply the scaling */
1937 
1938         if (dvalue < DINT_MIN)
1939         {
1940             *status = OVERFLOW_ERR;
1941             output[ii] = INT_MIN;
1942         }
1943         else if (dvalue > DINT_MAX)
1944         {
1945             *status = OVERFLOW_ERR;
1946             output[ii] = INT_MAX;
1947         }
1948         else
1949             output[ii] = (long) dvalue;
1950       }
1951       /* restore the char that was overwritten by the null */
1952       *tpos = tempstore;
1953     }
1954     return(*status);
1955 }
1956