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