1 /*  This file, putcolsb.c, contains routines that write data elements to   */
2 /*  a FITS image or table with signed char (signed byte) 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 <limits.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include "fitsio2.h"
12 
13 /*--------------------------------------------------------------------------*/
ffpprsb(fitsfile * fptr,long group,LONGLONG firstelem,LONGLONG nelem,signed char * array,int * status)14 int ffpprsb( fitsfile *fptr,  /* I - FITS file pointer                      */
15             long  group,     /* I - group to write(1 = 1st group)           */
16             LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
17             LONGLONG  nelem,     /* I - number of values to write               */
18             signed char *array, /* I - array of values that are written     */
19             int  *status)    /* IO - error status                           */
20 /*
21   Write an array of values to the primary array. Data conversion
22   and scaling will be performed if necessary (e.g, if the datatype of
23   the FITS array is not the same as the array being written).
24 */
25 {
26     long row;
27     signed char nullvalue;
28 
29     /*
30       the primary array is represented as a binary table:
31       each group of the primary array is a row in the table,
32       where the first column contains the group parameters
33       and the second column contains the image itself.
34     */
35 
36     if (fits_is_compressed_image(fptr, status))
37     {
38         /* this is a compressed image in a binary table */
39 
40         fits_write_compressed_pixels(fptr, TSBYTE, firstelem, nelem,
41             0, array, &nullvalue, status);
42         return(*status);
43     }
44 
45     row=maxvalue(1,group);
46 
47     ffpclsb(fptr, 2, row, firstelem, nelem, array, status);
48     return(*status);
49 }
50 /*--------------------------------------------------------------------------*/
ffppnsb(fitsfile * fptr,long group,LONGLONG firstelem,LONGLONG nelem,signed char * array,signed char nulval,int * status)51 int ffppnsb( fitsfile *fptr,  /* I - FITS file pointer                      */
52             long  group,     /* I - group to write(1 = 1st group)           */
53             LONGLONG  firstelem, /* I - first vector element to write(1 = 1st)  */
54             LONGLONG  nelem,     /* I - number of values to write               */
55             signed char *array, /* I - array of values that are written     */
56             signed char nulval, /* I - undefined pixel value                */
57             int  *status)    /* IO - error status                           */
58 /*
59   Write an array of values to the primary array. Data conversion
60   and scaling will be performed if necessary (e.g, if the datatype of the
61   FITS array is not the same as the array being written).  Any array values
62   that are equal to the value of nulval will be replaced with the null
63   pixel value that is appropriate for this column.
64 */
65 {
66     long row;
67     signed char nullvalue;
68 
69     /*
70       the primary array is represented as a binary table:
71       each group of the primary array is a row in the table,
72       where the first column contains the group parameters
73       and the second column contains the image itself.
74     */
75 
76     if (fits_is_compressed_image(fptr, status))
77     {
78         /* this is a compressed image in a binary table */
79 
80         nullvalue = nulval;  /* set local variable */
81         fits_write_compressed_pixels(fptr, TSBYTE, firstelem, nelem,
82             1, array, &nullvalue, status);
83         return(*status);
84     }
85 
86     row=maxvalue(1,group);
87 
88     ffpcnsb(fptr, 2, row, firstelem, nelem, array, nulval, status);
89     return(*status);
90 }
91 /*--------------------------------------------------------------------------*/
ffp2dsb(fitsfile * fptr,long group,LONGLONG ncols,LONGLONG naxis1,LONGLONG naxis2,signed char * array,int * status)92 int ffp2dsb(fitsfile *fptr,   /* I - FITS file pointer                    */
93            long  group,      /* I - group to write(1 = 1st group)         */
94            LONGLONG  ncols,      /* I - number of pixels in each row of array */
95            LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
96            LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
97            signed char *array, /* I - array to be written                 */
98            int  *status)     /* IO - error status                         */
99 /*
100   Write an entire 2-D array of values to the primary array. Data conversion
101   and scaling will be performed if necessary (e.g, if the datatype of the
102   FITS array is not the same as the array being written).
103 */
104 {
105     /* call the 3D writing routine, with the 3rd dimension = 1 */
106 
107     ffp3dsb(fptr, group, ncols, naxis2, naxis1, naxis2, 1, array, status);
108 
109     return(*status);
110 }
111 /*--------------------------------------------------------------------------*/
ffp3dsb(fitsfile * fptr,long group,LONGLONG ncols,LONGLONG nrows,LONGLONG naxis1,LONGLONG naxis2,LONGLONG naxis3,signed char * array,int * status)112 int ffp3dsb(fitsfile *fptr,   /* I - FITS file pointer                    */
113            long  group,      /* I - group to write(1 = 1st group)         */
114            LONGLONG  ncols,      /* I - number of pixels in each row of array */
115            LONGLONG  nrows,      /* I - number of rows in each plane of array */
116            LONGLONG  naxis1,     /* I - FITS image NAXIS1 value               */
117            LONGLONG  naxis2,     /* I - FITS image NAXIS2 value               */
118            LONGLONG  naxis3,     /* I - FITS image NAXIS3 value               */
119            signed char *array, /* I - array to be written                 */
120            int  *status)     /* IO - error status                         */
121 /*
122   Write an entire 3-D cube of values to the primary array. Data conversion
123   and scaling will be performed if necessary (e.g, if the datatype of the
124   FITS array is not the same as the array being written).
125 */
126 {
127     long tablerow, ii, jj;
128     long fpixel[3]= {1,1,1}, lpixel[3];
129     LONGLONG nfits, narray;
130     /*
131       the primary array is represented as a binary table:
132       each group of the primary array is a row in the table,
133       where the first column contains the group parameters
134       and the second column contains the image itself.
135     */
136 
137     if (fits_is_compressed_image(fptr, status))
138     {
139         /* this is a compressed image in a binary table */
140         lpixel[0] = (long) ncols;
141         lpixel[1] = (long) nrows;
142         lpixel[2] = (long) naxis3;
143 
144         fits_write_compressed_img(fptr, TSBYTE, fpixel, lpixel,
145             0,  array, NULL, status);
146 
147         return(*status);
148     }
149 
150     tablerow=maxvalue(1,group);
151 
152     if (ncols == naxis1 && nrows == naxis2)  /* arrays have same size? */
153     {
154       /* all the image pixels are contiguous, so write all at once */
155       ffpclsb(fptr, 2, tablerow, 1L, naxis1 * naxis2 * naxis3, array, status);
156       return(*status);
157     }
158 
159     if (ncols < naxis1 || nrows < naxis2)
160        return(*status = BAD_DIMEN);
161 
162     nfits = 1;   /* next pixel in FITS image to write to */
163     narray = 0;  /* next pixel in input array to be written */
164 
165     /* loop over naxis3 planes in the data cube */
166     for (jj = 0; jj < naxis3; jj++)
167     {
168       /* loop over the naxis2 rows in the FITS image, */
169       /* writing naxis1 pixels to each row            */
170 
171       for (ii = 0; ii < naxis2; ii++)
172       {
173        if (ffpclsb(fptr, 2, tablerow, nfits, naxis1,&array[narray],status) > 0)
174          return(*status);
175 
176        nfits += naxis1;
177        narray += ncols;
178       }
179       narray += (nrows - naxis2) * ncols;
180     }
181     return(*status);
182 }
183 /*--------------------------------------------------------------------------*/
ffpsssb(fitsfile * fptr,long group,long naxis,long * naxes,long * fpixel,long * lpixel,signed char * array,int * status)184 int ffpsssb(fitsfile *fptr,   /* I - FITS file pointer                      */
185            long  group,      /* I - group to write(1 = 1st group)           */
186            long  naxis,      /* I - number of data axes in array            */
187            long  *naxes,     /* I - size of each FITS axis                  */
188            long  *fpixel,    /* I - 1st pixel in each axis to write (1=1st) */
189            long  *lpixel,    /* I - last pixel in each axis to write        */
190            signed char *array, /* I - array to be written                   */
191            int  *status)     /* IO - error status                           */
192 /*
193   Write a subsection of pixels to the primary array or image.
194   A subsection is defined to be any contiguous rectangular
195   array of pixels within the n-dimensional FITS data file.
196   Data conversion and scaling will be performed if necessary
197   (e.g, if the datatype of the FITS array is not the same as
198   the array being written).
199 */
200 {
201     long tablerow;
202     LONGLONG fpix[7], dimen[7], astart, pstart;
203     LONGLONG off2, off3, off4, off5, off6, off7;
204     LONGLONG st10, st20, st30, st40, st50, st60, st70;
205     LONGLONG st1, st2, st3, st4, st5, st6, st7;
206     long ii, i1, i2, i3, i4, i5, i6, i7, irange[7];
207 
208     if (*status > 0)
209         return(*status);
210 
211     if (fits_is_compressed_image(fptr, status))
212     {
213         /* this is a compressed image in a binary table */
214 
215         fits_write_compressed_img(fptr, TSBYTE, fpixel, lpixel,
216             0,  array, NULL, status);
217 
218         return(*status);
219     }
220 
221     if (naxis < 1 || naxis > 7)
222       return(*status = BAD_DIMEN);
223 
224     tablerow=maxvalue(1,group);
225 
226      /* calculate the size and number of loops to perform in each dimension */
227     for (ii = 0; ii < 7; ii++)
228     {
229       fpix[ii]=1;
230       irange[ii]=1;
231       dimen[ii]=1;
232     }
233 
234     for (ii = 0; ii < naxis; ii++)
235     {
236       fpix[ii]=fpixel[ii];
237       irange[ii]=lpixel[ii]-fpixel[ii]+1;
238       dimen[ii]=naxes[ii];
239     }
240 
241     i1=irange[0];
242 
243     /* compute the pixel offset between each dimension */
244     off2 =     dimen[0];
245     off3 = off2 * dimen[1];
246     off4 = off3 * dimen[2];
247     off5 = off4 * dimen[3];
248     off6 = off5 * dimen[4];
249     off7 = off6 * dimen[5];
250 
251     st10 = fpix[0];
252     st20 = (fpix[1] - 1) * off2;
253     st30 = (fpix[2] - 1) * off3;
254     st40 = (fpix[3] - 1) * off4;
255     st50 = (fpix[4] - 1) * off5;
256     st60 = (fpix[5] - 1) * off6;
257     st70 = (fpix[6] - 1) * off7;
258 
259     /* store the initial offset in each dimension */
260     st1 = st10;
261     st2 = st20;
262     st3 = st30;
263     st4 = st40;
264     st5 = st50;
265     st6 = st60;
266     st7 = st70;
267 
268     astart = 0;
269 
270     for (i7 = 0; i7 < irange[6]; i7++)
271     {
272      for (i6 = 0; i6 < irange[5]; i6++)
273      {
274       for (i5 = 0; i5 < irange[4]; i5++)
275       {
276        for (i4 = 0; i4 < irange[3]; i4++)
277        {
278         for (i3 = 0; i3 < irange[2]; i3++)
279         {
280          pstart = st1 + st2 + st3 + st4 + st5 + st6 + st7;
281 
282          for (i2 = 0; i2 < irange[1]; i2++)
283          {
284            if (ffpclsb(fptr, 2, tablerow, pstart, i1, &array[astart],
285               status) > 0)
286               return(*status);
287 
288            astart += i1;
289            pstart += off2;
290          }
291          st2 = st20;
292          st3 = st3+off3;
293         }
294         st3 = st30;
295         st4 = st4+off4;
296        }
297        st4 = st40;
298        st5 = st5+off5;
299       }
300       st5 = st50;
301       st6 = st6+off6;
302      }
303      st6 = st60;
304      st7 = st7+off7;
305     }
306     return(*status);
307 }
308 /*--------------------------------------------------------------------------*/
ffpgpsb(fitsfile * fptr,long group,long firstelem,long nelem,signed char * array,int * status)309 int ffpgpsb( fitsfile *fptr,   /* I - FITS file pointer                     */
310             long  group,      /* I - group to write(1 = 1st group)          */
311             long  firstelem,  /* I - first vector element to write(1 = 1st) */
312             long  nelem,      /* I - number of values to write              */
313             signed char *array, /* I - array of values that are written     */
314             int  *status)     /* IO - error status                          */
315 /*
316   Write an array of group parameters to the primary array. Data conversion
317   and scaling will be performed if necessary (e.g, if the datatype of
318   the FITS array is not the same as the array being written).
319 */
320 {
321     long row;
322 
323     /*
324       the primary array is represented as a binary table:
325       each group of the primary array is a row in the table,
326       where the first column contains the group parameters
327       and the second column contains the image itself.
328     */
329 
330     row=maxvalue(1,group);
331 
332     ffpclsb(fptr, 1L, row, firstelem, nelem, array, status);
333     return(*status);
334 }
335 /*--------------------------------------------------------------------------*/
ffpclsb(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,signed char * array,int * status)336 int ffpclsb( fitsfile *fptr,  /* I - FITS file pointer                      */
337             int  colnum,     /* I - number of column to write (1 = 1st col) */
338             LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
339             LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
340             LONGLONG  nelem,     /* I - number of values to write               */
341             signed char *array, /* I - array of values to write             */
342             int  *status)    /* IO - error status                           */
343 /*
344   Write an array of values to a column in the current FITS HDU.
345   The column number may refer to a real column in an ASCII or binary table,
346   or it may refer to a virtual column in a 1 or more grouped FITS primary
347   array.  FITSIO treats a primary array as a binary table with
348   2 vector columns: the first column contains the group parameters (often
349   with length = 0) and the second column contains the array of image pixels.
350   Each row of the table represents a group in the case of multigroup FITS
351   images.
352 
353   The input array of values will be converted to the datatype of the column
354   and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary.
355 */
356 {
357     int tcode, maxelem, hdutype;
358     long twidth, incre;
359     long ntodo;
360     LONGLONG repeat, startpos, elemnum, wrtptr, rowlen, rownum, remain, next, tnull;
361     double scale, zero;
362     char tform[20], cform[20];
363     char message[FLEN_ERRMSG];
364 
365     char snull[20];   /*  the FITS null value  */
366 
367     double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
368     void *buffer;
369 
370     if (*status > 0)           /* inherit input status value if > 0 */
371         return(*status);
372 
373     buffer = cbuff;
374 
375     /*---------------------------------------------------*/
376     /*  Check input and get parameters about the column: */
377     /*---------------------------------------------------*/
378     if (ffgcprll( fptr, colnum, firstrow, firstelem, nelem, 1, &scale, &zero,
379         tform, &twidth, &tcode, &maxelem, &startpos,  &elemnum, &incre,
380         &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0)
381         return(*status);
382 
383     if (tcode == TSTRING)
384          ffcfmt(tform, cform);     /* derive C format for writing strings */
385 
386     /*---------------------------------------------------------------------*/
387     /*  Now write the pixels to the FITS column.                           */
388     /*  First call the ffXXfYY routine to  (1) convert the datatype        */
389     /*  if necessary, and (2) scale the values by the FITS TSCALn and      */
390     /*  TZEROn linear scaling parameters into a temporary buffer.          */
391     /*---------------------------------------------------------------------*/
392     remain = nelem;           /* remaining number of values to write  */
393     next = 0;                 /* next element in array to be written  */
394     rownum = 0;               /* row number, relative to firstrow     */
395 
396     while (remain)
397     {
398         /* limit the number of pixels to process a one time to the number that
399            will fit in the buffer space or to the number of pixels that remain
400            in the current vector, which ever is smaller.
401         */
402         ntodo = (long) minvalue(remain, maxelem);
403         ntodo = (long) minvalue(ntodo, (repeat - elemnum));
404 
405         wrtptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * incre);
406         ffmbyt(fptr, wrtptr, IGNORE_EOF, status); /* move to write position */
407 
408         switch (tcode)
409         {
410             case (TBYTE):
411 
412                 /* convert the raw data before writing to FITS file */
413                 ffs1fi1(&array[next], ntodo, scale, zero,
414                         (unsigned char *) buffer, status);
415                 ffpi1b(fptr, ntodo, incre, (unsigned char *) buffer, status);
416 
417               break;
418 
419             case (TLONGLONG):
420 
421                 ffs1fi8(&array[next], ntodo, scale, zero,
422                         (LONGLONG *) buffer, status);
423                 ffpi8b(fptr, ntodo, incre, (long *) buffer, status);
424                 break;
425 
426             case (TSHORT):
427 
428                 ffs1fi2(&array[next], ntodo, scale, zero,
429                         (short *) buffer, status);
430                 ffpi2b(fptr, ntodo, incre, (short *) buffer, status);
431                 break;
432 
433             case (TLONG):
434 
435                 ffs1fi4(&array[next], ntodo, scale, zero,
436                         (INT32BIT *) buffer, status);
437                 ffpi4b(fptr, ntodo, incre, (INT32BIT *) buffer, status);
438                 break;
439 
440             case (TFLOAT):
441 
442                 ffs1fr4(&array[next], ntodo, scale, zero,
443                         (float *)  buffer, status);
444                 ffpr4b(fptr, ntodo, incre, (float *) buffer, status);
445                 break;
446 
447             case (TDOUBLE):
448                 ffs1fr8(&array[next], ntodo, scale, zero,
449                         (double *) buffer, status);
450                 ffpr8b(fptr, ntodo, incre, (double *) buffer, status);
451                 break;
452 
453             case (TSTRING):  /* numerical column in an ASCII table */
454 
455                 if (strchr(tform,'A'))
456                 {
457                     /* write raw input bytes without conversion        */
458                     /* This case is a hack to let users write a stream */
459                     /* of bytes directly to the 'A' format column      */
460 
461                     if (incre == twidth)
462                         ffpbyt(fptr, ntodo, &array[next], status);
463                     else
464                         ffpbytoff(fptr, twidth, ntodo/twidth, incre - twidth,
465                                 &array[next], status);
466                     break;
467                 }
468                 else if (cform[1] != 's')  /*  "%s" format is a string */
469                 {
470                   ffs1fstr(&array[next], ntodo, scale, zero, cform,
471                           twidth, (char *) buffer, status);
472 
473                   if (incre == twidth)    /* contiguous bytes */
474                      ffpbyt(fptr, ntodo * twidth, buffer, status);
475                   else
476                      ffpbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
477                             status);
478                   break;
479                 }
480                 /* can't write to string column, so fall thru to default: */
481 
482             default:  /*  error trap  */
483                 snprintf(message, FLEN_ERRMSG,
484                        "Cannot write numbers to column %d which has format %s",
485                         colnum,tform);
486                 ffpmsg(message);
487                 if (hdutype == ASCII_TBL)
488                     return(*status = BAD_ATABLE_FORMAT);
489                 else
490                     return(*status = BAD_BTABLE_FORMAT);
491 
492         } /* End of switch block */
493 
494         /*-------------------------*/
495         /*  Check for fatal error  */
496         /*-------------------------*/
497         if (*status > 0)  /* test for error during previous write operation */
498         {
499           snprintf(message,FLEN_ERRMSG,
500           "Error writing elements %.0f thru %.0f of input data array (ffpclsb).",
501               (double) (next+1), (double) (next+ntodo));
502           ffpmsg(message);
503           return(*status);
504         }
505 
506         /*--------------------------------------------*/
507         /*  increment the counters for the next loop  */
508         /*--------------------------------------------*/
509         remain -= ntodo;
510         if (remain)
511         {
512             next += ntodo;
513             elemnum += ntodo;
514             if (elemnum == repeat)  /* completed a row; start on next row */
515             {
516                 elemnum = 0;
517                 rownum++;
518             }
519         }
520     }  /*  End of main while Loop  */
521 
522 
523     /*--------------------------------*/
524     /*  check for numerical overflow  */
525     /*--------------------------------*/
526     if (*status == OVERFLOW_ERR)
527     {
528       ffpmsg(
529       "Numerical overflow during type conversion while writing FITS data.");
530       *status = NUM_OVERFLOW;
531     }
532 
533     return(*status);
534 }
535 /*--------------------------------------------------------------------------*/
ffpcnsb(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,signed char * array,signed char nulvalue,int * status)536 int ffpcnsb( fitsfile *fptr,  /* I - FITS file pointer                      */
537             int  colnum,     /* I - number of column to write (1 = 1st col) */
538             LONGLONG  firstrow,  /* I - first row to write (1 = 1st row)        */
539             LONGLONG  firstelem, /* I - first vector element to write (1 = 1st) */
540             LONGLONG  nelem,     /* I - number of values to write               */
541             signed char *array,   /* I - array of values to write           */
542             signed char nulvalue, /* I - flag for undefined pixels          */
543             int  *status)    /* IO - error status                           */
544 /*
545   Write an array of elements to the specified column of a table.  Any input
546   pixels equal to the value of nulvalue will be replaced by the appropriate
547   null value in the output FITS file.
548 
549   The input array of values will be converted to the datatype of the column
550   and will be inverse-scaled by the FITS TSCALn and TZEROn values if necessary
551 */
552 {
553     tcolumn *colptr;
554     LONGLONG  ngood = 0, nbad = 0, ii;
555     LONGLONG repeat, first, fstelm, fstrow;
556     int tcode, overflow = 0;
557 
558     if (*status > 0)
559         return(*status);
560 
561     /* reset position to the correct HDU if necessary */
562     if (fptr->HDUposition != (fptr->Fptr)->curhdu)
563     {
564         ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
565     }
566     else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
567     {
568         if ( ffrdef(fptr, status) > 0)               /* rescan header */
569             return(*status);
570     }
571 
572     colptr  = (fptr->Fptr)->tableptr;   /* point to first column */
573     colptr += (colnum - 1);     /* offset to correct column structure */
574 
575     tcode  = colptr->tdatatype;
576 
577     if (tcode > 0)
578        repeat = colptr->trepeat;  /* repeat count for this column */
579     else
580        repeat = firstelem -1 + nelem;  /* variable length arrays */
581 
582     /* if variable length array, first write the whole input vector,
583        then go back and fill in the nulls */
584     if (tcode < 0) {
585       if (ffpclsb(fptr, colnum, firstrow, firstelem, nelem, array, status) > 0) {
586         if (*status == NUM_OVERFLOW)
587 	{
588 	  /* ignore overflows, which are possibly the null pixel values */
589 	  /*  overflow = 1;   */
590 	  *status = 0;
591 	} else {
592           return(*status);
593 	}
594       }
595     }
596 
597     /* absolute element number in the column */
598     first = (firstrow - 1) * repeat + firstelem;
599 
600     for (ii = 0; ii < nelem; ii++)
601     {
602       if (array[ii] != nulvalue)  /* is this a good pixel? */
603       {
604          if (nbad)  /* write previous string of bad pixels */
605          {
606             fstelm = ii - nbad + first;  /* absolute element number */
607             fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
608             fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
609 
610             if (ffpclu(fptr, colnum, fstrow, fstelm, nbad, status) > 0)
611                 return(*status);
612 
613             nbad=0;
614          }
615 
616          ngood = ngood + 1;  /* the consecutive number of good pixels */
617       }
618       else
619       {
620          if (ngood)  /* write previous string of good pixels */
621          {
622             fstelm = ii - ngood + first;  /* absolute element number */
623             fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
624             fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
625 
626             if (tcode > 0) {  /* variable length arrays have already been written */
627               if (ffpclsb(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood],
628                 status) > 0) {
629 		if (*status == NUM_OVERFLOW)
630 		{
631 		  overflow = 1;
632 		  *status = 0;
633 		} else {
634                   return(*status);
635 		}
636 	      }
637 	    }
638             ngood=0;
639          }
640 
641          nbad = nbad + 1;  /* the consecutive number of bad pixels */
642       }
643     }
644 
645     /* finished loop;  now just write the last set of pixels */
646 
647     if (ngood)  /* write last string of good pixels */
648     {
649       fstelm = ii - ngood + first;  /* absolute element number */
650       fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
651       fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
652 
653       if (tcode > 0) {  /* variable length arrays have already been written */
654         ffpclsb(fptr, colnum, fstrow, fstelm, ngood, &array[ii-ngood], status);
655       }
656     }
657     else if (nbad) /* write last string of bad pixels */
658     {
659       fstelm = ii - nbad + first;  /* absolute element number */
660       fstrow = (fstelm - 1) / repeat + 1;  /* starting row number */
661       fstelm = fstelm - (fstrow - 1) * repeat;  /* relative number */
662 
663       ffpclu(fptr, colnum, fstrow, fstelm, nbad, status);
664     }
665 
666     if (*status <= 0) {
667       if (overflow) {
668         *status = NUM_OVERFLOW;
669       }
670     }
671 
672     return(*status);
673 }
674 /*--------------------------------------------------------------------------*/
ffs1fi1(signed char * input,long ntodo,double scale,double zero,unsigned char * output,int * status)675 int ffs1fi1(signed char *input,    /* I - array of values to be converted  */
676             long ntodo,            /* I - number of elements in the array  */
677             double scale,          /* I - FITS TSCALn or BSCALE value      */
678             double zero,           /* I - FITS TZEROn or BZERO  value      */
679             unsigned char *output, /* O - output array of converted values */
680             int *status)           /* IO - error status                    */
681 /*
682   Copy input to output prior to writing output to a FITS file.
683   Do datatype conversion and scaling if required
684 */
685 {
686     long ii;
687     double dvalue;
688 
689     if (scale == 1. && zero == -128.)
690     {
691         /* Instead of adding 128, it is more efficient */
692         /* to just flip the sign bit with the XOR operator */
693 
694         for (ii = 0; ii < ntodo; ii++)
695              output[ii] =  ( *(unsigned char *) &input[ii] ) ^ 0x80;
696     }
697     else if (scale == 1. && zero == 0.)
698     {
699         for (ii = 0; ii < ntodo; ii++)
700         {
701             if (input[ii] < 0)
702             {
703                 *status = OVERFLOW_ERR;
704                 output[ii] = 0;
705             }
706             else
707                 output[ii] = (unsigned char) input[ii];
708         }
709     }
710     else
711     {
712         for (ii = 0; ii < ntodo; ii++)
713         {
714             dvalue = ( ((double) input[ii]) - zero) / scale;
715 
716             if (dvalue < DUCHAR_MIN)
717             {
718                 *status = OVERFLOW_ERR;
719                 output[ii] = 0;
720             }
721             else if (dvalue > DUCHAR_MAX)
722             {
723                 *status = OVERFLOW_ERR;
724                 output[ii] = UCHAR_MAX;
725             }
726             else
727                 output[ii] = (unsigned char) (dvalue + .5);
728         }
729     }
730     return(*status);
731 }
732 /*--------------------------------------------------------------------------*/
ffs1fi2(signed char * input,long ntodo,double scale,double zero,short * output,int * status)733 int ffs1fi2(signed char *input,    /* I - array of values to be converted  */
734             long ntodo,            /* I - number of elements in the array  */
735             double scale,          /* I - FITS TSCALn or BSCALE value      */
736             double zero,           /* I - FITS TZEROn or BZERO  value      */
737             short *output,         /* O - output array of converted values */
738             int *status)           /* IO - error status                    */
739 /*
740   Copy input to output prior to writing output to a FITS file.
741   Do datatype conversion and scaling if required
742 */
743 {
744     long ii;
745     double dvalue;
746 
747     if (scale == 1. && zero == 0.)
748     {
749         for (ii = 0; ii < ntodo; ii++)
750             output[ii] = input[ii];   /* just copy input to output */
751     }
752     else
753     {
754         for (ii = 0; ii < ntodo; ii++)
755         {
756             dvalue = (((double) input[ii]) - zero) / scale;
757 
758             if (dvalue < DSHRT_MIN)
759             {
760                 *status = OVERFLOW_ERR;
761                 output[ii] = SHRT_MIN;
762             }
763             else if (dvalue > DSHRT_MAX)
764             {
765                 *status = OVERFLOW_ERR;
766                 output[ii] = SHRT_MAX;
767             }
768             else
769             {
770                 if (dvalue >= 0)
771                     output[ii] = (short) (dvalue + .5);
772                 else
773                     output[ii] = (short) (dvalue - .5);
774             }
775         }
776     }
777     return(*status);
778 }
779 /*--------------------------------------------------------------------------*/
ffs1fi4(signed char * input,long ntodo,double scale,double zero,INT32BIT * output,int * status)780 int ffs1fi4(signed char *input,    /* I - array of values to be converted  */
781             long ntodo,            /* I - number of elements in the array  */
782             double scale,          /* I - FITS TSCALn or BSCALE value      */
783             double zero,           /* I - FITS TZEROn or BZERO  value      */
784             INT32BIT *output,      /* O - output array of converted values */
785             int *status)           /* IO - error status                    */
786 /*
787   Copy input to output prior to writing output to a FITS file.
788   Do datatype conversion and scaling if required
789 */
790 {
791     long ii;
792     double dvalue;
793 
794     if (scale == 1. && zero == 0.)
795     {
796         for (ii = 0; ii < ntodo; ii++)
797             output[ii] = (INT32BIT) input[ii];   /* copy input to output */
798     }
799     else
800     {
801         for (ii = 0; ii < ntodo; ii++)
802         {
803             dvalue = (((double) input[ii]) - zero) / scale;
804 
805             if (dvalue < DINT_MIN)
806             {
807                 *status = OVERFLOW_ERR;
808                 output[ii] = INT32_MIN;
809             }
810             else if (dvalue > DINT_MAX)
811             {
812                 *status = OVERFLOW_ERR;
813                 output[ii] = INT32_MAX;
814             }
815             else
816             {
817                 if (dvalue >= 0)
818                     output[ii] = (INT32BIT) (dvalue + .5);
819                 else
820                     output[ii] = (INT32BIT) (dvalue - .5);
821             }
822         }
823     }
824     return(*status);
825 }
826 /*--------------------------------------------------------------------------*/
ffs1fi8(signed char * input,long ntodo,double scale,double zero,LONGLONG * output,int * status)827 int ffs1fi8(signed char *input,   /* I - array of values to be converted  */
828             long ntodo,           /* I - number of elements in the array  */
829             double scale,         /* I - FITS TSCALn or BSCALE value      */
830             double zero,          /* I - FITS TZEROn or BZERO  value      */
831             LONGLONG *output,     /* O - output array of converted values */
832             int *status)          /* IO - error status                    */
833 /*
834   Copy input to output prior to writing output to a FITS file.
835   Do datatype conversion and scaling if required
836 */
837 {
838     long ii;
839     double dvalue;
840 
841     if (scale == 1. && zero ==  9223372036854775808.)
842     {
843         /* Writing to unsigned long long column. Input values must not be negative */
844         /* Instead of subtracting 9223372036854775808, it is more efficient */
845         /* and more precise to just flip the sign bit with the XOR operator */
846 
847         for (ii = 0; ii < ntodo; ii++) {
848            if (input[ii] < 0) {
849               *status = OVERFLOW_ERR;
850               output[ii] = LONGLONG_MIN;
851            } else {
852               output[ii] =  ((LONGLONG) input[ii]) ^ 0x8000000000000000;
853            }
854         }
855     }
856     else if (scale == 1. && zero == 0.)
857     {
858         for (ii = 0; ii < ntodo; ii++)
859                 output[ii] = input[ii];
860     }
861     else
862     {
863         for (ii = 0; ii < ntodo; ii++)
864         {
865             dvalue = (input[ii] - zero) / scale;
866 
867             if (dvalue < DLONGLONG_MIN)
868             {
869                 *status = OVERFLOW_ERR;
870                 output[ii] = LONGLONG_MIN;
871             }
872             else if (dvalue > DLONGLONG_MAX)
873             {
874                 *status = OVERFLOW_ERR;
875                 output[ii] = LONGLONG_MAX;
876             }
877             else
878             {
879                 if (dvalue >= 0)
880                     output[ii] = (LONGLONG) (dvalue + .5);
881                 else
882                     output[ii] = (LONGLONG) (dvalue - .5);
883             }
884         }
885     }
886     return(*status);
887 }
888 /*--------------------------------------------------------------------------*/
ffs1fr4(signed char * input,long ntodo,double scale,double zero,float * output,int * status)889 int ffs1fr4(signed char *input,    /* I - array of values to be converted  */
890             long ntodo,            /* I - number of elements in the array  */
891             double scale,          /* I - FITS TSCALn or BSCALE value      */
892             double zero,           /* I - FITS TZEROn or BZERO  value      */
893             float *output,         /* O - output array of converted values */
894             int *status)           /* IO - error status                    */
895 /*
896   Copy input to output prior to writing output to a FITS file.
897   Do datatype conversion and scaling if required.
898 */
899 {
900     long ii;
901 
902     if (scale == 1. && zero == 0.)
903     {
904         for (ii = 0; ii < ntodo; ii++)
905                 output[ii] = (float) input[ii];
906     }
907     else
908     {
909         for (ii = 0; ii < ntodo; ii++)
910             output[ii] = (float) (( ( (double) input[ii] ) - zero) / scale);
911     }
912     return(*status);
913 }
914 /*--------------------------------------------------------------------------*/
ffs1fr8(signed char * input,long ntodo,double scale,double zero,double * output,int * status)915 int ffs1fr8(signed char *input,    /* I - array of values to be converted  */
916             long ntodo,            /* I - number of elements in the array  */
917             double scale,          /* I - FITS TSCALn or BSCALE value      */
918             double zero,           /* I - FITS TZEROn or BZERO  value      */
919             double *output,        /* O - output array of converted values */
920             int *status)           /* IO - error status                    */
921 /*
922   Copy input to output prior to writing output to a FITS file.
923   Do datatype conversion and scaling if required.
924 */
925 {
926     long ii;
927 
928     if (scale == 1. && zero == 0.)
929     {
930         for (ii = 0; ii < ntodo; ii++)
931                 output[ii] = (double) input[ii];
932     }
933     else
934     {
935         for (ii = 0; ii < ntodo; ii++)
936             output[ii] = ( ( (double) input[ii] ) - zero) / scale;
937     }
938     return(*status);
939 }
940 /*--------------------------------------------------------------------------*/
ffs1fstr(signed char * input,long ntodo,double scale,double zero,char * cform,long twidth,char * output,int * status)941 int ffs1fstr(signed char *input, /* I - array of values to be converted  */
942             long ntodo,        /* I - number of elements in the array  */
943             double scale,      /* I - FITS TSCALn or BSCALE value      */
944             double zero,       /* I - FITS TZEROn or BZERO  value      */
945             char *cform,       /* I - format for output string values  */
946             long twidth,       /* I - width of each field, in chars    */
947             char *output,      /* O - output array of converted values */
948             int *status)       /* IO - error status                    */
949 /*
950   Copy input to output prior to writing output to a FITS file.
951   Do scaling if required.
952 */
953 {
954     long ii;
955     double dvalue;
956     char *cptr;
957 
958     cptr = output;
959 
960 
961     if (scale == 1. && zero == 0.)
962     {
963         for (ii = 0; ii < ntodo; ii++)
964         {
965            sprintf(output, cform, (double) input[ii]);
966            output += twidth;
967 
968            if (*output)  /* if this char != \0, then overflow occurred */
969               *status = OVERFLOW_ERR;
970         }
971     }
972     else
973     {
974         for (ii = 0; ii < ntodo; ii++)
975         {
976           dvalue = ((double) input[ii] - zero) / scale;
977           sprintf(output, cform, dvalue);
978           output += twidth;
979 
980           if (*output)  /* if this char != \0, then overflow occurred */
981             *status = OVERFLOW_ERR;
982         }
983     }
984 
985     /* replace any commas with periods (e.g., in French locale) */
986     while ((cptr = strchr(cptr, ','))) *cptr = '.';
987 
988     return(*status);
989 }
990