	SUBROUTINE RWFITSROW(LU,NMAP,NPLANE,DATA,LENGTH,NROW)
C
C       This subroutine reads from or writes to a FITS file, a single 
C  row of data.  One should not call RWFITSROW directly but rather one of 
C  the various entries, e.g., RDFITSROW or RDDPFITSROW for reading, and
C  WRFITSROW or WRDPFITSROW, for writing.  Each of the entries can read
C  or write data for several different value of BITPIX, as contained
C  in the COMMON block FITSFACTS_INTEGER4.  The choice of which subroutine
C  one uses will affect whether the data array in the argument list is
C  REAL*4 or REAL*8.
C			Donald H. Gudehus, June, 2006
C			Version 2, D. H. Gudehus, January 28, 2008
C			Improved the accuracy when writing by taking
C			the nearest integer.
C
C	LU	(C)	Logical unit for I/O
C	NMAP	(C)	Number of map to be read or written to, counting
C			from 1
C	NPLANE	(C)	Number of plane to be read or written to, counting
C			from 1
C	DATA	(C/R)	Array to receive data on read or to provide data
C			on write
C	LENGTH	(C)	Dimension of array.  Should be at least as big as the
C			row length.
C	NROW	(C)	Row number to be read or written, counting from 1
C
	INTEGER LU,LENGTH,NROW
	REAL DATA(LENGTH)
	REAL*8 DATADP(LENGTH)
C
	INCLUDE 'fitsfacts.for'
C
	BYTE PHYSREC(3000)
	INTEGER*2 I2REC(1500)
	INTEGER I4REC(750),I4X2REC(1500)
	REAL*4 R4REC(750)
	REAL*8 R8REC(375)
	EQUIVALENCE (PHYSREC,I2REC,I4REC,I4X2REC,R4REC,R8REC)
	CHARACTER*3 PRGFMAT
	CHARACTER*4 CALL
	INTEGER BSWAP,WSWAP
C
	CHARACTER*1 SYSTEM_ENDIAN
	COMMON /SYS_ENDIAN/ SYSTEM_ENDIAN
C
	ENTRY RDFITSROW(LU,NMAP,NPLANE,DATA,LENGTH,NROW)
	CALL='READ'
	PRGFMAT='R4'
	GO TO 100
C
	ENTRY WRFITSROW(LU,NMAP,NPLANE,DATA,LENGTH,NROW)
	CALL='WRIT'
	PRGFMAT='R4'
	GO TO 100
C
	ENTRY RDDPFITSROW(LU,NMAP,NPLANE,DATADP,LENGTH,NROW)
	CALL='READ'
	PRGFMAT='R8'
	GO TO 100
C
	ENTRY WRDPFITSROW(LU,NMAP,NPLANE,DATADP,LENGTH,NROW)
	CALL='WRIT'
	PRGFMAT='R8'
	GO TO 100
C
 100	IBLKLEN=2880
	BSWAP=1
	WSWAP=1
C
	NBYTESPERROW=NAXIS1(NMAP,LU)*ABS(BITPIX(NMAP,LU))/8
	NBYTESPERPLANE=NBYTESPERROW*NAXIS2(NMAP,LU)
	IBYTEOFFSET1=(NROW-1)*NBYTESPERROW+(NPLANE-1)*NBYTESPERPLANE
			!  Beginning of map to row start
c	IBYTEOFFSET2=IBYTEOFFSET1+NBYTESPERROW
	IBYTEOFFSET2=IBYTEOFFSET1+NBYTESPERROW-1
			!  Beginning of map to row end
	IRECOFFSET1=IBYTEOFFSET1/IBLKLEN
	IRECOFFSET2=IBYTEOFFSET2/IBLKLEN
	IRECSTART=MAPRECORDS(1,NMAP,LU)+IRECOFFSET1
	IRECEND=MAPRECORDS(1,NMAP,LU)+IRECOFFSET2
	IBYTEOFFSET3=IBYTEOFFSET1-IRECOFFSET1*IBLKLEN
		!  From start record boundary to row start
	IBYTEOFFSET4=IBYTEOFFSET2-IRECOFFSET2*IBLKLEN
		!  From end record boundary to row end
	IF (CALL.EQ.'READ') THEN
	  ICOUNT=1
	  DO IR=IRECSTART,IRECEND
	    READ(LU,REC=IR,IOSTAT=ISTAT) (PHYSREC(I),I=1,IBLKLEN)
	    IF (BITPIX(NMAP,LU).EQ.8) THEN
	      IF (IRECSTART.EQ.IRECEND) THEN
	        ISTART=IBYTEOFFSET3+1
	!  Adds 1 because we want an index in the record
	        IEND=IBYTEOFFSET4+1
	      ELSE
	        IF (IR.EQ.IRECSTART) THEN
	          ISTART=IBYTEOFFSET3+1
	          IEND=IBLKLEN
	        ELSE IF (IR.EQ.IRECEND) THEN
	          ISTART=1
	          IEND=IBYTEOFFSET4+1
	        ELSE
	          ISTART=1
	          IEND=IBLKLEN
	        END IF
	      END IF
	      IF (PRGFMAT.EQ.'R4') THEN
	        DO I=ISTART,IEND
	          IF (PHYSREC(I).LT.0) THEN
	            DATA(ICOUNT)=BSCALE(NMAP,LU)*(PHYSREC(I)+256)+
	1           BZERO(NMAP,LU)
	          ELSE
	            DATA(ICOUNT)=BSCALE(NMAP,LU)*PHYSREC(I)+
	1           BZERO(NMAP,LU)
	          END IF
	          ICOUNT=ICOUNT+1
	        END DO
	      ELSE IF (PRGFMAT.EQ.'R8') THEN
	        DO I=ISTART,IEND
	          IF (PHYSREC(I).LT.0) THEN
	            DATADP(ICOUNT)=BSCALE(NMAP,LU)*(PHYSREC(I)+256)+
	1           BZERO(NMAP,LU)
	          ELSE
	            DATADP(ICOUNT)=BSCALE(NMAP,LU)*PHYSREC(I)+
	1           BZERO(NMAP,LU)
	          END IF
	          ICOUNT=ICOUNT+1
	        END DO
	      END IF
	    ELSE IF (BITPIX(NMAP,LU).EQ.16) THEN
	      IF (SYSTEM_ENDIAN.EQ.'L') THEN
	        CALL IBMI2(I2REC,I2REC,IBLKLEN/2)
	      END IF
	      IF (IRECSTART.EQ.IRECEND) THEN
	        ISTART=IBYTEOFFSET3/2+1
	        IEND=IBYTEOFFSET4/2+1
	      ELSE
	        IF (IR.EQ.IRECSTART) THEN
	          ISTART=IBYTEOFFSET3/2+1
	          IEND=IBLKLEN/2
	        ELSE IF (IR.EQ.IRECEND) THEN
	          ISTART=1
	          IEND=IBYTEOFFSET4/2+1
	        ELSE
	          ISTART=1
	          IEND=IBLKLEN/2
	        END IF
	      END IF
	      IF (PRGFMAT.EQ.'R4') THEN
	        DO I=ISTART,IEND
	          DATA(ICOUNT)=BSCALE(NMAP,LU)*I2REC(I)+
	1         BZERO(NMAP,LU)
	          ICOUNT=ICOUNT+1
	        END DO
	      ELSE IF (PRGFMAT.EQ.'R8') THEN
	        DO I=ISTART,IEND
	          DATADP(ICOUNT)=BSCALE(NMAP,LU)*I2REC(I)+
	1         BZERO(NMAP,LU)
	          ICOUNT=ICOUNT+1
	        END DO
	      END IF
	    ELSE IF (BITPIX(NMAP,LU).EQ.32) THEN
	      IF (SYSTEM_ENDIAN.EQ.'L') THEN
	        CALL IBMI4(I4REC,I4REC,IBLKLEN/4)
	      END IF
	      IF (IRECSTART.EQ.IRECEND) THEN
	        ISTART=IBYTEOFFSET3/4+1
	        IEND=IBYTEOFFSET4/4+1
	      ELSE
	        IF (IR.EQ.IRECSTART) THEN
	          ISTART=IBYTEOFFSET3/4+1
	          IEND=IBLKLEN/4
	        ELSE IF (IR.EQ.IRECEND) THEN
	          ISTART=1
	          IEND=IBYTEOFFSET4/4+1
	        ELSE
	          ISTART=1
	          IEND=IBLKLEN/4
	        END IF
	      END IF
	      IF (PRGFMAT.EQ.'R4') THEN
	        DO I=ISTART,IEND
	          DATA(ICOUNT)=BSCALE(NMAP,LU)*I4REC(I)+
	1         BZERO(NMAP,LU)
	          ICOUNT=ICOUNT+1
	        END DO
	      ELSE IF (PRGFMAT.EQ.'R8') THEN
	        DO I=ISTART,IEND
	          DATADP(ICOUNT)=BSCALE(NMAP,LU)*I4REC(I)+
	1         BZERO(NMAP,LU)
	          ICOUNT=ICOUNT+1
	        END DO
	      END IF
	    ELSE IF (BITPIX(NMAP,LU).EQ.-32) THEN
	      IF (SYSTEM_ENDIAN.EQ.'L') THEN
	        CALL IEEE2UNIX(I4REC,IBLKLEN/4,BSWAP,WSWAP)
	      END IF
	      IF (IRECSTART.EQ.IRECEND) THEN
	        ISTART=IBYTEOFFSET3/4+1
	        IEND=IBYTEOFFSET4/4+1
	      ELSE
	        IF (IR.EQ.IRECSTART) THEN
	          ISTART=IBYTEOFFSET3/4+1
	          IEND=IBLKLEN/4
	        ELSE IF (IR.EQ.IRECEND) THEN
	          ISTART=1
	          IEND=IBYTEOFFSET4/4+1
	        ELSE
	          ISTART=1
	          IEND=IBLKLEN/4
	        END IF
	      END IF
	      IF (PRGFMAT.EQ.'R4') THEN
	        DO I=ISTART,IEND
	          DATA(ICOUNT)=BSCALE(NMAP,LU)*R4REC(I)+
	1         BZERO(NMAP,LU)
	          ICOUNT=ICOUNT+1
	        END DO
	      ELSE IF (PRGFMAT.EQ.'R8') THEN
	        DO I=ISTART,IEND
	          DATADP(ICOUNT)=BSCALE(NMAP,LU)*R4REC(I)+
	1         BZERO(NMAP,LU)
	          ICOUNT=ICOUNT+1
	        END DO
	      END IF
	    ELSE IF (BITPIX(NMAP,LU).EQ.-64) THEN
	      IF (SYSTEM_ENDIAN.EQ.'L') THEN
	        CALL IEEE2UNIX64(I4X2REC,IBLKLEN/8,BSWAP,WSWAP)
	      END IF
	      IF (IRECSTART.EQ.IRECEND) THEN
	        ISTART=IBYTEOFFSET3/8+1
	        IEND=IBYTEOFFSET4/8+1
	      ELSE
	        IF (IR.EQ.IRECSTART) THEN
	          ISTART=IBYTEOFFSET3/8+1
	          IEND=IBLKLEN/8
	        ELSE IF (IR.EQ.IRECEND) THEN
	          ISTART=1
	          IEND=IBYTEOFFSET4/8+1
	        ELSE
	          ISTART=1
	          IEND=IBLKLEN/8
	        END IF
	      END IF
	      IF (PRGFMAT.EQ.'R4') THEN
	        DO I=ISTART,IEND
	          DATA(ICOUNT)=BSCALE(NMAP,LU)*R8REC(I)+
	1         BZERO(NMAP,LU)
	          ICOUNT=ICOUNT+1
	        END DO
	      ELSE IF (PRGFMAT.EQ.'R8') THEN
	        DO I=ISTART,IEND
	          DATADP(ICOUNT)=BSCALE(NMAP,LU)*R8REC(I)+
	1         BZERO(NMAP,LU)
	          ICOUNT=ICOUNT+1
	        END DO
	      END IF
	    END IF
	  END DO
	END IF
C
	IF (CALL.EQ.'WRIT') THEN
	  ICOUNT=1
	  DO IR=IRECSTART,IRECEND
	    READ(LU,REC=IR,IOSTAT=ISTAT) (PHYSREC(I),I=1,IBLKLEN)
	    IF (BITPIX(NMAP,LU).EQ.8) THEN
	      IF (IRECSTART.EQ.IRECEND) THEN
	        ISTART=IBYTEOFFSET3+1
	        IEND=IBYTEOFFSET4+1
	      ELSE
	        IF (IR.EQ.IRECSTART) THEN
	          ISTART=IBYTEOFFSET3+1
	          IEND=IBLKLEN
	        ELSE IF (IR.EQ.IRECEND) THEN
	          ISTART=1
	          IEND=IBYTEOFFSET4+1
	        ELSE
	          ISTART=1
	          IEND=IBLKLEN
	        END IF
	      END IF
	      IF (PRGFMAT.EQ.'R4') THEN
	        DO I=ISTART,IEND
	          PHYSREC(I)=NINT((DATA(ICOUNT)-BZERO(NMAP,LU))/
	1         BSCALE(NMAP,LU))
	          ICOUNT=ICOUNT+1
	        END DO
	      ELSE IF (PRGFMAT.EQ.'R8') THEN
	        DO I=ISTART,IEND
	          PHYSREC(I)=NINT((DATADP(ICOUNT)-BZERO(NMAP,LU))/
	1         BSCALE(NMAP,LU))
	          ICOUNT=ICOUNT+1
	        END DO
	      END IF
	    ELSE IF (BITPIX(NMAP,LU).EQ.16) THEN
	      IF (SYSTEM_ENDIAN.EQ.'L') THEN
	        CALL IBMI2(I2REC,I2REC,IBLKLEN/2)
	      END IF
	      IF (IRECSTART.EQ.IRECEND) THEN
	        ISTART=IBYTEOFFSET3/2+1
	        IEND=IBYTEOFFSET4/2+1
	      ELSE
	        IF (IR.EQ.IRECSTART) THEN
	          ISTART=IBYTEOFFSET3/2+1
	          IEND=IBLKLEN/2
	        ELSE IF (IR.EQ.IRECEND) THEN
	          ISTART=1
	          IEND=IBYTEOFFSET4/2+1
	        ELSE
	          ISTART=1
	          IEND=IBLKLEN/2
	        END IF
	      END IF
	      IF (PRGFMAT.EQ.'R4') THEN
	        DO I=ISTART,IEND
	          I2REC(I)=NINT((DATA(ICOUNT)-BZERO(NMAP,LU))/
	1         BSCALE(NMAP,LU))
	          ICOUNT=ICOUNT+1
	        END DO
	      ELSE IF (PRGFMAT.EQ.'R8') THEN
	        DO I=ISTART,IEND
	          I2REC(I)=NINT((DATADP(ICOUNT)-BZERO(NMAP,LU))/
	1         BSCALE(NMAP,LU))
	          ICOUNT=ICOUNT+1
	        END DO
	      END IF
	      IF (SYSTEM_ENDIAN.EQ.'L') THEN
	        CALL IBMI2(I2REC,I2REC,IBLKLEN/2) !  Restores the order
	      END IF
	    ELSE IF (BITPIX(NMAP,LU).EQ.32) THEN
	      IF (SYSTEM_ENDIAN.EQ.'L') THEN
	        CALL IBMI4(I4REC,I4REC,IBLKLEN/4)
	      END IF
	      IF (IRECSTART.EQ.IRECEND) THEN
	        ISTART=IBYTEOFFSET3/4+1
	        IEND=IBYTEOFFSET4/4+1
	      ELSE
	        IF (IR.EQ.IRECSTART) THEN
	          ISTART=IBYTEOFFSET3/4+1
	          IEND=IBLKLEN/4
	        ELSE IF (IR.EQ.IRECEND) THEN
	          ISTART=1
	          IEND=IBYTEOFFSET4/4+1
	        ELSE
	          ISTART=1
	          IEND=IBLKLEN/4
	        END IF
	      END IF
	      IF (PRGFMAT.EQ.'R4') THEN
	        DO I=ISTART,IEND
	          I4REC(I)=NINT((DATA(ICOUNT)-BZERO(NMAP,LU))/
	1         BSCALE(NMAP,LU))
	          ICOUNT=ICOUNT+1
	        END DO
	      ELSE IF (PRGFMAT.EQ.'R8') THEN
	        DO I=ISTART,IEND
	          I4REC(I)=NINT((DATADP(ICOUNT)-BZERO(NMAP,LU))/
	1         BSCALE(NMAP,LU))
	          ICOUNT=ICOUNT+1
	        END DO
	      END IF
	      IF (SYSTEM_ENDIAN.EQ.'L') THEN
	        CALL IBMI4(I4REC,I4REC,IBLKLEN/4)
	      END IF
	    ELSE IF (BITPIX(NMAP,LU).EQ.-32) THEN
	      IF (SYSTEM_ENDIAN.EQ.'L') THEN
	        CALL IEEE2UNIX(I4REC,IBLKLEN/4,BSWAP,WSWAP)
	      END IF
	      IF (IRECSTART.EQ.IRECEND) THEN
	        ISTART=IBYTEOFFSET3/4+1
	        IEND=IBYTEOFFSET4/4+1
	      ELSE
	        IF (IR.EQ.IRECSTART) THEN
	          ISTART=IBYTEOFFSET3/4+1
	          IEND=IBLKLEN/4
	        ELSE IF (IR.EQ.IRECEND) THEN
	          ISTART=1
	          IEND=IBYTEOFFSET4/4+1
	        ELSE
	          ISTART=1
	          IEND=IBLKLEN/4
	        END IF
	      END IF
	      IF (PRGFMAT.EQ.'R4') THEN
	        DO I=ISTART,IEND
	          R4REC(I)=(DATA(ICOUNT)-BZERO(NMAP,LU))/
	1         BSCALE(NMAP,LU)
	          ICOUNT=ICOUNT+1
	        END DO
	      ELSE IF (PRGFMAT.EQ.'R8') THEN
	        DO I=ISTART,IEND
	          R4REC(I)=(DATADP(ICOUNT)-BZERO(NMAP,LU))/
	1         BSCALE(NMAP,LU)
	          ICOUNT=ICOUNT+1
	        END DO
	      END IF
	      IF (SYSTEM_ENDIAN.EQ.'L') THEN
	        CALL UNIX2IEEE(I4REC,IBLKLEN/4,BSWAP,WSWAP)
	      END IF
	    ELSE IF (BITPIX(NMAP,LU).EQ.-64) THEN
	      IF (SYSTEM_ENDIAN.EQ.'L') THEN
	        CALL IEEE2UNIX64(I4X2REC,IBLKLEN/8,BSWAP,WSWAP)
	      END IF
	      IF (IRECSTART.EQ.IRECEND) THEN
	        ISTART=IBYTEOFFSET3/8+1
	        IEND=IBYTEOFFSET4/8+1
	      ELSE
	        IF (IR.EQ.IRECSTART) THEN
	          ISTART=IBYTEOFFSET3/8+1
	          IEND=IBLKLEN/8
	        ELSE IF (IR.EQ.IRECEND) THEN
	          ISTART=1
	          IEND=IBYTEOFFSET4/8+1
	        ELSE
	          ISTART=1
	          IEND=IBLKLEN/8
	        END IF
	      END IF
	      IF (PRGFMAT.EQ.'R4') THEN
	        DO I=ISTART,IEND
	          R8REC(I)=(DATA(ICOUNT)-BZERO(NMAP,LU))/
	1         BSCALE(NMAP,LU)
	          ICOUNT=ICOUNT+1
	        END DO
	      ELSE IF (PRGFMAT.EQ.'R8') THEN
	        DO I=ISTART,IEND
	          R8REC(I)=(DATADP(ICOUNT)-BZERO(NMAP,LU))/
	1         BSCALE(NMAP,LU)
	          ICOUNT=ICOUNT+1
	        END DO
	      END IF
	      IF (SYSTEM_ENDIAN.EQ.'L') THEN
	        CALL UNIX2IEEE64(I4X2REC,IBLKLEN/8,BSWAP,WSWAP)
	      END IF
	    END IF
C  Now write the record back
	    WRITE(LU,REC=IR,IOSTAT=ISTAT) (PHYSREC(I),I=1,IBLKLEN)
	  END DO
	END IF
C	
	RETURN
	END
